Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docsource/modules180-190.rst
Original file line number Diff line number Diff line change
Expand Up @@ -994,7 +994,7 @@ Module coverage 18.0 -> 19.0
+---------------------------------------------------+----------------------+-------------------------------------------------+
| sale_edi_ubl | | |
+---------------------------------------------------+----------------------+-------------------------------------------------+
| sale_expense | | |
| sale_expense |Done | |
+---------------------------------------------------+----------------------+-------------------------------------------------+
| sale_expense_margin | |No DB layout changes. |
+---------------------------------------------------+----------------------+-------------------------------------------------+
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Copyright 2026 Tecnativa - Carlos Lopez
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from openupgradelib import openupgrade


def fill_hr_expense_sale_order_line_id(env):
"""
This function finds the corresponding sale order line for each hr.expense record
based on the product, quantity, and expense name
A sale order can have multiple lines with the same product and quantity,
so we use DISTINCT ON to select the first matching sale order line
"""
env.cr.execute(
"""
WITH expense_sale_line_match AS (
SELECT DISTINCT ON (he.id)
he.id AS expense_id,
sol.id AS sale_line_id
FROM hr_expense he
JOIN account_move_line aml ON aml.expense_id = he.id
JOIN sale_order_line sol ON sol.name = aml.name
JOIN sale_order so ON so.id = sol.order_id AND so.id = he.sale_order_id
WHERE sol.product_id = he.product_id
AND sol.product_uom_qty = he.quantity
AND sol.is_expense = True
ORDER BY he.id, sol.id
)
UPDATE hr_expense he
SET sale_order_line_id = esm.sale_line_id
FROM expense_sale_line_match esm
WHERE esm.expense_id = he.id
"""
)


@openupgrade.migrate()
def migrate(env, version):
fill_hr_expense_sale_order_line_id(env)
13 changes: 13 additions & 0 deletions openupgrade_scripts/scripts/sale_expense/19.0.1.0/pre-migration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright 2026 Tecnativa - Carlos Lopez
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from openupgradelib import openupgrade

_added_fields = [
("sale_order_line_id", "hr.expense", "hr_expense", "many2one", None, "sale_expense")
]


@openupgrade.migrate()
def migrate(env, version):
openupgrade.add_fields(env, _added_fields)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---Models in module 'sale_expense'---
---Fields in module 'sale_expense'---
sale_expense / hr.expense / sale_order_line_id (many2one) : NEW relation: sale.order.line, isfunction: function, stored
sale_expense / sale.order.line / expense_ids (one2many) : NEW relation: hr.expense
# DONE: precreated in pre-migration and populated in post-migration using a heuristic based on sale_order_id, name, product_id, and quantity.

---XML records in module 'sale_expense'---
NEW ir.ui.view: sale_expense.sale_order_reinvoice_tree_view
# NOTHING TO DO: Handled by the ORM. A new view was inherited from the primary view to add groups to some fields.

DEL ir.ui.view: sale_expense.hr_expense_sheet_form_view_inherit_sale_expense
DEL ir.ui.view: sale_expense.hr_expense_sheet_view_form
# NOTHING TO DO: Handled by the ORM. The views were removed because the hr.expense.sheet model was removed.
Loading