Skip to content

Commit

Permalink
[FIX] account: never set default for invoice_date
Browse files Browse the repository at this point in the history
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 #68689

Related: odoo/enterprise#17502
Signed-off-by: Laurent Smet <smetl@users.noreply.github.com>
  • Loading branch information
william-andre committed Apr 12, 2021
1 parent 14abcfa commit fcaa549
Show file tree
Hide file tree
Showing 13 changed files with 66 additions and 14 deletions.
6 changes: 6 additions & 0 deletions addons/account/i18n/account.pot
Original file line number Diff line number Diff line change
Expand Up @@ -11474,6 +11474,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
Expand Down
20 changes: 14 additions & 6 deletions addons/account/models/account_move.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,10 @@ def _get_default_journal(self):

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
Expand Down Expand Up @@ -264,8 +266,7 @@ def _get_default_invoice_incoterm(self):
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,
Expand Down Expand Up @@ -1652,7 +1653,11 @@ def _check_duplicate_supplier_reference(self):
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):
Expand Down Expand Up @@ -2449,9 +2454,12 @@ def _post(self, soft=True):
# 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 the next available date.
# /!\ 'check_move_validity' must be there since the dynamic lines will be recomputed outside the 'onchange'
Expand Down
1 change: 1 addition & 0 deletions addons/product_margin/tests/test_product_margin.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ def test_product_margin(self):
'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()
Expand Down
1 change: 1 addition & 0 deletions addons/purchase/tests/test_purchase_order_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ def test_00_purchase_order_report(self):
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()
Expand Down
2 changes: 2 additions & 0 deletions addons/purchase_stock/tests/test_purchase_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ def test_02_po_return(self):

#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()
Expand Down Expand Up @@ -136,6 +137,7 @@ def test_02_po_return(self):
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()
Expand Down
7 changes: 7 additions & 0 deletions addons/purchase_stock/tests/test_stockvaluation.py
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,7 @@ def test_fifo_anglosaxon_return(self):
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()
Expand All @@ -404,6 +405,7 @@ def test_fifo_anglosaxon_return(self):
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()
Expand All @@ -428,6 +430,7 @@ def test_fifo_anglosaxon_return(self):

# 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:
Expand Down Expand Up @@ -462,6 +465,7 @@ def test_anglosaxon_valuation(self):

# 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:
Expand Down Expand Up @@ -1211,6 +1215,7 @@ def test_anglosaxon_valuation_price_total_diff_discount(self):

# 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
Expand Down Expand Up @@ -1257,6 +1262,7 @@ def test_anglosaxon_valuation_discount(self):

# 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()
Expand Down Expand Up @@ -1303,6 +1309,7 @@ def test_anglosaxon_valuation_price_unit_diff_discount(self):

# 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
Expand Down
7 changes: 6 additions & 1 deletion addons/sale/tests/test_reinvoice.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@ def setUpClass(cls, chart_template_ref=None):
'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. """
Expand Down
1 change: 1 addition & 0 deletions addons/sale/tests/test_sale_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ def test_cost_invoicing(self):

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,
Expand Down
17 changes: 11 additions & 6 deletions addons/sale_timesheet/tests/test_reinvoice.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,12 @@ def setUpClass(cls, chart_template_ref=None):
'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. """
Expand Down Expand Up @@ -82,7 +87,7 @@ def test_at_cost(self):
'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']
Expand Down Expand Up @@ -117,7 +122,7 @@ def test_at_cost(self):
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']
Expand Down Expand Up @@ -181,7 +186,7 @@ def test_sales_price(self):
})

# 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']
Expand Down Expand Up @@ -216,7 +221,7 @@ def test_sales_price(self):
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']
Expand Down Expand Up @@ -256,7 +261,7 @@ def test_no_expense(self):
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']
Expand Down
1 change: 1 addition & 0 deletions addons/stock_dropshipping/tests/test_stockvaluation.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ def _dropship_product1(self):
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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@ def test_invoice_after_lc(self):

# 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()
Expand Down
7 changes: 6 additions & 1 deletion addons/stock_landed_costs/tests/test_stockvaluationlayer.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def _make_lc(self, move, amount):
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.
"""
Expand Down Expand Up @@ -341,6 +341,7 @@ def test_vendor_bill_flow_anglo_saxon_1(self):
# 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]
Expand All @@ -353,6 +354,7 @@ def test_vendor_bill_flow_anglo_saxon_1(self):
# 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
Expand Down Expand Up @@ -429,6 +431,7 @@ def test_vendor_bill_flow_anglo_saxon_2(self):
# 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
Expand Down Expand Up @@ -481,6 +484,7 @@ def test_vendor_bill_flow_continental_1(self):
# 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]
Expand All @@ -495,6 +499,7 @@ def test_vendor_bill_flow_continental_1(self):
# 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
Expand Down
9 changes: 9 additions & 0 deletions odoo/addons/test_main_flows/static/tests/tours/main_flow.js
Original file line number Diff line number Diff line change
Expand Up @@ -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')"),
{
Expand Down

5 comments on commit fcaa549

@naoufaltokane
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi,

i want to ask you about why the invoice_date is set by default in demo.odoo.com ?

Thanks.

@william-andre
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean that it doesn't follow what is described in this commit message on demo.odoo.com ?

@naoufaltokane
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, i mean that

@william-andre
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code simply wasn't up to date on the demo server. Should be fine now.
If you want to try out Odoo, you can use this https://www.odoo.com/trial where the code is always updated on Mondays, or https://runbot.odoo.com where the code is always up to date.

@naoufaltokane
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you so mush.

Please sign in to comment.