diff --git a/despatch_advice_import/README.rst b/despatch_advice_import/README.rst index 10082c9df6..0afe9c4633 100644 --- a/despatch_advice_import/README.rst +++ b/despatch_advice_import/README.rst @@ -43,7 +43,7 @@ To use this module, you need to: Known issues / Roadmap ====================== -* ... + Bug Tracker =========== diff --git a/despatch_advice_import/__init__.py b/despatch_advice_import/__init__.py index e948157abd..02baef47b9 100644 --- a/despatch_advice_import/__init__.py +++ b/despatch_advice_import/__init__.py @@ -1,3 +1,2 @@ # -*- coding: utf-8 -*- - -from . import wizard \ No newline at end of file +from . import wizard diff --git a/despatch_advice_import/__manifest__.py b/despatch_advice_import/__manifest__.py index 30eabe0a59..a89fa8b4bf 100644 --- a/despatch_advice_import/__manifest__.py +++ b/despatch_advice_import/__manifest__.py @@ -3,18 +3,18 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { - 'name': 'Despatch Advice Import', - 'summary': """ - Despatch Advice import""", - 'version': '10.0.1.0.0', - 'license': 'AGPL-3', - 'author': 'ACSONE SA/NV,Odoo Community Association (OCA)', - 'depends': ['purchase', 'base_business_document_import_stock' + "name": "Despatch Advice Import", + "summary": "Despatch Advice import", + "version": "10.0.1.0.0", + "license": "AGPL-3", + "author": "ACSONE SA/NV,Odoo Community Association (OCA)", + "depends": [ + "purchase", + "base_business_document_import_stock", ], - 'data': [ - 'wizard/despatch_advice_import.xml', + "data": [ + "wizard/despatch_advice_import.xml", ], - 'demo': [ - ], - 'installable': True, + "demo": [], + "installable": True, } diff --git a/despatch_advice_import/tests/__init__.py b/despatch_advice_import/tests/__init__.py index 2178897879..3d12552832 100644 --- a/despatch_advice_import/tests/__init__.py +++ b/despatch_advice_import/tests/__init__.py @@ -1 +1 @@ -from . import test_despatch_advice_import \ No newline at end of file +from . import test_despatch_advice_import diff --git a/despatch_advice_import/tests/test_despatch_advice_import.py b/despatch_advice_import/tests/test_despatch_advice_import.py index 8353b209d7..9d89a3e5ef 100644 --- a/despatch_advice_import/tests/test_despatch_advice_import.py +++ b/despatch_advice_import/tests/test_despatch_advice_import.py @@ -103,7 +103,6 @@ def setUpClass(cls): cls.DespatchAdviceImport = cls.env["despatch.advice.import"] - def order_line_to_data(self, order_line, qty=None, backorder_qty=None): return { "backorder_qty": backorder_qty, @@ -126,7 +125,7 @@ def _get_base_data(self): @classmethod def _add_procurements(cls, line, qties): for qty in qties: - cls.env['procurement.order'].create( + cls.env["procurement.order"].create( { "name": "Test", "product_id": line.product_id.id, @@ -137,7 +136,6 @@ def _add_procurements(cls, line, qties): } ) - def test_00(self): """ Data: @@ -162,32 +160,27 @@ def test_01(self): data = self._get_base_data() confirmed_qty = self.line1.product_qty - 21 data["lines"] = [ - self.order_line_to_data( - self.line1, qty=confirmed_qty, backorder_qty=21 - ), + self.order_line_to_data(self.line1, qty=confirmed_qty, backorder_qty=21), self.order_line_to_data(self.line2), self.order_line_to_data(self.line3), - self.order_line_to_data(self.line4) + self.order_line_to_data(self.line4), ] self.DespatchAdviceImport.process_data(data) - + self.assertTrue(self.purchase_order.picking_ids) move_ids = self.line1.move_ids self.assertEqual(len(move_ids), 2) - self.assertEqual( - sum(move_ids.mapped("product_qty")), self.line1.product_qty + self.assertEqual(sum(move_ids.mapped("product_qty")), self.line1.product_qty) + assigned = move_ids.filtered( + lambda s: s.state == "assigned" and s.product_qty == 3 ) - assigned = move_ids.filtered(lambda s: s.state == "assigned" and s.product_qty == 3) self.assertEqual(assigned.product_qty, confirmed_qty) move_backorder = move_ids.filtered( lambda s: s.state == "assigned" and s.product_qty == 21 ) self.assertTrue(move_backorder) - self.assertEqual( - move_backorder.picking_id.backorder_id, assigned.picking_id - ) - + self.assertEqual(move_backorder.picking_id.backorder_id, assigned.picking_id) def test_02(self): """ @@ -196,21 +189,17 @@ def test_02(self): data = self._get_base_data() confirmed_qty = self.line1.product_qty - 21 data["lines"] = [ - self.order_line_to_data( - self.line1, qty=confirmed_qty - ), + self.order_line_to_data(self.line1, qty=confirmed_qty), self.order_line_to_data(self.line2), self.order_line_to_data(self.line3), - self.order_line_to_data(self.line4) + self.order_line_to_data(self.line4), ] self.DespatchAdviceImport.process_data(data) - + self.assertTrue(self.purchase_order.picking_ids) move_ids = self.line1.move_ids self.assertEqual(len(move_ids), 2) - self.assertEqual( - sum(move_ids.mapped("product_qty")), self.line1.product_qty - ) + self.assertEqual(sum(move_ids.mapped("product_qty")), self.line1.product_qty) assigned = move_ids.filtered(lambda s: s.state == "assigned") self.assertEqual(assigned.product_qty, confirmed_qty) cancel = move_ids.filtered(lambda s: s.state == "cancel") @@ -235,9 +224,9 @@ def test_03(self): backorder_qty=3, ), self.order_line_to_data(self.line3), - self.order_line_to_data(self.line4) + self.order_line_to_data(self.line4), ] - + self.DespatchAdviceImport.process_data(data) self.assertEqual(self.purchase_order.state, "purchase") self.assertEqual(len(self.purchase_order.picking_ids), 2) @@ -248,8 +237,7 @@ def test_03(self): sum(line1_move_ids.mapped("product_qty")), self.line1.product_qty ) move_confirmed = line1_move_ids.filtered( - lambda s: s.state == "assigned" - and s.product_qty == line1_confirmed_qty + lambda s: s.state == "assigned" and s.product_qty == line1_confirmed_qty ) self.assertTrue(move_confirmed) self.assertEqual(move_confirmed.product_qty, line1_confirmed_qty) @@ -258,7 +246,8 @@ def test_03(self): ) self.assertTrue(move_backorder) self.assertEqual( - move_backorder.picking_id.backorder_id, move_confirmed.picking_id, + move_backorder.picking_id.backorder_id, + move_confirmed.picking_id, ) # line2 line2_move_ids = self.line2.move_ids @@ -267,8 +256,7 @@ def test_03(self): sum(line2_move_ids.mapped("product_qty")), self.line2.product_qty ) move_confirmed = line2_move_ids.filtered( - lambda s: s.state == "assigned" - and s.product_qty == line2_confirmed_qty + lambda s: s.state == "assigned" and s.product_qty == line2_confirmed_qty ) self.assertTrue(move_confirmed) self.assertEqual(move_confirmed.product_qty, line2_confirmed_qty) @@ -278,13 +266,12 @@ def test_03(self): ) self.assertTrue(move_backorder) self.assertEqual( - move_backorder.picking_id.backorder_id, move_confirmed.picking_id, + move_backorder.picking_id.backorder_id, + move_confirmed.picking_id, ) - def test_04(self): - """ - """ + """""" data = self._get_base_data() confirmed_qty = self.line1.product_qty - 3 data["lines"] = [ @@ -295,15 +282,13 @@ def test_04(self): ), self.order_line_to_data(self.line2), self.order_line_to_data(self.line3), - self.order_line_to_data(self.line4) + self.order_line_to_data(self.line4), ] self.DespatchAdviceImport.process_data(data) self.assertEqual(len(self.purchase_order.picking_ids), 2) move_ids = self.line1.move_ids self.assertEqual(len(move_ids), 3) - self.assertEqual( - sum(move_ids.mapped("product_qty")), self.line1.product_qty - ) + self.assertEqual(sum(move_ids.mapped("product_qty")), self.line1.product_qty) move_confirmed = move_ids.filtered( lambda s: s.state == "assigned" and s.product_qty == confirmed_qty ) @@ -313,44 +298,37 @@ def test_04(self): ) self.assertTrue(move_cancel) self.assertEqual( - _("No backorder planned by the supplier."), move_cancel.note, + _("No backorder planned by the supplier."), + move_cancel.note, ) move_backorder = move_ids.filtered( lambda s: s.state == "assigned" and s.product_qty == 2 ) self.assertTrue(move_backorder) self.assertEqual( - move_backorder.picking_id.backorder_id, move_confirmed.picking_id, + move_backorder.picking_id.backorder_id, + move_confirmed.picking_id, ) def test_05(self): - """ - - """ + """""" data = self._get_base_data() confirmed_qty = 6 data["lines"] = [ self.order_line_to_data(self.line1), self.order_line_to_data(self.line2), - self.order_line_to_data(self.line3, - qty=confirmed_qty, - backorder_qty=3 - ), - self.order_line_to_data(self.line4) + self.order_line_to_data(self.line3, qty=confirmed_qty, backorder_qty=3), + self.order_line_to_data(self.line4), ] self.DespatchAdviceImport.process_data(data) self.assertEqual(len(self.purchase_order.picking_ids), 2) move_ids = self.line3.move_ids self.assertEqual(len(move_ids), 4) - self.assertEqual( - sum(move_ids.mapped("product_qty")), self.line3.product_qty - ) + self.assertEqual(sum(move_ids.mapped("product_qty")), self.line3.product_qty) moves_confirmed = move_ids.filtered( lambda s: s.state == "assigned" and not s.picking_id.backorder_id ) - self.assertEqual( - sum(moves_confirmed.mapped("product_qty")), confirmed_qty - ) + self.assertEqual(sum(moves_confirmed.mapped("product_qty")), confirmed_qty) move_cancel = move_ids.filtered( lambda s: s.state == "cancel" and s.product_qty == 6 @@ -365,10 +343,8 @@ def test_05(self): moves_confirmed[0].picking_id, ) - def test_06(self): - """ - """ + """""" data = self._get_base_data() confirmed_qty = 3 data["lines"] = [ @@ -384,9 +360,7 @@ def test_06(self): self.DespatchAdviceImport.process_data(data) self.assertEqual(len(self.purchase_order.picking_ids), 2) move_ids = self.line4.move_ids - self.assertEqual( - sum(move_ids.mapped("product_qty")), self.line4.product_qty - ) + self.assertEqual(sum(move_ids.mapped("product_qty")), self.line4.product_qty) moves_confirmed = move_ids.filtered( lambda s: s.state == "assigned" and not s.picking_id.backorder_id ) @@ -400,4 +374,3 @@ def test_06(self): lambda s: s.state == "assigned" and s.picking_id.backorder_id ) self.assertEqual(sum(moves_backorder.mapped("product_qty")), 3) - diff --git a/despatch_advice_import/wizard/__init__.py b/despatch_advice_import/wizard/__init__.py index f77ed6fbb2..ce838ad980 100644 --- a/despatch_advice_import/wizard/__init__.py +++ b/despatch_advice_import/wizard/__init__.py @@ -1 +1 @@ -from . import despatch_advice_import \ No newline at end of file +from . import despatch_advice_import diff --git a/despatch_advice_import/wizard/despatch_advice_import.py b/despatch_advice_import/wizard/despatch_advice_import.py index 9a618fd9ea..0976c1fa00 100644 --- a/despatch_advice_import/wizard/despatch_advice_import.py +++ b/despatch_advice_import/wizard/despatch_advice_import.py @@ -27,10 +27,11 @@ class DespatchAdviceImport(models.TransientModel): ) filename = fields.Char(string="Filename") - # Format of parsed despatch advice + # #Format of parsed despatch advice # { - # 'ref': 'PO01234' # the buyer party identifier - # # (specified into the Order document -> po's name) + # # the buyer party identifier + # # (specified into the Order document -> po's name) + # 'ref': 'PO01234' # 'despatch_advice_type_code': ' scheduled | delivered' # 'supplier': {'vat': 'FR25499247138'}, # 'company': {'vat': 'FR12123456789'}, # Only used to check we are not @@ -45,7 +46,7 @@ class DespatchAdviceImport(models.TransientModel): # # the backorder qty will be delivered # # in a next shipping # }] - + @api.model def parse_despatch_advice(self, document, filename): if not document: @@ -62,7 +63,10 @@ def parse_despatch_advice(self, document, filename): raise UserError(_("This XML file is not XML-compliant")) if logger.isEnabledFor(logging.DEBUG): pretty_xml_string = etree.tostring( - xml_root, pretty_print=True, encoding="UTF-8", xml_declaration=True + xml_root, + pretty_print=True, + encoding="UTF-8", + xml_declaration=True, ) logger.debug("Starting to import the following XML file:") logger.debug(pretty_xml_string) @@ -89,7 +93,8 @@ def parse_despatch_advice(self, document, filename): and not self._context.get("edi_skip_company_check") ): self.env["business.document.import"]._check_company( - parsed_despatch_advice["company"], parsed_despatch_advice["chatter_msg"] + parsed_despatch_advice["company"], + parsed_despatch_advice["chatter_msg"], ) return parsed_despatch_advice @@ -157,7 +162,9 @@ def process_data(self, parsed_order_document): elif not line_info["qty"] and not line_info["backorder_qty"]: self._process_rejected(stock_moves, parsed_order_document) else: - self._process_conditional(stock_moves, parsed_order_document, line_info) + self._process_conditional( + stock_moves, parsed_order_document, line_info + ) @api.model def _process_rejected(self, stock_moves, parsed_order_document): @@ -196,27 +203,19 @@ def _process_conditional(self, moves, parsed_order_document, line): if float_compare(qty, moves_qty, precision_digits=precision) >= 0: return - + # confirmed qty < ordered qty move_ids_to_backorder = [] move_ids_to_cancel = [] for move in moves: self._check_picking_status(move.picking_id) - if ( - float_compare( - qty, move.product_qty, precision_digits=precision - ) - >= 0 - ): + if float_compare(qty, move.product_qty, precision_digits=precision) >= 0: # qty planned => qty into the stock move: Keep it qty -= move.product_qty continue if ( qty - and float_compare( - qty, move.product_qty, precision_digits=precision - ) - < 0 + and float_compare(qty, move.product_qty, precision_digits=precision) < 0 ): # qty planned < qty into the stock move: Split it new_move_id = move.split(move.product_qty - qty) @@ -238,25 +237,19 @@ def _process_conditional(self, moves, parsed_order_document, line): ): # backorder_qty < qty into the move -> split the move # anf cancel remaining qty - move_ids_to_cancel.append( - move.split(move.product_qty - backorder_qty) - ) + move_ids_to_cancel.append(move.split(move.product_qty - backorder_qty)) backorder_qty -= move.product_qty move_ids_to_backorder.append(move.id) # move backorder moves to a backorder if move_ids_to_backorder: - moves_to_backorder = self.env["stock.move"].browse( - move_ids_to_backorder - ) + moves_to_backorder = self.env["stock.move"].browse(move_ids_to_backorder) self._add_moves_to_backorder(moves_to_backorder) # cancel moves to cancel if move_ids_to_cancel: moves_to_cancel = self.env["stock.move"].browse(move_ids_to_cancel) moves_to_cancel.action_cancel() - moves_to_cancel.write( - {"note": _("No backorder planned by the supplier.")} - ) + moves_to_cancel.write({"note": _("No backorder planned by the supplier.")}) # Reset Operations moves[0].picking_id.do_prepare_partial() diff --git a/despatch_advice_import/wizard/despatch_advice_import.xml b/despatch_advice_import/wizard/despatch_advice_import.xml index e353c40d1b..e34808e779 100644 --- a/despatch_advice_import/wizard/despatch_advice_import.xml +++ b/despatch_advice_import/wizard/despatch_advice_import.xml @@ -1,9 +1,7 @@ - - despatch.advice.import (in purchase_order_import) despatch.advice.import @@ -42,5 +40,4 @@ - diff --git a/despatch_advice_import_ubl/README.rst b/despatch_advice_import_ubl/README.rst index b4e343fe8d..5131e5a3a6 100644 --- a/despatch_advice_import_ubl/README.rst +++ b/despatch_advice_import_ubl/README.rst @@ -43,7 +43,7 @@ To use this module, you need to: Known issues / Roadmap ====================== -* ... + Bug Tracker =========== diff --git a/despatch_advice_import_ubl/__manifest__.py b/despatch_advice_import_ubl/__manifest__.py index f5baae7179..f5e417aae3 100644 --- a/despatch_advice_import_ubl/__manifest__.py +++ b/despatch_advice_import_ubl/__manifest__.py @@ -3,17 +3,16 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). { - 'name': 'Despatch Advice Import Ubl', - 'summary': """ - Import Despatch Advice files""", - 'version': '10.0.1.0.0', - 'license': 'AGPL-3', - 'author': 'ACSONE SA/NV,Odoo Community Association (OCA)', - 'depends': ['despatch_advice_import','base_ubl' + "name": "Despatch Advice Import Ubl", + "summary": "Import Despatch Advice files", + "version": "10.0.1.0.0", + "license": "AGPL-3", + "author": "ACSONE SA/NV,Odoo Community Association (OCA)", + "depends": [ + "despatch_advice_import", + "base_ubl", ], - 'data': [ - ], - 'demo': [ - ], - 'installable': True, + "data": [], + "demo": [], + "installable": True, } diff --git a/despatch_advice_import_ubl/wizard/despatch_advice_import.py b/despatch_advice_import_ubl/wizard/despatch_advice_import.py index 705804baa4..af5712b787 100644 --- a/despatch_advice_import_ubl/wizard/despatch_advice_import.py +++ b/despatch_advice_import_ubl/wizard/despatch_advice_import.py @@ -20,17 +20,21 @@ def parse_xml_despatch_advice(self, xml_root): if xml_root.tag == start_tag + "DespatchAdvice-2}DespatchAdvice": return self.parse_ubl_despatch_advice(xml_root) else: - return super(DespatchAdviceImport, self).parse_xml_despatch_advice(xml_root) - + return super(DespatchAdviceImport, self).parse_xml_despatch_advice( + xml_root + ) @api.model def parse_ubl_despatch_advice(self, xml_root): ns = xml_root.nsmap main_xmlns = ns.pop("DespatchAdvice") ns["main"] = main_xmlns - date_xpath = xml_root.xpath("/main:DespatchAdvice/cbc:IssueDate", namespaces=ns) + date_xpath = xml_root.xpath( + "/main:DespatchAdvice/cbc:IssueDate", namespaces=ns + ) estimated_delivery_date_xpath = xml_root.xpath( - "/main:DespatchAdvice/cac:Shipment/cac:Delivery/cac:EstimatedDeliveryPeriod/cbc:EndDate", + "/main:DespatchAdvice/cac:Shipment/" + "cac:Delivery/cac:EstimatedDeliveryPeriod/cbc:EndDate", namespaces=ns, ) order_reference_xpath = xml_root.xpath( @@ -40,13 +44,15 @@ def parse_ubl_despatch_advice(self, xml_root): "/main:DespatchAdvice/cbc:DespatchAdviceTypeCode", namespaces=ns ) supplier_xpath = xml_root.xpath( - "/main:DespatchAdvice/cac:DespatchSupplierParty/cac:Party", namespaces=ns + "/main:DespatchAdvice/cac:DespatchSupplierParty/cac:Party", + namespaces=ns, ) supplier_dict = self.ubl_parse_party(supplier_xpath[0], ns) # We only take the "official references" for supplier_dict supplier_dict = {"vat": supplier_dict.get("vat")} customer_xpath = xml_root.xpath( - "/main:DespatchAdvice/cac:DeliveryCustomerParty/cac:Party", namespaces=ns + "/main:DespatchAdvice/cac:DeliveryCustomerParty/cac:Party", + namespaces=ns, ) customer_dict = self.ubl_parse_party(customer_xpath[0], ns) @@ -61,7 +67,9 @@ def parse_ubl_despatch_advice(self, xml_root): "ref": order_reference_xpath[0].text, "supplier": supplier_dict, "company": customer_dict, - "despatch_advice_type_code": despatch_advice_type_code_xpath[0].text, + "despatch_advice_type_code": despatch_advice_type_code_xpath[ + 0 + ].text, "date": len(date_xpath) and date_xpath[0].text, "estimated_delivery_date": len(estimated_delivery_date_xpath) and estimated_delivery_date_xpath[0].text, @@ -74,7 +82,9 @@ def parse_ubl_despatch_advice_line(self, line, ns): line_id_xpath = line.xpath("cbc:ID", namespaces=ns) qty_xpath = line.xpath("cbc:DeliveredQuantity", namespaces=ns) qty = float(qty_xpath[0].text) - backorder_qty_xpath = line.xpath("cbc:OutstandingQuantity", namespaces=ns) + backorder_qty_xpath = line.xpath( + "cbc:OutstandingQuantity", namespaces=ns + ) backorder_qty = None if backorder_qty_xpath and len(backorder_qty_xpath): backorder_qty = float(backorder_qty_xpath[0].text) @@ -97,7 +107,9 @@ def ubl_parse_party(self, party_node, ns): "cac:PartyLegalEntity/cbc:RegistrationName", namespaces=ns ) - vat_xpath = party_node.xpath("cac:PartyIdentification/cbc:ID", namespaces=ns) + vat_xpath = party_node.xpath( + "cac:PartyIdentification/cbc:ID", namespaces=ns + ) partner_dict = { "vat": vat_xpath[0].text