[MIG] stock_calendar: new API
This commit is contained in:
@@ -1,77 +1,69 @@
|
||||
from datetime import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from openerp import api
|
||||
from openerp.osv import fields, osv
|
||||
from openerp.tools.translate import _
|
||||
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT, DEFAULT_SERVER_DATE_FORMAT
|
||||
from openerp import SUPERUSER_ID
|
||||
from psycopg2 import OperationalError
|
||||
from openerp.tools import float_compare, float_round
|
||||
import pytz
|
||||
import openerp
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
class procurement_order(osv.osv):
|
||||
from datetime import datetime
|
||||
|
||||
from odoo import api, fields, models
|
||||
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
|
||||
|
||||
|
||||
class ProcurementOrder(models.Model):
|
||||
_inherit = 'procurement.order'
|
||||
|
||||
_columns = {
|
||||
'next_delivery_date': fields.datetime('Next Delivery Date',
|
||||
help="The date of the next delivery for this procurement group, when this group is on the purchase calendar of the orderpoint"),
|
||||
'next_purchase_date': fields.datetime('Next Purchase Date',
|
||||
help="The date the next purchase order should be sent to the vendor"),
|
||||
}
|
||||
next_delivery_date = fields.Datetime('Next Delivery Date', help="The date of the next delivery for this procurement group, when this group is on the purchase calendar of the orderpoint")
|
||||
next_purchase_date = fields.Datetime('Next Purchase Date', help="The date the next purchase order should be sent to the vendor")
|
||||
|
||||
def assign_group_date(self, cr, uid, ids, context=None):
|
||||
orderpoint_obj = self.pool.get("stock.warehouse.orderpoint")
|
||||
for procurement in self.browse(cr, uid, ids, context=context):
|
||||
ops = orderpoint_obj.search(cr, uid, [('location_id', '=', procurement.location_id.id),
|
||||
('product_id', '=', procurement.product_id.id)], context=context)
|
||||
if ops and ops[0]:
|
||||
orderpoint = orderpoint_obj.browse(cr, uid, ops[0], context=context)
|
||||
date_planned = datetime.strptime(procurement.date_planned, DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
purchase_date, delivery_date = self.pool['stock.orderpoint']._get_previous_dates(cr, uid, [orderpoint.id], date_planned, context=context)
|
||||
@api.multi
|
||||
def assign_group_date(self):
|
||||
Orderpoint = self.env["stock.warehouse.orderpoint"]
|
||||
for procurement in self:
|
||||
orderpoint = Orderpoint.search([
|
||||
('location_id', '=', procurement.location_id.id),
|
||||
('product_id', '=', procurement.product_id.id)], limit=1)
|
||||
if orderpoint:
|
||||
date_planned = fields.Datetime.from_string(procurement.date_planned)
|
||||
purchase_date, delivery_date = orderpoint._get_previous_dates(date_planned)
|
||||
if purchase_date and delivery_date:
|
||||
self.write(cr, uid, [procurement.id], {'next_delivery_date': delivery_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
|
||||
'next_purchase_date': purchase_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT),}, context=context)
|
||||
procurement.write({
|
||||
'next_delivery_date': delivery_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT),
|
||||
'next_purchase_date': purchase_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT)})
|
||||
|
||||
def _get_purchase_order_date(self, schedule_date):
|
||||
if self.next_purchase_date:
|
||||
return datetime.strptime(self.next_purchase_date, DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
return super(procurement_order, self)._get_purchase_order_date(schedule_date)
|
||||
return fields.Datetime.from_string(self.next_purchase_date)
|
||||
return super(ProcurementOrder, self)._get_purchase_order_date(schedule_date)
|
||||
|
||||
def _get_purchase_schedule_date(self):
|
||||
if self.next_delivery_date:
|
||||
return datetime.strptime(self.next_delivery_date, DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
return super(procurement_order, self)._get_purchase_schedule_date()
|
||||
return super(ProcurementOrder, self)._get_purchase_schedule_date()
|
||||
|
||||
def _prepare_purchase_order_line(self, cr, uid, ids, po, supplier, context=None):
|
||||
res = super(procurement_order, self)._prepare_purchase_order_line(cr, uid, ids, po, supplier, context=context)
|
||||
procurement = self.browse(cr, uid, ids, context=context)
|
||||
if procurement.next_delivery_date:
|
||||
res.update({'date_planned': procurement.next_delivery_date})
|
||||
def _prepare_purchase_order_line(self, po, supplier):
|
||||
res = super(ProcurementOrder, self)._prepare_purchase_order_line(po, supplier)
|
||||
if self.next_delivery_date:
|
||||
res.update({'date_planned': self.next_delivery_date})
|
||||
return res
|
||||
|
||||
def _procurement_from_orderpoint_get_order(self, cr, uid, context=None):
|
||||
def _procurement_from_orderpoint_get_order(self):
|
||||
return 'location_id, purchase_calendar_id, calendar_id'
|
||||
|
||||
def _procurement_from_orderpoint_get_grouping_key(self, cr, uid, orderpoint_ids, context=None):
|
||||
orderpoint = self.pool['stock.warehouse.orderpoint'].browse(cr, uid, orderpoint_ids[0], context=context)
|
||||
def _procurement_from_orderpoint_get_grouping_key(self, orderpoint_ids):
|
||||
orderpoint = self.env['stock.warehouse.orderpoint'].browse(orderpoint_ids[0])
|
||||
return (orderpoint.location_id.id, orderpoint.purchase_calendar_id.id, orderpoint.calendar_id.id)
|
||||
|
||||
def _procurement_from_orderpoint_get_groups(self, cr, uid, orderpoint_ids, context=None):
|
||||
orderpoint = self.pool['stock.warehouse.orderpoint'].browse(cr, uid, orderpoint_ids[0], context=context)
|
||||
def _procurement_from_orderpoint_get_groups(self, orderpoint_ids):
|
||||
orderpoint = self.env['stock.warehouse.orderpoint'].browse(orderpoint_ids[0])
|
||||
res_groups = []
|
||||
date_groups = self._get_group(cr, uid, [orderpoint.id], context=context)
|
||||
date_groups = orderpoint._get_group()
|
||||
for date, group in date_groups:
|
||||
if orderpoint.calendar_id and orderpoint.calendar_id.attendance_ids:
|
||||
date1, date2 = self._get_next_dates(cr, uid, [orderpoint.id], date, group, context=context)
|
||||
date1, date2 = orderpoint._get_next_dates(date, group)
|
||||
res_groups += [{'to_date': date2, 'procurement_values': {'group': group, 'date': date1, 'purchase_date': date}}] # date1/date2 as deliveries and date as purchase confirmation date
|
||||
else:
|
||||
res_groups += [{'to_date': False, 'procurement_values': {'group': group, 'date': date, 'purchase_date': date}}]
|
||||
return res_groups
|
||||
|
||||
def _procurement_from_orderpoint_post_process(self, cr, uid, orderpoint_ids, context=None):
|
||||
self.pool['stock.warehouse.orderpoint'].write(
|
||||
cr, uid, orderpoint_ids, {
|
||||
'last_execution_date': datetime.utcnow().strftime(DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
}, context=context)
|
||||
return super(procurement_order, self)._procurement_from_orderpoint_post_process(cr, uid, orderpoint_ids, context=context)
|
||||
def _procurement_from_orderpoint_post_process(self, orderpoint_ids):
|
||||
self.env['stock.warehouse.orderpoint'].browse(orderpoint_ids).write({
|
||||
'last_execution_date': datetime.utcnow().strftime(DEFAULT_SERVER_DATETIME_FORMAT)})
|
||||
return super(ProcurementOrder, self)._procurement_from_orderpoint_post_process(orderpoint_ids)
|
||||
|
||||
@@ -1,16 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import datetime
|
||||
|
||||
from openerp.osv import fields, osv
|
||||
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT, DEFAULT_SERVER_DATE_FORMAT
|
||||
from odoo import api, fields, models
|
||||
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT, DEFAULT_SERVER_DATE_FORMAT
|
||||
|
||||
|
||||
class resource_calendar_leaves(osv.osv):
|
||||
class ResourceCalendarAttendance(models.Model):
|
||||
_inherit = "resource.calendar.attendance"
|
||||
|
||||
group_id = fields.Many2one('procurement.group', 'Procurement Group')
|
||||
|
||||
|
||||
class ResourceCalendarLeaves(models.Model):
|
||||
_inherit = "resource.calendar.leaves"
|
||||
_columns = {
|
||||
'group_id': fields.many2one('procurement.group', string="Procurement Group"),
|
||||
}
|
||||
|
||||
class resource_calendar(osv.osv):
|
||||
group_id = fields.Many2one('procurement.group', 'Procurement Group')
|
||||
|
||||
|
||||
class ResourceCalendar(models.Model):
|
||||
_inherit = "resource.calendar"
|
||||
|
||||
# Keep as it takes into account times
|
||||
@@ -32,6 +41,8 @@ class resource_calendar(osv.osv):
|
||||
:return list leaves: list of tuples (start_datetime, end_datetime) of
|
||||
leave intervals
|
||||
"""
|
||||
# TDE FIXME: waw, overriding completely a method + changing its result
|
||||
# and its behavior, very nice. Please FIXME.
|
||||
resource_calendar = self.browse(cr, uid, id, context=context)
|
||||
leaves = []
|
||||
for leave in resource_calendar.leave_ids:
|
||||
@@ -75,6 +86,8 @@ class resource_calendar(osv.osv):
|
||||
that are intervals to remove from the base interval
|
||||
:return list intervals: a list of tuples (begin datetime, end datetime)
|
||||
that are the remaining valid intervals """
|
||||
# TDE FIXME: waw, overriding completely a method + changing its result
|
||||
# and its behavior, very nice. Please FIXME.
|
||||
if not interval:
|
||||
return interval
|
||||
if leave_intervals is None:
|
||||
@@ -109,11 +122,3 @@ class resource_calendar(osv.osv):
|
||||
else:
|
||||
intervals.append((current_interval[0], current_interval[1],))
|
||||
return intervals
|
||||
|
||||
|
||||
class resource_calendar_attendance(osv.osv):
|
||||
_inherit = "resource.calendar.attendance"
|
||||
|
||||
_columns = {
|
||||
'group_id': fields.many2one('procurement.group', 'Procurement Group'),
|
||||
}
|
||||
|
||||
@@ -1,28 +1,31 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from datetime import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
from openerp.osv import fields, osv
|
||||
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT, DEFAULT_SERVER_DATE_FORMAT
|
||||
from odoo import fields, models
|
||||
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
|
||||
|
||||
|
||||
class stock_warehouse_orderpoint(osv.osv):
|
||||
class StockWarehouseOrderpoint(models.Model):
|
||||
_inherit = "stock.warehouse.orderpoint"
|
||||
|
||||
_columns = {
|
||||
'calendar_id': fields.many2one('resource.calendar', 'Calendar',
|
||||
help="In the calendar you can define the days that the goods will be delivered. That way the scheduler will only take into account the goods needed until the second delivery and put the procurement date as the first delivery. "),
|
||||
'purchase_calendar_id': fields.many2one('resource.calendar', 'Purchase Calendar'),
|
||||
'last_execution_date': fields.datetime('Last Execution Date', readonly=True),
|
||||
}
|
||||
calendar_id = fields.Many2one(
|
||||
'resource.calendar', 'Calendar',
|
||||
help="In the calendar you can define the days that the goods will be delivered. That way the scheduler will "
|
||||
"only take into account the goods needed until the second delivery and put the procurement date as the first delivery.")
|
||||
purchase_calendar_id = fields.Many2one('resource.calendar', 'Purchase Calendar')
|
||||
last_execution_date = fields.Datetime('Last Execution Date', readonly=True)
|
||||
|
||||
def _prepare_procurement_values(self, cr, uid, ids, product_qty, date=False, purchase_date=False, group=False, context=None):
|
||||
res = super(stock_warehouse_orderpoint, self)._prepare_procurement_values(cr, uid, ids, product_qty, date=date, group=group, context=context)
|
||||
def _prepare_procurement_values(self, product_qty, date=False, purchase_date=False, group=False):
|
||||
res = super(StockWarehouseOrderpoint, self)._prepare_procurement_values(product_qty, date=date, group=group)
|
||||
res.update({
|
||||
'next_delivery_date': date,
|
||||
'next_purchase_date': purchase_date})
|
||||
return res
|
||||
|
||||
def _get_group(self, cr, uid, ids, context=None):
|
||||
def _get_group(self):
|
||||
"""
|
||||
Will return the groups and the end dates of the intervals of the purchase calendar
|
||||
that need to be executed now.
|
||||
@@ -30,55 +33,52 @@ class stock_warehouse_orderpoint(osv.osv):
|
||||
:return [(date, group)]
|
||||
"""
|
||||
# TDE FIXME: unused context key 'no_round_hours' removed
|
||||
orderpoint = self.browse(cr, uid, ids, context=context)[0]
|
||||
# Check if orderpoint has last execution date and calculate if we need to calculate again already
|
||||
calendar_obj = self.pool.get("resource.calendar")
|
||||
att_obj = self.pool.get("resource.calendar.attendance")
|
||||
Calendar = self.env["resource.calendar"]
|
||||
Attendance = self.env["resource.calendar.attendance"]
|
||||
group = False
|
||||
date = False
|
||||
now_date = datetime.utcnow()
|
||||
res_intervals = []
|
||||
if orderpoint.purchase_calendar_id and orderpoint.purchase_calendar_id.attendance_ids:
|
||||
if orderpoint.last_execution_date:
|
||||
new_date = datetime.strptime(orderpoint.last_execution_date, DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
if self.purchase_calendar_id and self.purchase_calendar_id.attendance_ids:
|
||||
if self.last_execution_date:
|
||||
new_date = datetime.strptime(self.last_execution_date, DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
else:
|
||||
new_date = datetime.utcnow()
|
||||
# TDE note: I bet accessing interval[2] will crash, no ? this code seems very louche
|
||||
intervals = calendar_obj._schedule_days(cr, uid, orderpoint.purchase_calendar_id.id, 1, new_date, compute_leaves=True, context=context)
|
||||
intervals = Calendar._schedule_days(self.purchase_calendar_id.id, 1, new_date, compute_leaves=True)
|
||||
for interval in intervals:
|
||||
# If last execution date, interval should start after it in order not to execute the same orderpoint twice
|
||||
# TODO: Make the interval a little bigger
|
||||
if (orderpoint.last_execution_date and (interval[0] > new_date and interval[0] < now_date)) or (not orderpoint.last_execution_date and interval[0] < now_date and interval[1] > now_date):
|
||||
group = att_obj.browse(cr, uid, interval[2], context=context).group_id.id
|
||||
if (self.last_execution_date and (interval[0] > new_date and interval[0] < now_date)) or (not self.last_execution_date and interval[0] < now_date and interval[1] > now_date):
|
||||
group = Attendance.browse(interval[2]).group_id.id
|
||||
date = interval[1]
|
||||
res_intervals += [(date, group), ]
|
||||
else:
|
||||
return [(now_date, None)]
|
||||
return res_intervals
|
||||
|
||||
def _get_previous_dates(self, cr, uid, ids, start_date=False, context=None):
|
||||
def _get_previous_dates(self, start_date=False):
|
||||
"""
|
||||
Date should be given in utc
|
||||
"""
|
||||
# TDE FIXME: unused context key 'no_round_hours' removed
|
||||
orderpoint = self.browse(cr, uid, ids, context=context)[0]
|
||||
calendar_obj = self.pool.get('resource.calendar')
|
||||
att_obj = self.pool.get('resource.calendar.attendance')
|
||||
Attendance = self.env["resource.calendar.attendance"]
|
||||
# First check if the orderpoint has a Calendar as it should be delivered at this calendar date
|
||||
purchase_date = False
|
||||
delivery_date = start_date
|
||||
if orderpoint.calendar_id and orderpoint.calendar_id.attendance_ids:
|
||||
res = calendar_obj._schedule_days(cr, uid, orderpoint.calendar_id.id, -1, start_date, compute_leaves=True, context=context)
|
||||
if self.calendar_id and self.calendar_id.attendance_ids:
|
||||
res = self.calendar_id._schedule_days(-1, start_date, compute_leaves=True)[0] # CLEANME
|
||||
if res and res[0][0] < start_date:
|
||||
group_to_find = res[0][2] and att_obj.browse(cr, uid, res[0][2], context=context).group_id.id or False
|
||||
group_to_find = res[0][2] and Attendance.browse(res[0][2]).group_id.id
|
||||
delivery_date = res[0][0]
|
||||
found_date = delivery_date
|
||||
if orderpoint.purchase_calendar_id and orderpoint.purchase_calendar_id.attendance_ids:
|
||||
if self.purchase_calendar_id and self.purchase_calendar_id.attendance_ids:
|
||||
while not purchase_date:
|
||||
found_date = found_date + relativedelta(days=-1) # won't allow to deliver within the day
|
||||
res = calendar_obj._schedule_days(cr, uid, orderpoint.purchase_calendar_id.id, -1, found_date, compute_leaves=True, context=context)
|
||||
found_date = found_date + relativedelta(days=-1) # won't allow to deliver within the day
|
||||
res = self.purchase_calendar_id._schedule_days(-1, found_date, compute_leaves=True)[0] # CLEANME
|
||||
for re in res:
|
||||
group = re[2] and att_obj.browse(cr, uid, re[2], context=context).group_id.id or False
|
||||
group = re[2] and Attendance.browse(re[2]).group_id.id
|
||||
found_date = re[0]
|
||||
if not purchase_date and (group_to_find and group_to_find == group or (not group_to_find)):
|
||||
purchase_date = re[0]
|
||||
@@ -86,26 +86,24 @@ class stock_warehouse_orderpoint(osv.osv):
|
||||
delivery_date = start_date or datetime.utcnow()
|
||||
return purchase_date, delivery_date
|
||||
|
||||
def _get_next_dates(self, cr, uid, ids, new_date=False, group=False, context=None):
|
||||
def _get_next_dates(self, new_date=False, group=False):
|
||||
# TDE FIXME: unused context key 'no_round_hours' removed
|
||||
orderpoint = self.browse(cr, uid, ids, context=context)[0]
|
||||
calendar_obj = self.pool.get('resource.calendar')
|
||||
att_obj = self.pool.get('resource.calendar.attendance')
|
||||
Attendance = self.env["resource.calendar.attendance"]
|
||||
if not new_date:
|
||||
new_date = datetime.utcnow()
|
||||
now_date = datetime.utcnow()
|
||||
|
||||
# Search first calendar day (without group)
|
||||
res = calendar_obj._schedule_days(cr, uid, orderpoint.calendar_id.id, 1, new_date, compute_leaves=True, context=context)
|
||||
att_group = res and res[0][2] and att_obj.browse(cr, uid, res[0][2], context=context).group_id.id or False
|
||||
#If hours are smaller than the current date, search a day further
|
||||
res = self.calendar_id._schedule_days(1, new_date, compute_leaves=True)[0] # CLEANME
|
||||
att_group = res and res[0][2] and Attendance.browse(res[0][2]).group_id.id
|
||||
# If hours are smaller than the current date, search a day further
|
||||
if res and res[0][0] < now_date:
|
||||
new_date = res[0][1] + relativedelta(days=1)
|
||||
res = calendar_obj._schedule_days(cr, uid, orderpoint.calendar_id.id, 1, new_date, compute_leaves=True, context=context)
|
||||
res = self.calendar_id._schedule_days(1, new_date, compute_leaves=True)
|
||||
for re in res:
|
||||
att_group = False
|
||||
if re[2]:
|
||||
att_group = att_obj.browse(cr, uid, re[2], context=context).group_id.id
|
||||
att_group = Attendance.browse(re[2]).group_id.id
|
||||
if att_group == group:
|
||||
break
|
||||
|
||||
@@ -114,14 +112,14 @@ class stock_warehouse_orderpoint(osv.osv):
|
||||
while res and group and att_group != group and number < 100:
|
||||
number += 1
|
||||
new_date = res[0][1] + relativedelta(days=1)
|
||||
res = calendar_obj._schedule_days(cr, uid, orderpoint.calendar_id.id, 1, new_date, compute_leaves=True, context=context)
|
||||
res = self.calendar_id._schedule_days(1, new_date, compute_leaves=True)[0]
|
||||
att_group = False
|
||||
for re in res:
|
||||
if re[2]:
|
||||
att_group = att_obj.browse(cr, uid, re[2], context=context).group_id.id
|
||||
att_group = Attendance.browse(re[2]).group_id.id
|
||||
if att_group == group:
|
||||
break
|
||||
#number as safety pall for endless loops
|
||||
# number as safety pall for endless loops
|
||||
if number >= 100:
|
||||
res = False
|
||||
|
||||
@@ -130,7 +128,7 @@ class stock_warehouse_orderpoint(osv.osv):
|
||||
if res:
|
||||
date1 = res[0][1]
|
||||
new_date = res[0][1] + relativedelta(days=1)
|
||||
res = calendar_obj._schedule_days(cr, uid, orderpoint.calendar_id.id, 1, new_date, compute_leaves=True, context=context)
|
||||
res = self.calendar_id._schedule_days(1, new_date, compute_leaves=True)[0]
|
||||
if res:
|
||||
return (date1, res[0][1])
|
||||
return (False, False)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<odoo>
|
||||
<data>
|
||||
<record id="view_warehouse_orderpoint_form_inherit" model="ir.ui.view">
|
||||
<field name="name">stock.warehouse.orderpoint.form.inherit</field>
|
||||
@@ -13,4 +13,4 @@
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
</odoo>
|
||||
|
||||
Reference in New Issue
Block a user