Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[16.0][IMP] base_edifact: Support more EDIFACT format #835

Merged
merged 11 commits into from
Oct 26, 2023
Merged
66 changes: 52 additions & 14 deletions base_edifact/models/edifact.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,11 @@

@api.model
def _loads_edifact(self, order_file):
interchange = Interchange.from_str(order_file.decode())
# TODO: use chardet library for get encoding
try:
interchange = Interchange.from_str(order_file.decode())
except UnicodeDecodeError:
interchange = Interchange.from_str(order_file.decode("latin-1"))

Check warning on line 77 in base_edifact/models/edifact.py

View check run for this annotation

Codecov / codecov/patch

base_edifact/models/edifact.py#L76-L77

Added lines #L76 - L77 were not covered by tests
return interchange

@api.model
Expand All @@ -82,7 +86,11 @@
@api.model
def map2odoo_date(self, dt):
# '102'
dtt = datetime.datetime.strptime(dt[1], "%Y%m%d")
date_format = "%Y%m%d%H%M%S"
length_dt = len(dt[1])
if length_dt % 2 == 0 and length_dt in range(8, 13, 2):
date_format = date_format[0 : length_dt - 2]
dtt = datetime.datetime.strptime(dt[1], date_format)
return dtt.date()

@api.model
Expand Down Expand Up @@ -138,22 +146,30 @@
nameref = self.MAP_AGENCY_CODE_2_RES_PARTNER_NAMEREF.get(agency_code, "gln")
address["partner"][nameref] = party_id
d = address["address"]
# Fallback if address information is missing
try:
if isinstance(seg, Segment):
lenght_seg = len(seg.elements)

Check warning on line 152 in base_edifact/models/edifact.py

View check run for this annotation

Codecov / codecov/patch

base_edifact/models/edifact.py#L152

Added line #L152 was not covered by tests
else:
lenght_seg = len(seg)
except ValueError:
lenght_seg = 0

Check warning on line 156 in base_edifact/models/edifact.py

View check run for this annotation

Codecov / codecov/patch

base_edifact/models/edifact.py#L155-L156

Added lines #L155 - L156 were not covered by tests
# PARTY NAME
if bool(seg[2]):
if lenght_seg > 2 and bool(seg[2]):
d["name"] = seg[2]
if bool(seg[3]):
if lenght_seg > 3 and bool(seg[3]):
d["name"] = "{}{}".format(f"{d['name']}. " if d.get("name") else "", seg[3])
if bool(seg[4]):
if lenght_seg > 4 and bool(seg[4]):
# Street address and/or PO Box number in a structured address: one to three lines.
d["street"] = seg[4]
if bool(seg[5]):
if lenght_seg > 5 and bool(seg[5]):
d["city"] = seg[5]
if bool(seg[6]):
if lenght_seg > 6 and bool(seg[6]):
# Country sub-entity identification
d["state_code"] = seg[6]
if bool(seg[7]):
if lenght_seg > 7 and bool(seg[7]):
d["zip"] = seg[7]
if bool(seg[8]):
if lenght_seg > 8 and bool(seg[8]):
# Country, coded ISO 3166
d["country_code"] = seg[8]

Expand All @@ -172,16 +188,22 @@
}

@api.model
def map2odoo_product(self, seg):
def map2odoo_product(self, seg, pia=None):
"""
:seg: LIN segment
['1', '', ['8885583503464', 'EN']]
EN. International Article Numbering Association (EAN)
UP. UPC (Universal product code)
SRV. GTIN
:product_info: PIA segment
['5', ['1276', 'SA', '', '9']]
SA. Supplier's Article Number
"""
product = seg[2]
pct = product[1]
# Fallback on SA if no EAN given
if not product[0] and pia[1][0]:
return dict(code=pia[1][0])
return dict(code=product[0]) if pct == "SRV" else dict(barcode=product[0])

@api.model
Expand All @@ -193,14 +215,30 @@
return float(seg[0][1])

@api.model
def map2odoo_unit_price(self, seg):
def map2odoo_unit_price(self, seg=None):
"""
'PRI' EDI segment: [['AAA', '19.75']]
Price qualifier:
* 'AAA'. Calculation net
* 'AAB'. Calculation gross
"""
pri = seg[0]
if pri[0] == "AAA":
return float(pri[1])
if seg:
pri = seg[0]
if pri[0] == "AAA":
return float(pri[1])
# TODO: Add price calculation formula
if pri[0] == "AAB":
return float(pri[1])

Check warning on line 231 in base_edifact/models/edifact.py

View check run for this annotation

Codecov / codecov/patch

base_edifact/models/edifact.py#L231

Added line #L231 was not covered by tests
return 0.0

@api.model
def map2odoo_description(self, seg):
"""
'IMD' EDI segment: ['F', '79', ['', '', '', 'Description']]
F: Label
79: Other description
"""
if seg:
description = seg[2][3]
return description
return None

Check warning on line 244 in base_edifact/models/edifact.py

View check run for this annotation

Codecov / codecov/patch

base_edifact/models/edifact.py#L244

