[FIX] hr_expense: Add inverse on total_amount to update unit_amount

The customer was having an issue where they would create an expense from an email with the wrong cost on the expense.
Then when they would try to change the price on the expense record it would seem find all the way up until the journal was posted.

Issue:
When creating an expense from an email the unit_amount is updated instead of the total_amount.
This would cause issues if you had an attachment because when you would attempt to change the amount through the front-end this unit_amount would never get updated because it was set and there was an attachment (line 265).
However, when you would create a journal entry from this expense, because it has the unit_amount != 0 it would provide the unit_amount instead of the total_amount.
Thus propogating the original number from the email even if it was updated between the time of posting and the creation of the expense from the email.

Solution:
Implement an inverse function on total_amount that will update the unit_amount to total_amount_company.
This will cause the unit_amount to stay up to date with the total_amount while also taking into account currency.

opw-3286372

closes odoo/odoo#126388

X-original-commit: c2588824edc732bea40b1a8f6e5248b3d318b361
Signed-off-by: Brice Bartoletti (bib) <bib@odoo.com>
This commit is contained in:
Ryan Cen
2023-06-26 22:15:20 +02:00
committed by Julien Alardot (jual)
parent be90d8abae
commit 2bd6553ea4
3 changed files with 37 additions and 19 deletions
+9 -16
View File
@@ -39,7 +39,6 @@
<field name="employee_id" ref="hr.employee_admin"/>
<field name="analytic_distribution" eval="{ref('analytic.analytic_our_super_product'): 100}"/>
<field name="product_id" ref="product_product_no_cost"/>
<field eval="0.0" name="unit_amount"/>
<field eval="289.0" name="total_amount"/>
<field name="date" eval="time.strftime('%Y')+'-04-03'"/>
</record>
@@ -49,7 +48,6 @@
<field name="employee_id" ref="hr.employee_admin"/>
<field name="analytic_distribution" eval="{ref('analytic.analytic_our_super_product'): 100}"/>
<field name="product_id" ref="product_product_no_cost"/>
<field eval="0.0" name="unit_amount"/>
<field eval="889.0" name="total_amount"/>
<field name="date" eval="time.strftime('%Y')+'-04-03'"/>
</record>
@@ -58,7 +56,7 @@
<field name="name">Travel by car</field>
<field name="employee_id" ref="hr.employee_admin"/>
<field name="product_id" ref="expense_product_mileage"/>
<field eval="0.52" name="unit_amount"/>
<field eval="108.84" name="total_amount"/>
<field name="product_uom_id" ref="uom.product_uom_km"/>
<field eval="320.0" name="quantity"/>
</record>
@@ -67,7 +65,7 @@
<field name="name">BreakFast</field>
<field name="employee_id" ref="hr.employee_admin"/>
<field name="product_id" ref="expense_product_meal"/>
<field eval="20" name="unit_amount"/>
<field eval="20" name="total_amount"/>
<field eval="1.0" name="quantity"/>
</record>
@@ -82,7 +80,7 @@
<field name="employee_id" ref="hr.employee_admin"/>
<field name="analytic_distribution" eval="{ref('analytic.analytic_our_super_product'): 100}"/>
<field name="product_id" ref="expense_product_travel_accommodation"/>
<field eval="700.0" name="unit_amount"/>
<field eval="700.0" name="total_amount"/>
<field name="product_uom_id" ref="uom.product_uom_unit"/>
<field eval="1.0" name="quantity"/>
<field name="date" eval="time.strftime('%Y-%m')+'-12'"/>
@@ -94,7 +92,7 @@
<field name="employee_id" ref="hr.employee_admin"/>
<field name="analytic_distribution" eval="{ref('analytic.analytic_nebula'): 100}"/>
<field name="product_id" ref="expense_product_travel_accommodation"/>
<field eval="400.0" name="unit_amount"/>
<field eval="2000.0" name="total_amount"/>
<field name="product_uom_id" ref="uom.product_uom_unit"/>
<field eval="5.0" name="quantity"/>
<field name="date" eval="time.strftime('%Y-%m')+'-17'"/>
@@ -106,7 +104,7 @@
<field name="employee_id" ref="hr.employee_admin"/>
<field name="analytic_distribution" eval="{ref('analytic.analytic_nebula'): 100}"/>
<field name="product_id" ref="expense_product_meal"/>
<field eval="152.8" name="unit_amount"/>
<field eval="152.8" name="total_amount"/>
<field name="date" eval="time.strftime('%Y-%m')+'-13'"/>
<field eval="1.0" name="quantity"/>
<field name="sheet_id" ref="travel_ny_sheet"/>
@@ -118,7 +116,7 @@
<field name="analytic_distribution" eval="{ref('analytic.analytic_nebula'): 100}"/>
<field name="product_id" ref="expense_product_meal"/>
<field name="date" eval="time.strftime('%Y-%m')+'-15'"/>
<field eval="56.8" name="unit_amount"/>
<field eval="56.8" name="total_amount"/>
<field eval="1.0" name="quantity"/>
<field name="sheet_id" ref="travel_ny_sheet"/>
</record>
@@ -135,7 +133,7 @@
<field name="employee_id" ref="hr.employee_qdp"/>
<field name="analytic_distribution" eval="{ref('analytic.analytic_our_super_product'): 100}"/>
<field name="product_id" ref="expense_product_mileage"/>
<field eval="0.52" name="unit_amount"/>
<field eval="120.85" name="total_amount"/>
<field name="product_uom_id" ref="uom.product_uom_km"/>
<field name="date" eval="time.strftime('%Y')+'-01-15'"/>
<field eval="152.0" name="quantity"/>
@@ -148,7 +146,6 @@
<field name="analytic_distribution" eval="{ref('analytic.analytic_nebula'): 100}"/>
<field name="product_id" ref="product_product_no_cost"/>
<field name="date" eval="time.strftime('%Y')+'-01-15'"/>
<field eval="0.0" name="unit_amount"/>
<field eval="152.8" name="total_amount"/>
<field name="sheet_id" ref="customer_meeting_sheet"/>
</record>
@@ -166,7 +163,7 @@
<field name="analytic_distribution" eval="{ref('analytic.analytic_nebula'): 100}"/>
<field name="product_id" ref="expense_product_meal"/>
<field name="date" eval="time.strftime('%Y-%m')+'-05'"/>
<field eval="12.5" name="unit_amount"/>
<field eval="154" name="total_amount"/>
<field eval="12.0" name="quantity"/>
<field name="sheet_id" ref="team_building_sheet"/>
</record>
@@ -177,7 +174,7 @@
<field name="analytic_distribution" eval="{ref('analytic.analytic_nebula'): 100}"/>
<field name="product_id" ref="expense_product_meal"/>
<field name="date" eval="time.strftime('%Y-%m')+'-05'"/>
<field eval="2.5" name="unit_amount"/>
<field eval="42.5" name="total_amount"/>
<field eval="17.0" name="quantity"/>
<field name="sheet_id" ref="team_building_sheet"/>
</record>
@@ -188,7 +185,6 @@
<field name="analytic_distribution" eval="{ref('analytic.analytic_nebula'): 100}"/>
<field name="product_id" ref="product_product_no_cost"/>
<field name="date" eval="time.strftime('%Y-%m')+'-05'"/>
<field eval="0.0" name="unit_amount"/>
<field eval="25" name="total_amount"/>
<field name="sheet_id" ref="team_building_sheet"/>
</record>
@@ -206,7 +202,6 @@
<field name="analytic_distribution" eval="{ref('analytic.analytic_nebula'): 100}"/>
<field name="product_id" ref="product_product_no_cost"/>
<field name="date" eval="time.strftime('%Y')+'-06-02'"/>
<field eval="0.0" name="unit_amount"/>
<field eval="55.75" name="total_amount"/>
<field name="sheet_id" ref="office_furniture_sheet"/>
</record>
@@ -217,7 +212,6 @@
<field name="analytic_distribution" eval="{ref('analytic.analytic_nebula'): 100}"/>
<field name="product_id" ref="product_product_no_cost"/>
<field name="date" eval="time.strftime('%Y')+'-06-02'"/>
<field eval="0.0" name="unit_amount"/>
<field eval="28.99" name="total_amount"/>
<field name="sheet_id" ref="office_furniture_sheet"/>
</record>
@@ -229,7 +223,6 @@
<field name="analytic_distribution" eval="{ref('analytic.analytic_nebula'): 100}"/>
<field name="product_id" ref="product_product_no_cost"/>
<field name="date" eval="time.strftime('%Y')+'-03-15'"/>
<field eval="0.0" name="unit_amount"/>
<field eval="450.58" name="total_amount"/>
</record>
+8 -3
View File
@@ -73,7 +73,7 @@ class HrExpense(models.Model):
help="Both price-included and price-excluded taxes will behave as price-included taxes for expenses.")
amount_tax = fields.Monetary(string='Tax amount in Currency', help="Tax amount in currency", compute='_compute_amount_tax', store=True, currency_field='currency_id')
amount_tax_company = fields.Monetary('Tax amount', help="Tax amount in company currency", compute='_compute_amount_tax', store=True, currency_field='company_currency_id')
total_amount = fields.Monetary("Total In Currency", compute='_compute_amount', store=True, currency_field='currency_id', tracking=True, readonly=False)
total_amount = fields.Monetary("Total In Currency", compute='_compute_amount', store=True, currency_field='currency_id', tracking=True, readonly=False, inverse='_inverse_total_amount')
untaxed_amount = fields.Monetary("Total Untaxed Amount In Currency", compute='_compute_amount_tax', store=True, currency_field='currency_id')
company_currency_id = fields.Many2one('res.currency', string="Report Company Currency", related='company_id.currency_id', readonly=True)
total_amount_company = fields.Monetary('Total', compute='_compute_amount_tax', store=True, currency_field='company_currency_id')
@@ -173,7 +173,7 @@ class HrExpense(models.Model):
@api.depends('quantity', 'unit_amount', 'tax_ids')
def _compute_amount(self):
for expense in self:
if expense.product_id and not expense.unit_amount:
if expense.product_id and not expense.product_has_cost:
continue
taxes = expense._get_taxes_results(expense.unit_amount, expense.quantity, expense.currency_id)
expense.total_amount = taxes['total_included']
@@ -315,6 +315,11 @@ class HrExpense(models.Model):
})
expense.analytic_distribution = distribution or expense.analytic_distribution
@api.onchange('total_amount')
def _inverse_total_amount(self):
for expense in self:
expense.unit_amount = expense.total_amount_company / expense.quantity
@api.constrains('payment_mode')
def _check_payment_mode(self):
self.sheet_id._check_payment_mode()
@@ -670,7 +675,7 @@ class HrExpense(models.Model):
vals = {
'employee_id': employee.id,
'name': expense_description,
'unit_amount': price,
'total_amount': price,
'product_id': product.id if product else None,
'product_uom_id': product.uom_id.id,
'tax_ids': [(4, tax.id, False) for tax in product.supplier_taxes_id.filtered(lambda r: r.company_id == company)],
+20
View File
@@ -924,3 +924,23 @@ class TestExpenses(TestExpenseCommon):
move = expense_sheet.account_move_id
expected_date = fields.Date.from_string('2021-01-31')
self.assertEqual(move.invoice_date_due, expected_date, 'Bill due date should follow employee payment terms')
def test_inverse_total_amount(self):
""" Test if the inverse method works correctly """
expense = self.env['hr.expense'].create({
'name': 'Choucroute Saucisse',
'employee_id': self.expense_employee.id,
'product_id': self.product_c.id,
'total_amount': 60,
'unit_amount': 0,
'tax_ids': [self.tax_purchase_a.id, self.tax_purchase_b.id],
'analytic_distribution': {
self.analytic_account_1.id: 50,
self.analytic_account_2.id: 50,
},
})
expense.total_amount = 90
self.assertEqual(expense.unit_amount, 90, 'Unit amount should be the same as total amount was written to')