oca-ocb-sale/odoo-bringout-oca-ocb-sale_expense/sale_expense/models/hr_expense.py
Ernad Husremovic 73afc09215 19.0 vanilla
2026-03-09 09:32:12 +01:00

91 lines
3.9 KiB
Python

# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import Command, api, fields, models
class HrExpense(models.Model):
_inherit = "hr.expense"
sale_order_id = fields.Many2one(
'sale.order',
string='Customer to Reinvoice',
compute='_compute_sale_order_id',
store=True,
readonly=False,
index='btree_not_null',
tracking=True,
# NOTE: only confirmed SO can be selected, but this domain in activated throught the name search with the `sale_expense_all_order`
# context key. So, this domain is not the one applied.
domain="[('state', '=', 'sale')]",
check_company=True,
help="If the category has an expense policy, it will be reinvoiced on this sales order")
sale_order_line_id = fields.Many2one(
comodel_name='sale.order.line',
compute='_compute_sale_order_id',
store=True,
readonly=True,
index='btree_not_null',
)
can_be_reinvoiced = fields.Boolean("Can be reinvoiced", compute='_compute_can_be_reinvoiced')
@api.depends('product_id.expense_policy')
def _compute_can_be_reinvoiced(self):
for expense in self:
expense.can_be_reinvoiced = expense.product_id.expense_policy in ['sales_price', 'cost']
@api.depends('can_be_reinvoiced')
def _compute_sale_order_id(self):
for expense in self.filtered(lambda e: not e.can_be_reinvoiced):
expense.sale_order_id = False
expense.sale_order_line_id = False
@api.onchange('sale_order_id')
def _onchange_sale_order_id(self):
to_reset = self.filtered(lambda line: not self.env.is_protected(self._fields['analytic_distribution'], line))
to_reset.invalidate_recordset(['analytic_distribution'])
self.env.add_to_compute(self._fields['analytic_distribution'], to_reset)
def _sale_expense_reset_sol_quantities(self):
"""
Resets the quantity of a SOL created by a reinvoiced expense to 0 when the expense or its move is reset to an unfinished state
Note: Resetting the qty_delivered will raise if the product is a storable product and sale_stock is installed,
but it's fine as it doesn't make much sense to have a stored product in an expense.
"""
self.check_access('write')
# If we can edit the expense, we may not be able to edit the sol without sudoing.
self.sudo().sale_order_line_id.write({
'qty_delivered': 0.0,
'product_uom_qty': 0.0,
'expense_ids': [Command.clear()],
})
def _get_split_values(self):
# EXTENDS hr_expense
vals = super()._get_split_values()
for split_value in vals:
split_value['sale_order_id'] = self.sale_order_id.id
return vals
def action_post(self):
# EXTENDS hr_expense
# When posting expense, we need the analytic entries to be generated, because reinvoicing uses analytic accounts.
# We then ensure the proper analytic acocunt is given in the distribution and if not,
# we create an account and set the distribution to it.
for expense in self:
if expense.sale_order_id and not expense.analytic_distribution:
analytic_account = self.env['account.analytic.account'].create(expense.sale_order_id._prepare_analytic_account_data())
expense.analytic_distribution = {analytic_account.id: 100}
return super().action_post()
def action_open_sale_order(self):
self.ensure_one()
return {
'type': 'ir.actions.act_window',
'res_model': 'sale.order',
'views': [(self.env.ref("sale.view_order_form").id, 'form')],
'view_mode': 'form',
'target': 'current',
'name': self.sale_order_id.display_name,
'res_id': self.sale_order_id.id,
}