Added line #L244 was not covered by tests
24 changes: 24 additions & 0 deletions base_edifact/tests/files/test_orders_-_no_PRI_segments.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
UNA:+.? '
UNB+UNOC:3+ENI-CH:14+2256:14+230320:1910+2'
UNH+000011956901+ORDERS:D:96A:UN:EAN008'
BGM+220+COM-004017+9'
DTM+137:20230320:102'
DTM+2:20230321:102'
NAD+BY+5450534008617::91'
NAD+BY+5450534008143::92++PartyName1+Address1+City1++1964'
NAD+SU+2256::9'
NAD+DP+5450534008617::91++PartyName1+Address1+City1++1964'
RFF+API:5450534008617'
LIN+1++9783898307529:EN'
PIA+1+7076:SA::91+30007:BP::92'
QTY+21:8:6'
LIN+2++9783898307538:EN'
PIA+1+7065:SA::91+38812:BP::92'
QTY+21:4:6'
LIN+3++9783898307645:EN'
PIA+1+7056:SA::91+30008:BP::92'
QTY+21:1:24'
UNS+S'
CNT+2:3'
UNT+267+000011956901'
UNZ+1+2'
69 changes: 69 additions & 0 deletions base_edifact/tests/files/test_orders_-_no_ean_in_LIN_segments.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
UNB+UNOC:3+3027800012009:14+7640142640004:14+230320:1438+003274'
UNH+3269+ORDERS:D:96A:UN:EAN008'
BGM+220::9:ORDERS+467819+9'
DTM+137:202303201433:203'
DTM+2:202303220000:203'
NAD+SU+7640142640004::9++Suppliér1+Address1+City1++1762+CH'
RFF+IT:5020'
NAD+BY+5450534008617::ZZ++'
RFF+IT:5132'
CTA+OC+:RADON'
NAD+SF+++'
NAD+IV+5450534008617::ZZ++Suppliér1+Address1+City1++3110+CH'
RFF+IT:5132'
NAD+DP+5450534008617::ZZ++Suppliér1+Address1+City1++3110+CH'
RFF+IT:5132'
RFF+GN:RCS'
CUX+2:EUR:9'
ALC+C++6++FC::9:FRAIS DE PORT'
MOA+23:0'
LIN+1++:EN'
PIA+5+1276:SA::9'
PIA+5+31136:IN::9'
PIA+5+00:VL'
IMD+F+ANM+:::Product1'
IMD+F+79+:::Product1 description'
QTY+21:12:BOU'
QTY+59:6:PCE'
PRI+AAB:5.22::NTP'
LIN+2++:EN'
PIA+5+46630:SA::9'
PIA+5+27952:IN::9'
PIA+5+00:VL'
IMD+F+ANM+:::Product2'
IMD+F+79+:::Product2 Description'
QTY+21:24:BOU'
QTY+59:24:PCE'
PRI+AAB:27.641::NTP'
LIN+3++:EN'
PIA+5+98891 75:SA::9'
PIA+5+22389:IN::9'
PIA+5+00:VL'
IMD+F+ANM+:::Product3'
IMD+F+79+:::Product3 Description'
QTY+21:12:BOU'
QTY+59:6:PCE'
PRI+AAB:51.03::NTP'
LIN+4++:EN'
PIA+5+37230:SA::9'
PIA+5+16344:IN::9'
PIA+5+00:VL'
IMD+F+ANM+:::Product4'
IMD+F+79+:::Product4 Description'
QTY+21:24:BOU'
QTY+59:24:PCE'
PRI+AAB:29.542::NTP'
LIN+5++:EN'
PIA+5+1076:SA::9'
PIA+5+16270:IN::9'
PIA+5+00:VL'
IMD+F+ANM+:::Product5'
IMD+F+79+:::Product5 Description'
QTY+21:90:BOU'
QTY+59:6:PCE'
PRI+AAB:5.22::NTP'
UNS+S'
MOA+125:247.98'
CNT+2:5'
UNT+67+3269'
UNZ+1+003274'
27 changes: 27 additions & 0 deletions base_edifact/tests/test_base_edifact.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ def test_pydifact_obj(self):
# [1]: to get the list messages, [0]: to get the first list value of the segments
self.assertEqual(obj[1]["segments"][0]["BGM"][1], "1AA1TEST")

def test_pydifact_obj_latin1(self):
edifact_docu = _get_file_content("test_orders_-_no_ean_in_LIN_segments.txt")
obj = self.base_edifact_model.pydifact_obj(edifact_docu)
# [1]: to get the list messages, [3]: to get the third list value of the segments
self.assertEqual(obj[1]["segments"][3]["NAD"][3], "Suppliér1")

def test_map2odoo_address(self):
"""Address segment
DP. Party to which goods should be delivered, if not identical with
Expand All @@ -48,12 +54,33 @@ def test_map2odoo_product(self):
product = self.base_edifact_model.map2odoo_product(seg)
self.assertEqual(product["barcode"], "8885583503464")

def test_map2odoo_product_pia(self):
seg = ("1", "", ["", "EN"])
pia = ["5", ["1276", "SA", "", "9"]]
product = self.base_edifact_model.map2odoo_product(seg, pia)
self.assertEqual(product["code"], "1276")

def test_map2odoo_qty(self):
seg = (["21", "2"],)
qty = self.base_edifact_model.map2odoo_qty(seg)
self.assertEqual(qty, 2.0)

def test_map2odoo_unit_price(self):
# Test with Price qualifier is AAA
seg = (["AAA", "19.75"],)
unit_price = self.base_edifact_model.map2odoo_unit_price(seg)
self.assertEqual(unit_price, 19.75)
# Test with no unit price
unit_price = self.base_edifact_model.map2odoo_unit_price()
self.assertEqual(unit_price, 0.0)

def test_map2odoo_date(self):
# Test with date format YYYY-MM-DD HH:MM
date_str = ["137", "202303201433", "203"]
date = self.base_edifact_model.map2odoo_date(date_str)
self.assertEqual(str(date), "2023-03-20")

def test_map2odoo_description(self):
seg = ["F", "79", ["", "", "", "Description"]]
description = self.base_edifact_model.map2odoo_description(seg)
self.assertEqual(description, "Description")
Loading