[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:
committed by
Julien Alardot (jual)
parent
be90d8abae
commit
2bd6553ea4
@@ -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>
|
||||
|
||||
|
||||
@@ -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)],
|
||||
|
||||
@@ -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')
|
||||
|
||||
Reference in New Issue
Block a user