diff --git a/addons/sale_order_dates/__openerp__.py b/addons/sale_order_dates/__openerp__.py
index 3fa9fba0ecf..1f4eb399dd8 100644
--- a/addons/sale_order_dates/__openerp__.py
+++ b/addons/sale_order_dates/__openerp__.py
@@ -22,7 +22,7 @@
{
'name': 'Dates on Sales Order',
- 'version': '1.0',
+ 'version': '1.1',
'category': 'Sales Management',
'description': """
Add additional date information to the sales order.
@@ -30,7 +30,7 @@ Add additional date information to the sales order.
You can add the following additional dates to a sales order:
------------------------------------------------------------
- * Requested Date
+ * Requested Date (will be used as the expected date on pickings)
* Commitment Date
* Effective Date
""",
@@ -40,7 +40,7 @@ You can add the following additional dates to a sales order:
'depends': ['sale_stock'],
'data': ['sale_order_dates_view.xml'],
'demo': [],
- 'test': [],
+ 'test': ['test/requested_date.yml'],
'installable': True,
'auto_install': False,
}
diff --git a/addons/sale_order_dates/i18n/sale_order_dates.pot b/addons/sale_order_dates/i18n/sale_order_dates.pot
index 8a45a8a46af..b34c1143ec0 100644
--- a/addons/sale_order_dates/i18n/sale_order_dates.pot
+++ b/addons/sale_order_dates/i18n/sale_order_dates.pot
@@ -32,12 +32,14 @@ msgstr ""
#. module: sale_order_dates
#: help:sale.order,effective_date:0
-msgid "Date on which picking is created."
+msgid "Date on which the first Delivery Order was created."
msgstr ""
#. module: sale_order_dates
#: help:sale.order,requested_date:0
-msgid "Date requested by the customer for the sale."
+msgid "Date by which the customer has requested the items to be delivered.\n"
+"When this Order gets confirmed, the Delivery Order's expected date will be computed based on this date and the Company's Security Delay.\n"
+"Leave this field empty if you want the Delivery Order to be processed as soon as possible. In that case the expected date will be computed using the default method: based on the Product Lead Times and the Company's Security Delay."
msgstr ""
#. module: sale_order_dates
@@ -52,6 +54,18 @@ msgstr ""
#. module: sale_order_dates
#: help:sale.order,commitment_date:0
-msgid "Committed date for delivery."
+msgid "Date by which the products are sure to be delivered. This is a date that you can promise to the customer, based on the Product Lead Times."
+msgstr ""
+
+#. module: sale_order_dates
+#: code:addons/sale_order_dates/sale_order_dates.py:90
+#, python-format
+msgid "Requested date is too soon!"
+msgstr ""
+
+#. module: sale_order_dates
+#: code:addons/sale_order_dates/sale_order_dates.py:91
+#, python-format
+msgid "The date requested by the customer is sooner than the commitment date. You may be unable to honor the customer's request."
msgstr ""
diff --git a/addons/sale_order_dates/sale_order_dates.py b/addons/sale_order_dates/sale_order_dates.py
index 64b939de088..f3ff971be9f 100644
--- a/addons/sale_order_dates/sale_order_dates.py
+++ b/addons/sale_order_dates/sale_order_dates.py
@@ -19,15 +19,37 @@
#
##############################################################################
-from datetime import datetime
-from dateutil.relativedelta import relativedelta
+from datetime import datetime, timedelta
from openerp.osv import fields, osv
+from openerp.tools.translate import _
+from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT
class sale_order_dates(osv.osv):
+ """Add several date fields to Sale Orders, computed or user-entered"""
_inherit = 'sale.order'
+ def copy(self, cr, uid, id, default=None, context=None):
+ """Don't copy the requested date along with the Sales Order"""
+ default = dict(default or {}, requested_date=False)
+ return super(sale_order_dates, self).copy(cr, uid, id, default=default,
+ context=context)
+
+ def _get_date_planned(self, cr, uid, order, line, start_date, context=None):
+ """Compute the expected date from the requested date, not the order date"""
+ if order and order.requested_date:
+ planned_str = self.date_to_datetime(cr, uid,
+ order.requested_date, context)
+ date_planned = datetime.strptime(planned_str,
+ DEFAULT_SERVER_DATETIME_FORMAT)
+ date_planned -= timedelta(days=order.company_id.security_lead)
+ return date_planned.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
+ return super(sale_order_dates, self)._get_date_planned(
+ cr, uid, order, line, start_date, context=context)
+
def _get_effective_date(self, cr, uid, ids, name, arg, context=None):
+ """Read the shipping date from the related packings"""
+ # TODO: would be better if it returned the date the picking was processed?
res = {}
dates_list = []
for order in self.browse(cr, uid, ids, context=context):
@@ -41,22 +63,57 @@ class sale_order_dates(osv.osv):
return res
def _get_commitment_date(self, cr, uid, ids, name, arg, context=None):
+ """Compute the commitment date"""
res = {}
dates_list = []
for order in self.browse(cr, uid, ids, context=context):
+ order_datetime_str = self.date_to_datetime(cr, uid, order.date_order,
+ context)
+ order_datetime = datetime.strptime(order_datetime_str,
+ DEFAULT_SERVER_DATETIME_FORMAT)
dates_list = []
for line in order.order_line:
- dt = datetime.strptime(order.date_order, '%Y-%m-%d') + relativedelta(days=line.delay or 0.0)
- dt_s = dt.strftime('%Y-%m-%d')
+ dt = order_datetime + timedelta(days=line.delay or 0.0)
+ dt_s = dt.strftime(DEFAULT_SERVER_DATE_FORMAT)
dates_list.append(dt_s)
if dates_list:
res[order.id] = min(dates_list)
return res
+ def onchange_requested_date(self, cr, uid, ids, requested_date,
+ commitment_date, context=None):
+ """Warn if the requested dates is sooner than the commitment date"""
+ if (requested_date and commitment_date
+ and requested_date < commitment_date):
+ return {'warning': {
+ 'title': _('Requested date is too soon!'),
+ 'message': _("The date requested by the customer is "
+ "sooner than the commitment date. You may be "
+ "unable to honor the customer's request.")
+ }
+ }
+ return {}
+
_columns = {
- 'commitment_date': fields.function(_get_commitment_date, store=True, type='date', string='Commitment Date', help="Committed date for delivery."),
- 'requested_date': fields.date('Requested Date', help="Date requested by the customer for the sale."),
- 'effective_date': fields.function(_get_effective_date, type='date', store=True, string='Effective Date',help="Date on which picking is created."),
+ 'commitment_date': fields.function(_get_commitment_date, store=True,
+ type='date', string='Commitment Date',
+ help="Date by which the products are sure to be delivered. This is "
+ "a date that you can promise to the customer, based on the "
+ "Product Lead Times."),
+ 'requested_date': fields.date('Requested Date',
+ readonly=True, states={'draft': [('readonly', False)]},
+ help="Date by which the customer has requested the items to be "
+ "delivered.\n"
+ "When this Order gets confirmed, the Delivery Order's "
+ "expected date will be computed based on this date and the "
+ "Company's Security Delay.\n"
+ "Leave this field empty if you want the Delivery Order to be "
+ "processed as soon as possible. In that case the expected "
+ "date will be computed using the default method: based on "
+ "the Product Lead Times and the Company's Security Delay."),
+ 'effective_date': fields.function(_get_effective_date, type='date',
+ store=True, string='Effective Date',
+ help="Date on which the first Delivery Order was created."),
}
diff --git a/addons/sale_order_dates/sale_order_dates_view.xml b/addons/sale_order_dates/sale_order_dates_view.xml
index 68419cd29bb..cc216ddd9b9 100644
--- a/addons/sale_order_dates/sale_order_dates_view.xml
+++ b/addons/sale_order_dates/sale_order_dates_view.xml
@@ -10,13 +10,23 @@
-
+
+
+ sale.order
+
+
+
+
+
+
+
+
diff --git a/addons/sale_order_dates/test/requested_date.yml b/addons/sale_order_dates/test/requested_date.yml
new file mode 100644
index 00000000000..d05191a4d99
--- /dev/null
+++ b/addons/sale_order_dates/test/requested_date.yml
@@ -0,0 +1,32 @@
+-
+ In order to test the Requested Date feature in Sale Orders in OpenERP,
+ I update a demo Sale Order with Requested Date on 2010-12-17
+-
+ !python {model: sale.order}: |
+ self.write(cr, uid, ref("sale.sale_order_6"), {'requested_date': '2010-07-12'})
+-
+ I confirm the Sale Order.
+-
+ !workflow {
+ model: sale.order, action: order_confirm,
+ ref: sale.sale_order_6
+ }
+-
+ I verify that the Procurements and Stock Moves have been generated with the
+ correct date
+-
+ !python {model: sale.order}: |
+ from datetime import datetime, timedelta
+ from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT
+
+ so = self.browse(cr, uid, ref("sale.sale_order_6"))
+ security_delay = timedelta(days=so.company_id.security_lead)
+ requested_date = datetime.strptime(
+ self.date_to_datetime(cr, uid, so.requested_date),
+ DEFAULT_SERVER_DATETIME_FORMAT)
+ right_date = (requested_date - security_delay).strftime(
+ DEFAULT_SERVER_DATETIME_FORMAT)
+ for line in so.order_line:
+ assert line.procurement_id, "No Procurement was created"
+ assert line.procurement_id.date_planned == right_date, "The planned date for the Procurement Order is wrong"
+ assert line.procurement_id.move_id.date_expected == right_date, "The expected date for the Stock Move is wrong"
diff --git a/addons/sale_stock/sale_stock.py b/addons/sale_stock/sale_stock.py
index 26d9d80f13e..f90aecac184 100644
--- a/addons/sale_stock/sale_stock.py
+++ b/addons/sale_stock/sale_stock.py
@@ -21,7 +21,6 @@
##############################################################################
from datetime import datetime, timedelta
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT, DATETIME_FORMATS_MAP, float_compare
-from dateutil.relativedelta import relativedelta
from openerp.osv import fields, osv
from openerp.tools.translate import _
import pytz
@@ -257,7 +256,7 @@ class sale_order(osv.osv):
if tz_name:
utc = pytz.timezone('UTC')
context_tz = pytz.timezone(tz_name)
- user_datetime = user_date + relativedelta(hours=12.0)
+ user_datetime = user_date + timedelta(hours=12.0)
local_timestamp = context_tz.localize(user_datetime, is_dst=False)
user_datetime = local_timestamp.astimezone(utc)
return user_datetime.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
@@ -379,8 +378,9 @@ class sale_order(osv.osv):
return True
def _get_date_planned(self, cr, uid, order, line, start_date, context=None):
+ """Compute the Stock Move date for the Sale Order Line"""
start_date = self.date_to_datetime(cr, uid, start_date, context)
- date_planned = datetime.strptime(start_date, DEFAULT_SERVER_DATETIME_FORMAT) + relativedelta(days=line.delay or 0.0)
+ date_planned = datetime.strptime(start_date, DEFAULT_SERVER_DATETIME_FORMAT) + timedelta(days=line.delay or 0.0)
date_planned = (date_planned - timedelta(days=order.company_id.security_lead)).strftime(DEFAULT_SERVER_DATETIME_FORMAT)
return date_planned