[FIX] account: never set default for invoice_date

For customer invoices:
* do not set default date because if you prepare an invoice (and it gets
  a default date), then validate it the next day, the date will be wrong
* set the date when posting if it wasn't set, because why not?

For vendor bills:
* do not set default date because you rarely encode a bill at the bill
  date. Forcing the user to enter it reduces risks of user error
  (duplicated vendor bill)
* do not set it when posting, same reason.

opw-2492862
Related #68368
Closes #68367

closes odoo/odoo#69639

X-original-commit: 41041d8016d11f017d92d28f32ab2cf42f1349a9
Related: odoo/enterprise#17866
Signed-off-by: Laurent Smet <smetl@users.noreply.github.com>
Signed-off-by: William André (wan) <wan@odoo.com>
This commit is contained in:
wan
2021-04-22 08:16:08 +00:00
parent 0bc56aa7a2
commit 002f89bd84
13 changed files with 66 additions and 14 deletions
+6
View File
@@ -11561,6 +11561,12 @@ msgid ""
" for vendor/customer accounts."
msgstr ""
#. module: account
#: code:addons/account/models/account_move.py:0
#, python-format
msgid "The Bill/Refund date is required to validate this document."
msgstr ""
#. module: account
#: model:ir.model.fields,help:account.field_account_bank_statement__country_code
#: model:ir.model.fields,help:account.field_account_bank_statement_line__country_code
+14 -6
View File
@@ -113,8 +113,10 @@ class AccountMove(models.Model):
return journal
# TODO remove in master
@api.model
def _get_default_invoice_date(self):
warnings.warn("Method '_get_default_invoice_date()' is deprecated and has been removed.", DeprecationWarning)
return fields.Date.context_today(self) if self._context.get('default_move_type', 'entry') in self.get_purchase_types(include_receipts=True) else False
@api.model
@@ -274,8 +276,7 @@ class AccountMove(models.Model):
string='Salesperson',
default=lambda self: self.env.user)
invoice_date = fields.Date(string='Invoice/Bill Date', readonly=True, index=True, copy=False,
states={'draft': [('readonly', False)]},
default=_get_default_invoice_date)
states={'draft': [('readonly', False)]})
invoice_date_due = fields.Date(string='Due Date', readonly=True, index=True, copy=False,
states={'draft': [('readonly', False)]})
invoice_origin = fields.Char(string='Origin', readonly=True, tracking=True,
@@ -1668,7 +1669,11 @@ class AccountMove(models.Model):
duplicated_moves = self.browse([r[0] for r in self._cr.fetchall()])
if duplicated_moves:
raise ValidationError(_('Duplicated vendor reference detected. You probably encoded twice the same vendor bill/credit note:\n%s') % "\n".join(
duplicated_moves.mapped(lambda m: "%(partner)s - %(ref)s - %(date)s" % {'ref': m.ref, 'partner': m.partner_id.display_name, 'date': format_date(self.env, m.date)})
duplicated_moves.mapped(lambda m: "%(partner)s - %(ref)s - %(date)s" % {
'ref': m.ref,
'partner': m.partner_id.display_name,
'date': format_date(self.env, m.invoice_date),
})
))
def _check_balanced(self):
@@ -2515,9 +2520,12 @@ class AccountMove(models.Model):
# lines are recomputed accordingly.
# /!\ 'check_move_validity' must be there since the dynamic lines will be recomputed outside the 'onchange'
# environment.
if not move.invoice_date and move.is_invoice(include_receipts=True):
move.invoice_date = fields.Date.context_today(self)
move.with_context(check_move_validity=False)._onchange_invoice_date()
if not move.invoice_date:
if move.is_sale_document(include_receipts=True):
move.invoice_date = fields.Date.context_today(self)
move.with_context(check_move_validity=False)._onchange_invoice_date()
elif move.is_purchase_document(include_receipts=True):
raise UserError(_("The Bill/Refund date is required to validate this document."))
# When the accounting date is prior to the tax lock date, move it automatically to today.
# /!\ 'check_move_validity' must be there since the dynamic lines will be recomputed outside the 'onchange'
@@ -40,6 +40,7 @@ class TestProductMargin(AccountTestInvoicingCommon):
'invoice_line_ids': [(0, 0, {'product_id': ipad.id, 'quantity': 10.0, 'price_unit': 550.0})],
},
])
invoices.invoice_date = invoices[0].date
invoices.action_post()
result = ipad._compute_product_margin_fields_values()
@@ -39,6 +39,7 @@ class TestPurchaseOrderReport(AccountTestInvoicingCommon):
po.button_confirm()
f = Form(self.env['account.move'].with_context(default_move_type='in_invoice'))
f.invoice_date = f.date
f.partner_id = po.partner_id
f.purchase_id = po
invoice = f.save()
@@ -106,6 +106,7 @@ class TestPurchaseOrder(ValuationReconciliationTestCommon):
#After Receiving all products create vendor bill.
move_form = Form(self.env['account.move'].with_context(default_move_type='in_invoice'))
move_form.invoice_date = move_form.date
move_form.partner_id = self.partner_a
move_form.purchase_id = self.po
self.invoice = move_form.save()
@@ -136,6 +137,7 @@ class TestPurchaseOrder(ValuationReconciliationTestCommon):
self.assertEqual(self.po.order_line[0].qty_received, 3.0, 'Purchase: delivered quantity should be 3.0 instead of "%s" after picking return' % self.po.order_line[0].qty_received)
#Create vendor bill for refund qty
move_form = Form(self.env['account.move'].with_context(default_move_type='in_refund'))
move_form.invoice_date = move_form.date
move_form.partner_id = self.partner_a
move_form.purchase_id = self.po
self.invoice = move_form.save()
@@ -379,6 +379,7 @@ class TestStockValuationWithCOA(AccountTestInvoicingCommon):
receipt_po1.button_validate()
move_form = Form(self.env['account.move'].with_context(default_move_type='in_invoice'))
move_form.invoice_date = move_form.date
move_form.partner_id = self.partner_id
move_form.purchase_id = po1
invoice_po1 = move_form.save()
@@ -404,6 +405,7 @@ class TestStockValuationWithCOA(AccountTestInvoicingCommon):
receipt_po2.button_validate()
move_form = Form(self.env['account.move'].with_context(default_move_type='in_invoice'))
move_form.invoice_date = move_form.date
move_form.partner_id = self.partner_id
move_form.purchase_id = po2
invoice_po2 = move_form.save()
@@ -428,6 +430,7 @@ class TestStockValuationWithCOA(AccountTestInvoicingCommon):
# create a credit note for po2
move_form = Form(self.env['account.move'].with_context(default_move_type='in_refund'))
move_form.invoice_date = move_form.date
move_form.partner_id = self.partner_id
move_form.purchase_id = po2
with move_form.invoice_line_ids.edit(0) as line_form:
@@ -462,6 +465,7 @@ class TestStockValuationWithCOA(AccountTestInvoicingCommon):
# Create an invoice with a different price
move_form = Form(self.env['account.move'].with_context(default_move_type='in_invoice'))
move_form.invoice_date = move_form.date
move_form.partner_id = order.partner_id
move_form.purchase_id = order
with move_form.invoice_line_ids.edit(0) as line_form:
@@ -1211,6 +1215,7 @@ class TestStockValuationWithCOA(AccountTestInvoicingCommon):
# Create an invoice with a different price and a discount
invoice_form = Form(self.env['account.move'].with_context(default_move_type='in_invoice'))
invoice_form.invoice_date = invoice_form.date
invoice_form.purchase_id = order
with invoice_form.invoice_line_ids.edit(0) as line_form:
line_form.price_unit = 100.0
@@ -1257,6 +1262,7 @@ class TestStockValuationWithCOA(AccountTestInvoicingCommon):
# Create an invoice with a different price and a discount
invoice_form = Form(self.env['account.move'].with_context(default_move_type='in_invoice'))
invoice_form.invoice_date = invoice_form.date
invoice_form.purchase_id = order
with invoice_form.invoice_line_ids.edit(0) as line_form:
line_form.tax_ids.clear()
@@ -1303,6 +1309,7 @@ class TestStockValuationWithCOA(AccountTestInvoicingCommon):
# Create an invoice with a different price and a discount
invoice_form = Form(self.env['account.move'].with_context(default_move_type='in_invoice'))
invoice_form.invoice_date = invoice_form.date
invoice_form.purchase_id = order
with invoice_form.invoice_line_ids.edit(0) as line_form:
line_form.price_unit = 100.0
+6 -1
View File
@@ -26,7 +26,12 @@ class TestReInvoice(TestSaleCommon):
'pricelist_id': cls.company_data['default_pricelist'].id,
})
cls.AccountMove = cls.env['account.move'].with_context(default_move_type='in_invoice', mail_notrack=True, mail_create_nolog=True)
cls.AccountMove = cls.env['account.move'].with_context(
default_move_type='in_invoice',
default_invoice_date=cls.sale_order.date_order,
mail_notrack=True,
mail_create_nolog=True,
)
def test_at_cost(self):
""" Test vendor bill at cost for product based on ordered and delivered quantities. """
+1
View File
@@ -240,6 +240,7 @@ class TestSaleOrder(TestSaleCommon):
inv = self.env['account.move'].with_context(default_move_type='in_invoice').create({
'partner_id': self.partner_a.id,
'invoice_date': so.date_order,
'invoice_line_ids': [
(0, 0, {
'name': serv_cost.name,
+11 -6
View File
@@ -40,7 +40,12 @@ class TestReInvoice(TestCommonSaleTimesheet):
'pricelist_id': cls.company_data['default_pricelist'].id,
})
cls.Invoice = cls.env['account.move'].with_context(mail_notrack=True, mail_create_nolog=True)
cls.Invoice = cls.env['account.move'].with_context(
default_move_type='in_invoice',
default_invoice_date=cls.sale_order.date_order,
mail_notrack=True,
mail_create_nolog=True,
)
def test_at_cost(self):
""" Test vendor bill at cost for product based on ordered and delivered quantities. """
@@ -82,7 +87,7 @@ class TestReInvoice(TestCommonSaleTimesheet):
'company_id': self.company_data['company'].id,
})
move_form = Form(self.env['account.move'].with_context(default_move_type='in_invoice'))
move_form = Form(self.Invoice)
move_form.partner_id = self.partner_a
with move_form.line_ids.new() as line_form:
line_form.product_id = self.company_data['product_order_cost']
@@ -117,7 +122,7 @@ class TestReInvoice(TestCommonSaleTimesheet):
self.assertEqual(sale_order_line4.qty_delivered_method, 'analytic', "Delivered quantity of 'expense' SO line should be computed by analytic amount")
# create second invoice lines and validate it
move_form = Form(self.env['account.move'].with_context(default_move_type='in_invoice'))
move_form = Form(self.Invoice)
move_form.partner_id = self.partner_a
with move_form.line_ids.new() as line_form:
line_form.product_id = self.company_data['product_order_cost']
@@ -181,7 +186,7 @@ class TestReInvoice(TestCommonSaleTimesheet):
})
# create invoice lines and validate it
move_form = Form(self.env['account.move'].with_context(default_move_type='in_invoice'))
move_form = Form(self.Invoice)
move_form.partner_id = self.partner_a
with move_form.line_ids.new() as line_form:
line_form.product_id = self.company_data['product_delivery_sales_price']
@@ -216,7 +221,7 @@ class TestReInvoice(TestCommonSaleTimesheet):
self.assertEqual(sale_order_line4.qty_delivered_method, 'analytic', "Delivered quantity of 'expense' SO line 4 should be computed by analytic amount")
# create second invoice lines and validate it
move_form = Form(self.env['account.move'].with_context(default_move_type='in_invoice'))
move_form = Form(self.Invoice)
move_form.partner_id = self.partner_a
with move_form.line_ids.new() as line_form:
line_form.product_id = self.company_data['product_delivery_sales_price']
@@ -256,7 +261,7 @@ class TestReInvoice(TestCommonSaleTimesheet):
self.sale_order.action_confirm()
# create invoice lines and validate it
move_form = Form(self.env['account.move'].with_context(default_move_type='in_invoice'))
move_form = Form(self.Invoice)
move_form.partner_id = self.partner_a
with move_form.line_ids.new() as line_form:
line_form.product_id = self.company_data['product_order_no']
@@ -69,6 +69,7 @@ class TestStockValuation(ValuationReconciliationTestCommon):
move_form = Form(self.env['account.move'].with_context(default_move_type='in_invoice'))
move_form.partner_id = vendor1
move_form.purchase_id = self.purchase_order1
move_form.invoice_date = move_form.date
for i in range(len(self.purchase_order1.order_line)):
with move_form.invoice_line_ids.edit(i) as line_form:
line_form.tax_ids.clear()
@@ -355,6 +355,7 @@ class TestLandedCostsWithPurchaseAndInv(TestStockValuationLCCommon):
# Create an invoice with the same price
move_form = Form(self.env['account.move'].with_context(default_move_type='in_invoice'))
move_form.invoice_date = move_form.date
move_form.partner_id = order.partner_id
move_form.purchase_id = order
move = move_form.save()
@@ -65,7 +65,7 @@ class TestStockValuationLCCommon(TestStockLandedCostsCommon):
lc.compute_landed_cost()
lc.button_validate()
return lc
def _make_in_move(self, product, quantity, unit_cost=None, create_picking=False):
""" Helper to create and validate a receipt move.
"""
@@ -341,6 +341,7 @@ class TestStockValuationLCFIFOVB(TestStockValuationLCCommon):
# Create a vendor bill for the RFQ
action = rfq.action_create_invoice()
vb = self.env['account.move'].browse(action['res_id'])
vb.invoice_date = vb.date
vb.action_post()
input_aml = self._get_stock_input_move_lines()[-1]
@@ -353,6 +354,7 @@ class TestStockValuationLCFIFOVB(TestStockValuationLCCommon):
# Create a vendor bill for a landed cost product, post it and validate a landed cost
# linked to this vendor bill. LC; 1@50
lcvb = Form(self.env['account.move'].with_context(default_move_type='in_invoice'))
lcvb.invoice_date = lcvb.date
lcvb.partner_id = self.vendor2
with lcvb.invoice_line_ids.new() as inv_line:
inv_line.product_id = self.productlc1
@@ -429,6 +431,7 @@ class TestStockValuationLCFIFOVB(TestStockValuationLCCommon):
# Create a vendor bill for the RFQ and add to it the landed cost
vb = Form(self.env['account.move'].with_context(default_move_type='in_invoice'))
vb.partner_id = self.vendor1
vb.invoice_date = vb.date
with vb.invoice_line_ids.new() as inv_line:
inv_line.product_id = self.productlc1
inv_line.price_unit = 50
@@ -481,6 +484,7 @@ class TestStockValuationLCFIFOVB(TestStockValuationLCCommon):
# Create a vebdor bill for the RFQ
action = rfq.action_create_invoice()
vb = self.env['account.move'].browse(action['res_id'])
vb.invoice_date = vb.date
vb.action_post()
expense_aml = self._get_expense_move_lines()[-1]
@@ -495,6 +499,7 @@ class TestStockValuationLCFIFOVB(TestStockValuationLCCommon):
# linked to this vendor bill. LC; 1@50
lcvb = Form(self.env['account.move'].with_context(default_move_type='in_invoice'))
lcvb.partner_id = self.vendor2
lcvb.invoice_date = lcvb.date
with lcvb.invoice_line_ids.new() as inv_line:
inv_line.product_id = self.productlc1
inv_line.price_unit = 50
@@ -775,6 +775,15 @@ tour.stepUtils.openBuggerMenu("li.breadcrumb-item.active:contains('OP/')"),
position: 'bottom',
},
...tour.stepUtils.statusbarButtonsSteps('Create Bill', _t('go to Vendor Bills'), ".o_statusbar_status .btn.dropdown-toggle:contains('Purchase Order')"),
{
trigger: '.o_form_button_edit',
content: _t('Edit the vendor bill'),
extra_trigger: 'body.o_web_client:not(.oe_wait)',
}, {
trigger:".o_field_widget[name=invoice_date] input",
content: _t('Set the invoice date'),
run: "text 01/01/2020",
},
...tour.stepUtils.statusbarButtonsSteps('Confirm', _t("Try to send it to email"), ".o_statusbar_status .btn.dropdown-toggle:contains('Draft')"),
...tour.stepUtils.statusbarButtonsSteps('Register Payment', _t("Register Payment"), ".o_statusbar_status .btn.dropdown-toggle:contains('Posted')"),
{