Skip to content

Commit cf7be2e

Browse files
yankinmaxsimahawk
authored andcommitted
[REF] edi_purchase_oca: align with edi_sale_oca
Co-author: Simone Orsi <simahawk@gmail.com>
1 parent 77e61e5 commit cf7be2e

12 files changed

Lines changed: 163 additions & 19 deletions

edi_purchase_oca/__manifest__.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,15 @@
1212
"depends": [
1313
"purchase",
1414
"edi_core_oca",
15+
"edi_record_metadata_oca",
1516
],
1617
"data": [
17-
"views/purchase_order_views.xml",
18+
# Data
19+
"data/edi_configuration.xml",
20+
# Views
1821
"views/edi_exchange_record_views.xml",
22+
"views/purchase_order_views.xml",
1923
"views/res_partner_view.xml",
20-
"data/edi_configuration.xml",
2124
],
2225
"demo": [
2326
"demo/edi_backend.xml",

edi_purchase_oca/demo/edi_configuration.xml

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="UTF-8" ?>
22
<odoo>
33
<record id="demo_edi_configuration_confirmed" model="edi.configuration">
4-
<field name="name">Demo PO send</field>
4+
<field name="name">Demo Purchase Order - order confirmed</field>
55
<field
66
name="description"
77
>Show case how you can send out an order automatically</field>
@@ -14,9 +14,22 @@
1414
# ('sent', 'RFQ Sent'),
1515
# ('to approve', 'To Approve'),
1616
# ('purchase', 'Purchase Order'),
17-
# ('done', 'Locked'),
1817
# ('cancel', 'Cancelled')
1918
if record.state == 'purchase':
19+
record._edi_send_via_edi(conf.type_id)
20+
</field>
21+
</record>
22+
<record id="demo_edi_configuration_cancelled" model="edi.configuration">
23+
<field name="name">Demo Purchase Order - order cancelled</field>
24+
<field
25+
name="description"
26+
>Show case how you can send out an order automatically</field>
27+
<field name="type_id" ref="demo_edi_exc_type_order_out" />
28+
<field name="backend_id" ref="demo_edi_backend" />
29+
<field name="model_id" ref="purchase.model_purchase_order" />
30+
<field name="trigger_id" ref="edi_conf_trigger_purchase_order_state_change" />
31+
<field name="snippet_do">
32+
if record.state == 'cancel':
2033
record._edi_send_via_edi(conf.type_id)
2134
</field>
2235
</record>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
from . import purchase_order_line
12
from . import purchase_order
23
from . import res_partner

edi_purchase_oca/models/purchase_order.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,15 @@ class PurchaseOrder(models.Model):
1313

1414
def _edi_config_field_relation(self):
1515
return self.partner_id.edi_purchase_conf_ids
16+
17+
# edi_record_metadata api
18+
def _edi_get_metadata_to_store(self, orig_vals):
19+
data = super()._edi_get_metadata_to_store(orig_vals)
20+
line_vals_by_edi_id = {}
21+
for line_vals in orig_vals.get("order_line", []):
22+
vals = line_vals[-1]
23+
edi_id = vals.get("edi_id")
24+
if edi_id:
25+
line_vals_by_edi_id[edi_id] = vals
26+
data.update({"orig_values": {"lines": line_vals_by_edi_id}})
27+
return data
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Copyright 2026 Camptocamp SA
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
3+
4+
from odoo import api, fields, models
5+
6+
7+
class PurchaseOrderLine(models.Model):
8+
_name = "purchase.order.line"
9+
_inherit = [
10+
"purchase.order.line",
11+
"edi.exchange.consumer.mixin",
12+
"edi.id.mixin",
13+
]
14+
15+
edi_disable_auto = fields.Boolean(related="order_id.edi_disable_auto")
16+
edi_exchange_ready = fields.Boolean(compute="_compute_edi_exchange_ready")
17+
18+
@api.depends()
19+
def _compute_edi_exchange_ready(self):
20+
for rec in self:
21+
rec.edi_exchange_ready = rec._edi_exchange_ready()
22+
23+
def _edi_exchange_ready(self):
24+
# Only product lines are eligible for EDI processing
25+
# sections/notes and downpayment lines should be ignored
26+
return not self.display_type and not self.is_downpayment
27+
28+
@api.model_create_multi
29+
def create(self, vals_list):
30+
# Set default origin if not passed
31+
for vals in vals_list:
32+
orig_id = vals.get("origin_exchange_record_id")
33+
if not orig_id and "order_id" in vals:
34+
order = self.env["purchase.order"].browse(vals["order_id"])
35+
vals["origin_exchange_record_id"] = order.origin_exchange_record_id.id
36+
return super().create(vals_list)
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
* Lois Rilo <lois.rilo@forgeflow.com>
22
* Simone Orsi <simone.orsi@camptocamp.com>
3-
- Phan Hong Phuc \<<phucph@trobz.com>\>
3+
* Phan Hong Phuc \<<phucph@trobz.com>\>
Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
1-
This module intends to create a base to be extended by local edi rules
2-
for purchase. Assign the EDI Configuration on the partner form.
1+
Handle purchase orders via EDI.
2+
3+
This is a base module to plug purchase processes with the EDI framework.
4+
5+
To handle inbound/outbound purchase orders, you need to create your own
6+
integration modules on top of this base module.

edi_purchase_oca/tests/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
from . import test_generate
2+
from . import test_order
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Copyright 2026 Camptocamp SA
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
3+
4+
from odoo.tests.common import TransactionCase
5+
6+
from .common import OrderMixin, PurchaseEDIBackendTestMixin
7+
8+
9+
class TestOrder(TransactionCase, PurchaseEDIBackendTestMixin, OrderMixin):
10+
@classmethod
11+
def setUpClass(cls):
12+
super().setUpClass()
13+
cls.env = cls.env(context=dict(cls.env.context, edi_framework_action=True))
14+
cls._setup_records()
15+
cls.exchange_type_in.exchange_filename_pattern = "{record.id}-{type.code}-{dt}"
16+
cls.exc_record_in = cls.backend.create_record(
17+
cls.exchange_type_in.code, {"edi_exchange_state": "input_received"}
18+
)
19+
order_vals = cls._setup_order()
20+
cls.order = cls._create_purchase_order(
21+
origin_exchange_record_id=cls.exc_record_in.id,
22+
**order_vals,
23+
)
24+
25+
def test_line_origin(self):
26+
order = self.order
27+
self.assertEqual(order.origin_exchange_record_id, self.exc_record_in)
28+
lines = order.order_line
29+
self.env["purchase.order.line"].create(
30+
[
31+
{
32+
"order_id": order.id,
33+
"product_id": self.product.id,
34+
"product_qty": 20,
35+
"price_unit": 100.0,
36+
"edi_id": 2000,
37+
},
38+
{
39+
"order_id": order.id,
40+
"product_id": self.product.id,
41+
"product_qty": 30,
42+
"price_unit": 100.0,
43+
"edi_id": 3000,
44+
},
45+
]
46+
)
47+
order.invalidate_recordset()
48+
new_line1, new_line2 = order.order_line - lines
49+
self.assertEqual(new_line1.origin_exchange_record_id, self.exc_record_in)
50+
self.assertEqual(new_line2.origin_exchange_record_id, self.exc_record_in)
51+
52+
def test_line_exchange_ready(self):
53+
line_model = self.env["purchase.order.line"]
54+
55+
regular_line = line_model.new({"product_id": self.product.id})
56+
section_line = line_model.new({"display_type": "line_section"})
57+
downpayment_line = line_model.new({"is_downpayment": True})
58+
59+
self.assertTrue(regular_line.edi_exchange_ready)
60+
self.assertFalse(section_line.edi_exchange_ready)
61+
self.assertFalse(downpayment_line.edi_exchange_ready)

edi_purchase_oca/views/edi_exchange_record_views.xml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
model="ir.actions.act_window"
77
id="act_open_edi_exchange_record_purchase_order_view"
88
>
9-
<field name="name">Purchase Order Exchange Record</field>
9+
<field name="name">Purchase Order Exchange Records</field>
1010
<field name="type">ir.actions.act_window</field>
1111
<field name="res_model">edi.exchange.record</field>
1212
<field name="view_mode">list,form</field>
@@ -15,13 +15,13 @@
1515
</record>
1616
<menuitem
1717
id="menu_purchase_edi_root"
18-
name="Exchange records"
18+
name="EDI"
1919
parent="purchase.menu_purchase_root"
20-
sequence="20"
20+
sequence="99"
2121
/>
2222
<menuitem
2323
id="menu_purchase_edi_exchange_record"
24-
name="Purchase Orders"
24+
name="Exchanges"
2525
action="act_open_edi_exchange_record_purchase_order_view"
2626
parent="menu_purchase_edi_root"
2727
sequence="20"

0 commit comments

Comments
 (0)