[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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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. """
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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')"),
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user