From 4488bfa9277ceb2612fe50710f4e72738f1eb468 Mon Sep 17 00:00:00 2001 From: szalatyzuzanna Date: Tue, 17 Sep 2024 11:19:33 +0100 Subject: [PATCH] [FIX] pre-commit --- .copier-answers.yml | 0 .github/workflows/pre-commit.yml | 0 .github/workflows/stale.yml | 0 LICENSE | 0 README.md | 0 bc3_importer/LICENSE | 0 bc3_importer/README.rst | 2 +- bc3_importer/__manifest__.py | 5 - bc3_importer/models/bc3_file.py | 2 +- bc3_importer/models/bc3_version.py | 44 +- bc3_importer/models/product_product.py | 2 +- bc3_importer/models/sale_order.py | 5 +- bc3_importer/readme/CONTRIBUTORS.rst | 0 bc3_importer/readme/DESCRIPTION.rst | 0 bc3_importer/static/description/icon.png | Bin bc3_importer/static/description/index.html | 2 +- bc3_importer/wizard/bc3_import_wizard.py | 1003 ++++++++++---------- setup/.setuptools-odoo-make-default-ignore | 0 setup/README | 0 setup/bc3_importer/setup.py | 0 20 files changed, 542 insertions(+), 523 deletions(-) mode change 100644 => 100755 .copier-answers.yml mode change 100644 => 100755 .github/workflows/pre-commit.yml mode change 100644 => 100755 .github/workflows/stale.yml mode change 100644 => 100755 LICENSE mode change 100644 => 100755 README.md mode change 100644 => 100755 bc3_importer/LICENSE mode change 100644 => 100755 bc3_importer/readme/CONTRIBUTORS.rst mode change 100644 => 100755 bc3_importer/readme/DESCRIPTION.rst mode change 100644 => 100755 bc3_importer/static/description/icon.png mode change 100644 => 100755 bc3_importer/static/description/index.html mode change 100644 => 100755 setup/.setuptools-odoo-make-default-ignore mode change 100644 => 100755 setup/README mode change 100644 => 100755 setup/bc3_importer/setup.py diff --git a/.copier-answers.yml b/.copier-answers.yml old mode 100644 new mode 100755 diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml old mode 100644 new mode 100755 diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml old mode 100644 new mode 100755 diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/bc3_importer/LICENSE b/bc3_importer/LICENSE old mode 100644 new mode 100755 diff --git a/bc3_importer/README.rst b/bc3_importer/README.rst index 8a56cf5..38c2bc6 100644 --- a/bc3_importer/README.rst +++ b/bc3_importer/README.rst @@ -7,7 +7,7 @@ BC3 Connector !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:38bc1203bf2790d2d9824e92585efb60fc59fe150c7bdba0944459f3a1704100 + !! source digest: sha256:c34cbd1b192b73e97d7be9a5628abde9082ddd06eb0814fd02f2ce0e47c4c43b !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png diff --git a/bc3_importer/__manifest__.py b/bc3_importer/__manifest__.py index 81cefb3..afb2c79 100644 --- a/bc3_importer/__manifest__.py +++ b/bc3_importer/__manifest__.py @@ -4,15 +4,10 @@ BC3 Connector.""", "author": "Binhex, Odoo Community Association (OCA)", "website": "https://github.com/OCA/vertical-construction", - # Categories can be used to filter modules in modules listing - # Check https://github.com/odoo/odoo/blob/14.0/odoo/addons/base/data/ir_module_category_data.xml - # for the full list "category": "Sales/Sales", "version": "14.0.1.0.0", "license": "AGPL-3", - # any module necessary for this one to work correctly "depends": ["base", "sale", "project", "uom", "sale_management"], - # always loaded "data": [ "security/bc3_file_security.xml", "security/ir.model.access.csv", diff --git a/bc3_importer/models/bc3_file.py b/bc3_importer/models/bc3_file.py index b840e72..404cbb7 100644 --- a/bc3_importer/models/bc3_file.py +++ b/bc3_importer/models/bc3_file.py @@ -1,4 +1,4 @@ -from odoo import _, api, fields, models, tools +from odoo import fields, models class Bc3File(models.Model): diff --git a/bc3_importer/models/bc3_version.py b/bc3_importer/models/bc3_version.py index e8b4937..941be24 100644 --- a/bc3_importer/models/bc3_version.py +++ b/bc3_importer/models/bc3_version.py @@ -1,13 +1,11 @@ import logging -import re from iteration_utilities import duplicates -from odoo import _, api, fields, models, tools -from odoo.exceptions import UserError, ValidationError +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError _logger = logging.getLogger(__name__) -import regex class Bc3Version(models.Model): @@ -55,7 +53,13 @@ class Bc3VersionRegister(models.Model): "Model", required=True, ondelete="cascade", - domain="['|','|',('model', '=', 'sale.order'),('model', '=', 'sale.order.line'),('model', '=', 'product.product')]", + domain=[ + "|", + "|", + ("model", "=", "sale.order"), + ("model", "=", "sale.order.line"), + ("model", "=", "product.product"), + ], ) edit_existent = fields.Boolean("The register may edit existent records") @@ -70,7 +74,20 @@ class Bc3VersionRegisterRule(models.Model): field_id = fields.Many2one( "ir.model.fields", "Field", - domain="[('model_id', '=', model_id),('ttype','not in',['many2one_reference','reference','serialized','job_serialized','selection'])]", + domain=[ + ("model_id", "=", model_id), + ( + "ttype", + "not in", + [ + "many2one_reference", + "reference", + "serialized", + "job_serialized", + "selection", + ], + ), + ], ondelete="cascade", ) register_id = fields.Many2one( @@ -82,6 +99,19 @@ class Bc3VersionRegisterRule(models.Model): field_ids = fields.Many2many( "ir.model.fields", string="Field", - domain="[('model_id', '=', model_id),('ttype','not in',['many2one_reference','reference','serialized','job_serialized','selection'])]", + domain=[ + ("model_id", "=", model_id), + ( + "ttype", + "not in", + [ + "many2one_reference", + "reference", + "serialized", + "job_serialized", + "selection", + ], + ), + ], ondelete="cascade", ) diff --git a/bc3_importer/models/product_product.py b/bc3_importer/models/product_product.py index 68b60d8..5263a06 100644 --- a/bc3_importer/models/product_product.py +++ b/bc3_importer/models/product_product.py @@ -1,4 +1,4 @@ -from odoo import _, api, fields, models +from odoo import fields, models class Product(models.Model): diff --git a/bc3_importer/models/sale_order.py b/bc3_importer/models/sale_order.py index a8e0fd7..df67ea3 100644 --- a/bc3_importer/models/sale_order.py +++ b/bc3_importer/models/sale_order.py @@ -1,7 +1,4 @@ -from datetime import datetime, timedelta - -from odoo import SUPERUSER_ID, _, api, fields, models -from odoo.exceptions import AccessError, UserError, ValidationError +from odoo import fields, models class SaleOrder(models.Model): diff --git a/bc3_importer/readme/CONTRIBUTORS.rst b/bc3_importer/readme/CONTRIBUTORS.rst old mode 100644 new mode 100755 diff --git a/bc3_importer/readme/DESCRIPTION.rst b/bc3_importer/readme/DESCRIPTION.rst old mode 100644 new mode 100755 diff --git a/bc3_importer/static/description/icon.png b/bc3_importer/static/description/icon.png old mode 100644 new mode 100755 diff --git a/bc3_importer/static/description/index.html b/bc3_importer/static/description/index.html old mode 100644 new mode 100755 index a193230..76bb053 --- a/bc3_importer/static/description/index.html +++ b/bc3_importer/static/description/index.html @@ -368,7 +368,7 @@

BC3 Connector

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:38bc1203bf2790d2d9824e92585efb60fc59fe150c7bdba0944459f3a1704100 +!! source digest: sha256:c34cbd1b192b73e97d7be9a5628abde9082ddd06eb0814fd02f2ce0e47c4c43b !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Beta License: AGPL-3 OCA/vertical-construction Translate me on Weblate Try me on Runboat

Importer of quotations in bc3 format.

diff --git a/bc3_importer/wizard/bc3_import_wizard.py b/bc3_importer/wizard/bc3_import_wizard.py index 813d24e..b46d358 100644 --- a/bc3_importer/wizard/bc3_import_wizard.py +++ b/bc3_importer/wizard/bc3_import_wizard.py @@ -1,19 +1,15 @@ import base64 -import logging +import io import os import re import tempfile from datetime import datetime -from odoo import _, api, fields, models -from odoo.exceptions import UserError, ValidationError - -_logger = logging.getLogger(__name__) -import codecs -import io - import chardet +from odoo import _, api, fields, models +from odoo.exceptions import UserError + BC3_PRODUCTS = {} created_product = False parse_later = [] @@ -51,7 +47,7 @@ def _default_version(self): "product.product", string="Default product", ondelete="cascade", - help="Select a product which will be used in case a product is not specified in the BC3 file.", + help="Select a product which will be used in the BC3 file.", ) sale_id = fields.Many2one("sale.order", "Sale Order") sequence = fields.Integer() @@ -116,7 +112,7 @@ def do_action(self): line_ids.append(s.id) s.write({"sequence": seq}) seq += 1 - for l in ( + for line in ( self.env["sale.order.line"] .sudo() .search( @@ -127,21 +123,21 @@ def do_action(self): ) .sorted("name") ): - if l: + if line: if ( - (l.price_unit == 1 and l.product_uom_qty == 1) - or (l.price_unit == 0 and l.product_uom_qty == 1) - or ("%" in l.code) - or (l.price_unit == 1) - or not l.price_subtotal + (line.price_unit == 1 and line.product_uom_qty == 1) + or (line.price_unit == 0 and line.product_uom_qty == 1) + or ("%" in line.code) + or (line.price_unit == 1) + or not line.price_subtotal ): - l.sudo().unlink() - elif l.id not in line_ids: - line_ids.append(l.id) - l.sudo().write({"sequence": seq}) + line.sudo().unlink() + elif line.id not in line_ids: + line_ids.append(line.id) + line.sudo().write({"sequence": seq}) seq += 1 elif not s and key == "0": - for l in ( + for line in ( self.env["sale.order.line"] .sudo() .search( @@ -152,17 +148,17 @@ def do_action(self): ) .sorted("name") ): - if l: + if line: if ( - (l.price_unit == 1 and l.product_uom_qty == 1) - or (l.price_unit == 0 and l.product_uom_qty == 1) - or ("%" in l.code) - or (l.price_unit == 1) + (line.price_unit == 1 and line.product_uom_qty == 1) + or (line.price_unit == 0 and line.product_uom_qty == 1) + or ("%" in line.code) + or (line.price_unit == 1) ): - l.sudo().unlink() + line.sudo().unlink() else: - line_ids.append(l.id) - l.sudo().write({"sequence": seq}) + line_ids.append(line.id) + line.sudo().write({"sequence": seq}) seq += 1 for s in self.env["sale.order.line"].search( [("order_id", "=", self.sale_id.id)], order="sequence asc" @@ -199,7 +195,7 @@ def do_action(self): .sudo() .search([("code", "=", c), ("order_id", "=", self.sale_id.id)]) ) - if line and not c in lines: + if line and not (c in lines): line.sudo().unlink() return { "name": _("Show Sale Order"), @@ -250,7 +246,6 @@ def _search_create_product(self, code): product = self.env["product.template"].search( [("default_code", "ilike", code[0])], limit=1 ) - created_product = False if product: return product else: @@ -267,7 +262,6 @@ def _search_create_product(self, code): "default_code": code_temp, } ) - created_product = True else: # Por defecto se ponen unidades product = self.env.ref("bc3_importer.product_product_product_units") @@ -306,211 +300,29 @@ def _parse_register_edit_sale_order_line( if len(parsed_line) == len(rules): primary_key_id = parsed_line[0][0] existent_line = self.search_line(primary_key_id.replace("#", "")) - existent_lines = self.search_lines(primary_key_id.replace("#", "")) parent_seq = False # Está dentro de un capítulo if existent_line: parent_seq = existent_line.sequence elif "#" in primary_key_id and not existent_line: - existent_line = ( - self.env["sale.order.line"] - .sudo() - .create( - { - "name": primary_key_id.replace("#", ""), - "display_type": "line_section", - "code": primary_key_id.replace("#", ""), - "order_id": self.sale_id.id, - } - ) - ) + existent_line = self._create_line_section(primary_key_id) i = 0 seq = False line = {} - recursive = False while i < len(rules): # Repetidos if rules[i]["id"] in rule_ids: if rules[i] in dependent_rules: - recursive = True - z = 0 - while z < len(parsed_line[i]): - j = i - counter = 0 - temp_line = {} - if parent_seq: - seq = parent_seq + 1 - # self.lines_reorder(seq) - else: - seq = self.sequence - self.sequence += 1 - while counter < len(dependent_rules[rules[i]]): - temp_line[ - dependent_rules[rules[i]][counter]["field_id"][ - "name" - ] - ] = parsed_line[j][z] - j += 1 - counter += 1 - z += 1 - temp_line["sequence"] = seq - sale_order_line = False - if "code" in temp_line: - sale_order_line = self.env["sale.order.line"].search( - [ - ("order_id", "=", self.sale_id.id), - ("code", "=", temp_line["code"]), - ] - ) - if len(sale_order_line) > 1: - if existent_line: - chapter = existent_line.code - for s in sale_order_line: - if ( - chapter in lines - and s.id in lines[chapter] - ): - sale_order_line = s - else: - create_line = True - sale_order_line = False - if sale_order_line: - create_line = False - if ( - existent_line - and not existent_line.id == sale_order_line.id - and not existent_line.display_type - and not sale_order_line.display_type - ): - if not self.line_in_any_dict(sale_order_line.id): - erase_lines.append(temp_line["code"]) - continue - if ( - existent_line - and not existent_line.id == sale_order_line.id - and lines - ): - if ( - not self.line_in_dict( - existent_line.code, sale_order_line.id - ) - and not sale_order_line.id - in self.sale_id.order_line.ids - ): - create_line = True - elif self.line_in_any_dict(sale_order_line.id): - create_line = True - if create_line: - sale_order_line = sale_order_line.copy( - { - "order_id": self.sale_id.id, - "price_unit": sale_order_line.price_unit, - } - ) - if ( - sale_order_line - and "price_unit" in temp_line - and float(temp_line["price_unit"]) == 1.0 - ): - temp_line[ - "price_unit" - ] = sale_order_line.price_unit - sale_order_line.sudo().write(temp_line) - else: - if ( - "product_uom_qty" in temp_line - and float(temp_line["product_uom_qty"]) == 1.0 - and sale_order_line.product_uom_qty - and not sale_order_line.display_type - ): - temp_line[ - "product_uom_qty" - ] = sale_order_line.product_uom_qty - elif not sale_order_line.product_uom_qty == 1: - temp_line["product_uom_qty"] = ( - float(temp_line["product_uom_qty"]) - + sale_order_line.product_uom_qty - ) - if ( - "price_unit" in temp_line - and float(temp_line["price_unit"]) == 1.0 - and not sale_order_line.display_type - ): - temp_line[ - "price_unit" - ] = sale_order_line.price_unit - if "name" in temp_line and sale_order_line.name: - temp_line["name"] = ( - sale_order_line.name - + "-" - + temp_line["name"] - ) - if sale_order_line.display_type: - temp_line["product_uom_qty"] = 0 - temp_line["price_unit"] = 0 - sale_order_line.sudo().write(temp_line) - if ( - existent_line - and not existent_line.id == sale_order_line.id - and existent_line.display_type - and existent_line.display_type == "line_section" - ): - if existent_line.code in lines: - lines[existent_line.code].append( - sale_order_line.id - ) - else: - lines[existent_line.code] = [sale_order_line.id] - else: - - product = self.env.ref( - "bc3_importer.product_product_product_units" - ) - if "code" in temp_line: - temp_line["name"] = ( - temp_line["code"] - or product.default_code - or "Line" - ) - else: - temp_line["name"] = product.default_code or "Line" - temp_line["product_id"] = product.id - temp_line["product_uom"] = product.uom_id.id - temp_line["order_id"] = self.sale_id.id - temp_line["sequence"] = seq - if ( - "price_unit" in temp_line - and float(temp_line["price_unit"]) == 1.0 - ): - s = self.env["sale.order.line"].search( - [ - ("order_id", "=", self.sale_id.id), - ("code", "=", temp_line["code"]), - ("price_unit", ">", 1), - ], - limit=1, - ) - if s: - temp_line["price_unit"] = s.price_unit - sale_order_line = self.env["sale.order.line"].create( - temp_line - ) - if ( - existent_line - and not existent_line.id == sale_order_line.id - and existent_line.display_type - and existent_line.display_type == "line_section" - ): - if existent_line.code in lines: - lines[existent_line.code].append( - sale_order_line.id - ) - else: - lines[existent_line.code] = [sale_order_line.id] - if line: - line = {} + self._process_dependent_rules( + parsed_line[i], + rules[i], + dependent_rules[rules[i]], + existent_line, + line, + i, + ) # Únicos else: if rules[i]["field_id"]["name"]: @@ -526,78 +338,225 @@ def _parse_register_edit_sale_order_line( i += 1 # Solo cuando actualiza un dato -> lo hago para todos if line: - s = False - if "code" in line: - line["code"] = line["code"].replace("#", "") - s = self.env["sale.order.line"].search( - [ - ("order_id", "=", self.sale_id.id), - ("code", "=", line["code"].replace("#", "")), - ] - ) - if s: - for sale_order_line in s: - if sale_order_line.code in erase_lines: - erase_lines.remove(sale_order_line.code) - if ( - "product_uom_qty" in line - and sale_order_line.product_uom_qty - and not sale_order_line.display_type - ): - line["product_uom_qty"] = float( - line["product_uom_qty"] - ) + float(sale_order_line.product_uom_qty) - if ( - "price_unit" in line - and sale_order_line.price_unit - and sale_order_line.price_unit > 1 - and line["price_unit"] == 1 - and not sale_order_line.display_type - ): - line["price_unit"] = sale_order_line.price_unit - if "name" in line and sale_order_line.name: - if sale_order_line.name not in line["name"]: - line["name"] = ( - sale_order_line.name + "- " + line["name"] - ) - if sale_order_line.display_type: - line["product_uom_qty"] = 0 - line["price_unit"] = 0 - sale_order_line.sudo().write(line) - - else: - product = self.env.ref("bc3_importer.product_product_product_units") - - if "code" in line: - if "name" in line: - line["name"] = ( - line["code"] or product.default_code or "Line" - ) + line["name"] - else: - line["name"] = ( - line["code"] or product.default_code or "Line" - ) - else: - if "name" in line: - line["name"] = (product.default_code or "Line") + line[ - "name" - ] - else: - line["name"] = product.default_code or "Line" - line["product_id"] = product.id - line["product_uom"] = product.uom_id.id - line["order_id"] = self.sale_id.id - line["sequence"] = seq - sale_order_line = self.env["sale.order.line"].create(line) + self._update_sale_order_line(line, seq) return - @api.model - def search_eq_line(self, line, line_dict): - sale_order_line = self.env["sale.order.line"].search( - [("order_id", "=", self.sale_id.id), ("code", "=", seq)], limit=1 + def _create_line_section(self, primary_key_id): + return ( + self.env["sale.order.line"] + .sudo() + .create( + { + "name": primary_key_id.replace("#", ""), + "display_type": "line_section", + "code": primary_key_id.replace("#", ""), + "order_id": self.sale_id.id, + } + ) ) - return sale_order_line.sequence or False + + def _process_dependent_rules( + self, parsed_line, rule, dependent_rules, existent_line, line, i + ): + z = 0 + while z < len(parsed_line): + j = i + counter = 0 + temp_line = {} + if existent_line: + seq = existent_line.sequence + 1 + # self.lines_reorder(seq) + else: + seq = self.sequence + self.sequence += 1 + while counter < len(dependent_rules): + temp_line[dependent_rules[counter]["field_id"]["name"]] = parsed_line[ + j + ][z] + j += 1 + counter += 1 + z += 1 + temp_line["sequence"] = seq + sale_order_line = False + if "code" in temp_line: + sale_order_line = self.env["sale.order.line"].search( + [ + ("order_id", "=", self.sale_id.id), + ("code", "=", temp_line["code"]), + ] + ) + if len(sale_order_line) > 1: + if existent_line: + chapter = existent_line.code + for s in sale_order_line: + if chapter in lines and s.id in lines[chapter]: + sale_order_line = s + else: + sale_order_line = False + if sale_order_line: + self._update_existing_line(sale_order_line, temp_line, existent_line) + else: + self._create_new_line(temp_line, existent_line, seq) + + def _update_existing_line(self, sale_order_line, temp_line, existent_line): + create_line = False + if ( + existent_line + and not existent_line.id == sale_order_line.id + and not existent_line.display_type + and not sale_order_line.display_type + ): + if not self.line_in_any_dict(sale_order_line.id): + erase_lines.append(temp_line["code"]) + if existent_line and not existent_line.id == sale_order_line.id and lines: + if not self.line_in_dict(existent_line.code, sale_order_line.id) and not ( + sale_order_line.id in self.sale_id.order_line.ids + ): + create_line = True + elif self.line_in_any_dict(sale_order_line.id): + create_line = True + if create_line: + sale_order_line = sale_order_line.copy( + { + "order_id": self.sale_id.id, + "price_unit": sale_order_line.price_unit, + } + ) + if ( + sale_order_line + and "price_unit" in temp_line + and float(temp_line["price_unit"]) == 1.0 + ): + temp_line["price_unit"] = sale_order_line.price_unit + sale_order_line.sudo().write(temp_line) + else: + if ( + "product_uom_qty" in temp_line + and float(temp_line["product_uom_qty"]) == 1.0 + and sale_order_line.product_uom_qty + and not sale_order_line.display_type + ): + temp_line["product_uom_qty"] = sale_order_line.product_uom_qty + elif not sale_order_line.product_uom_qty == 1: + temp_line["product_uom_qty"] = ( + float(temp_line["product_uom_qty"]) + + sale_order_line.product_uom_qty + ) + if ( + "price_unit" in temp_line + and float(temp_line["price_unit"]) == 1.0 + and not sale_order_line.display_type + ): + temp_line["price_unit"] = sale_order_line.price_unit + if "name" in temp_line and sale_order_line.name: + temp_line["name"] = sale_order_line.name + "-" + temp_line["name"] + if sale_order_line.display_type: + temp_line["product_uom_qty"] = 0 + temp_line["price_unit"] = 0 + sale_order_line.sudo().write(temp_line) + if ( + existent_line + and not existent_line.id == sale_order_line.id + and existent_line.display_type + and existent_line.display_type == "line_section" + ): + if existent_line.code in lines: + lines[existent_line.code].append(sale_order_line.id) + else: + lines[existent_line.code] = [sale_order_line.id] + + def _create_new_line(self, temp_line, existent_line, seq): + product = self.env.ref("bc3_importer.product_product_product_units") + if "code" in temp_line: + temp_line["name"] = temp_line["code"] or product.default_code or "Line" + else: + temp_line["name"] = product.default_code or "Line" + temp_line["product_id"] = product.id + temp_line["product_uom"] = product.uom_id.id + temp_line["order_id"] = self.sale_id.id + temp_line["sequence"] = seq + if "price_unit" in temp_line and float(temp_line["price_unit"]) == 1.0: + s = self.env["sale.order.line"].search( + [ + ("order_id", "=", self.sale_id.id), + ("code", "=", temp_line["code"]), + ("price_unit", ">", 1), + ], + limit=1, + ) + if s: + temp_line["price_unit"] = s.price_unit + sale_order_line = self.env["sale.order.line"].create(temp_line) + if ( + existent_line + and not existent_line.id == sale_order_line.id + and existent_line.display_type + and existent_line.display_type == "line_section" + ): + if existent_line.code in lines: + lines[existent_line.code].append(sale_order_line.id) + else: + lines[existent_line.code] = [sale_order_line.id] + + def _update_sale_order_line(self, line, seq): + s = False + if "code" in line: + line["code"] = line["code"].replace("#", "") + s = self.env["sale.order.line"].search( + [ + ("order_id", "=", self.sale_id.id), + ("code", "=", line["code"].replace("#", "")), + ] + ) + if s: + for sale_order_line in s: + if sale_order_line.code in erase_lines: + erase_lines.remove(sale_order_line.code) + if ( + "product_uom_qty" in line + and sale_order_line.product_uom_qty + and not sale_order_line.display_type + ): + line["product_uom_qty"] = float(line["product_uom_qty"]) + float( + sale_order_line.product_uom_qty + ) + if ( + "price_unit" in line + and sale_order_line.price_unit + and sale_order_line.price_unit > 1 + and line["price_unit"] == 1 + and not sale_order_line.display_type + ): + line["price_unit"] = sale_order_line.price_unit + if "name" in line and sale_order_line.name: + if sale_order_line.name not in line["name"]: + line["name"] = sale_order_line.name + "- " + line["name"] + if sale_order_line.display_type: + line["product_uom_qty"] = 0 + line["price_unit"] = 0 + sale_order_line.sudo().write(line) + + else: + product = self.env.ref("bc3_importer.product_product_product_units") + + if "code" in line: + if "name" in line: + line["name"] = ( + line["code"] or product.default_code or "Line" + ) + line["name"] + else: + line["name"] = line["code"] or product.default_code or "Line" + else: + if "name" in line: + line["name"] = (product.default_code or "Line") + line["name"] + else: + line["name"] = product.default_code or "Line" + line["product_id"] = product.id + line["product_uom"] = product.uom_id.id + line["order_id"] = self.sale_id.id + line["sequence"] = seq + sale_order_line = self.env["sale.order.line"].create(line) @api.model def search_seq_line(self, seq): @@ -639,6 +598,50 @@ def lines_reorder(self, seq): s.write({"sequence": s.sequence + 1}) return + def _rule_sale_order_line(self, rule, parsed_line, i, line, product): + if (not rule.field_id.relation) or ( + rule.field_id.relation and rule.field_id.relation == "product.template" + ): + if ( + not rule.field_id.name == "product_template_id" + and not rule.field_id.name == "categ_id" + ): + if len(parsed_line[i]) == 1 and parsed_line[i]: + line[rule.field_id.name] = self._parse_data( + parsed_line[i][0], rule.field_id.ttype + ) + elif len(parsed_line[i]) > 1: + if rule.field_id.name in line: + line[rule.field_id.name] += self._parse_child_data( + parsed_line[i], rule.field_id.ttype + ) + else: + line[rule.field_id.name] = self._parse_child_data( + parsed_line[i], rule.field_id.ttype + ) + elif rule.field_id.name == "product_template_id": + if len(parsed_line[i]) == 1 and parsed_line[i]: + product_name = self._parse_data( + parsed_line[i][0], rule.field_id.ttype + ) + elif rule.field_id.relation and rule.field_id.relation == "uom.uom": + if len(parsed_line[i]) == 1 and parsed_line[i]: + uom_id = int(self._search_create_uom(parsed_line[i][0])) + line[rule.field_id.name] = uom_id + if product and product.uom_id and not product.uom_id.id == uom_id: + if created_product: + product.uom_id = uom_id + else: + if uom_id in BC3_PRODUCTS: + product = BC3_PRODUCTS[uom_id] + else: + product = self.env.ref( + "bc3_importer.product_product_product_units" + ) + line["product_id"] = product.id + line["product_uom"] = product.uom_id.id + return line, product_name + @api.model def _parse_register_sale_order_line( self, parsed_line, rules, current_register, red=False @@ -646,7 +649,6 @@ def _parse_register_sale_order_line( product_name = "" if len(parsed_line) == len(rules): # Se busca el codigo del producto - is_section = False if not len(parsed_line[0]) > 0: return if len(parsed_line[0]) > 0 and "%" in parsed_line[0][0]: @@ -654,68 +656,16 @@ def _parse_register_sale_order_line( line_t = self.search_lines(parsed_line[0][0]) product = self._search_create_product(parsed_line[0]) if not line_t: - line = { - "name": product.default_code or parsed_line[0], - "product_id": product.id, - "product_uom_qty": 1, - "qty_delivered": 1, - "product_uom": product.uom_id.id, - "order_id": self.sale_id.id, - "sequence": self.sequence, - } - self.sequence += 1 + line = self._create_sale_order_line(parsed_line, rules, product) else: line = {} i = len(rules) - 1 for rule in rules.sorted(key="sequence", reverse=True): # Sale order line if rule.model_id.model == "sale.order.line": - if (not rule.field_id.relation) or ( - rule.field_id.relation - and rule.field_id.relation == "product.template" - ): - if ( - not rule.field_id.name == "product_template_id" - and not rule.field_id.name == "categ_id" - ): - if len(parsed_line[i]) == 1 and parsed_line[i]: - line[rule.field_id.name] = self._parse_data( - parsed_line[i][0], rule.field_id.ttype - ) - elif len(parsed_line[i]) > 1: - if rule.field_id.name in line: - line[rule.field_id.name] += self._parse_child_data( - parsed_line[i], rule.field_id.ttype - ) - else: - line[rule.field_id.name] = self._parse_child_data( - parsed_line[i], rule.field_id.ttype - ) - elif rule.field_id.name == "product_template_id": - if len(parsed_line[i]) == 1 and parsed_line[i]: - product_name = self._parse_data( - parsed_line[i][0], rule.field_id.ttype - ) - elif rule.field_id.relation and rule.field_id.relation == "uom.uom": - if len(parsed_line[i]) == 1 and parsed_line[i]: - uom_id = int(self._search_create_uom(parsed_line[i][0])) - line[rule.field_id.name] = uom_id - if ( - product - and product.uom_id - and not product.uom_id.id == uom_id - ): - if created_product: - product.uom_id = uom_id - else: - if uom_id in BC3_PRODUCTS: - product = BC3_PRODUCTS[uom_id] - else: - product = self.env.ref( - "bc3_importer.product_product_product_units" - ) - line["product_id"] = product.id - line["product_uom"] = product.uom_id.id + line, product_name = self._rule_sale_order_line( + rule, parsed_line, i, line, product + ) elif rule.model_id.model == "product.template": if len(parsed_line[i]) == 1: line_type = int(self._parse_data(parsed_line[i][0], "char")) @@ -728,53 +678,68 @@ def _parse_register_sale_order_line( if self.create_products: product.name = product_name if not line_t: - if "display_type" in line: - line["price_unit"] = 0.0 - line["product_id"] = False - line["product_uom_qty"] = 0.0 - sale_order_line = self.env["sale.order.line"].create(line) - if ( - sale_order_line.display_type - and sale_order_line.display_type == "line_note" - ): - if "0" in lines: - lines["0"].append(sale_order_line.id) - else: - lines["0"] = [sale_order_line.id] + self._create_new_sale_order_line(line) else: - for t in line_t: - if t.display_type: - line["price_unit"] = 0.0 - line["product_id"] = False - line["product_uom_qty"] = 0.0 + self._update_existing_sale_order_line(line, line_t) - if "display_type" in line and not t.display_type: - if not t.product_uom_qty > 1: - a = t.read(["sequence", "code"])[0] - a["order_id"] = self.sale_id.id - a.update(line) - t.unlink() - sale_order_line = self.env["sale.order.line"].create(a) - if ( - sale_order_line.display_type - and sale_order_line.display_type == "line_note" - ): - if "0" in lines: - lines["0"].append(sale_order_line.id) - else: - lines["0"] = [sale_order_line.id] + def _create_sale_order_line(self, parsed_line, rules, product): + line = { + "name": product.default_code or parsed_line[0], + "product_id": product.id, + "product_uom_qty": 1, + "qty_delivered": 1, + "product_uom": product.uom_id.id, + "order_id": self.sale_id.id, + "sequence": self.sequence, + } + self.sequence += 1 + return line + + def _create_new_sale_order_line(self, line): + if "display_type" in line: + line["price_unit"] = 0.0 + line["product_id"] = False + line["product_uom_qty"] = 0.0 + sale_order_line = self.env["sale.order.line"].create(line) + if sale_order_line.display_type and sale_order_line.display_type == "line_note": + if "0" in lines: + lines["0"].append(sale_order_line.id) + else: + lines["0"] = [sale_order_line.id] + + def _update_existing_sale_order_line(self, line, line_t): + for t in line_t: + if t.display_type: + line["price_unit"] = 0.0 + line["product_id"] = False + line["product_uom_qty"] = 0.0 + + if "display_type" in line and not t.display_type: + if not t.product_uom_qty > 1: + a = t.read(["sequence", "code"])[0] + a["order_id"] = self.sale_id.id + a.update(line) + t.unlink() + sale_order_line = self.env["sale.order.line"].create(a) + if ( + sale_order_line.display_type + and sale_order_line.display_type == "line_note" + ): + if "0" in lines: + lines["0"].append(sale_order_line.id) else: - line["display_type"] = False - t.write(line) + lines["0"] = [sale_order_line.id] + else: + line["display_type"] = False + t.write(line) + else: + t.write(line) + if t.display_type and line_t.display_type == "line_note": + if "0" in lines: + lines["0"].append(line_t.id) else: - t.write(line) - if t.display_type and line_t.display_type == "line_note": - if "0" in lines: - lines["0"].append(line_t.id) - else: - lines["0"] = [line_t.id] - return True + lines["0"] = [line_t.id] @api.model def _parse_data(self, data, field_type): @@ -785,7 +750,7 @@ def _parse_data(self, data, field_type): # if odd -> 0 if not len(data) % 2 == 0: data += "0" - ##AA + # AA if len(data) == 2: return datetime.strptime(data, "%y").date() # MMAA @@ -818,9 +783,42 @@ def _parse_child_data(self, data, field_type): def _parse_register(self, line): register_type = line[0].lower() current_register = register_type - register_line = ( - line[1:] - .rstrip() + register_line = self._clean_register_line(line[1:]) + register_rules = self._get_register_rules(register_type) + + model = self._get_model(register_rules) + register_line = self._adjust_register_line(register_line, register_rules) + + render_func = getattr(self, "_parse_register_" + model, None) + if not render_func: + raise UserError(_("Error parsing the file")) + + regular_expression = self._get_regular_expression(register_rules) + parser_result = self._parse_register_line(regular_expression, register_line) + + if len(parser_result) > 0: + final_result = self._flatten_parser_result(parser_result) + if register_rules[0].register_id.edit_existent: + repeat_value_rule, rule_ids = self._get_repeat_value_rule( + register_rules + ) + render_func = getattr(self, "_parse_register_edit_" + model, None) + if not render_func: + raise UserError(_("Error parsing the file")) + render_func( + final_result, + register_rules, + repeat_value_rule, + rule_ids, + current_register, + ) + return + else: + render_func(final_result, register_rules, current_register) + + def _clean_register_line(self, line): + return ( + line.rstrip() .replace("�", "") .replace("(", ",") .replace(")", ",") @@ -829,7 +827,9 @@ def _parse_register(self, line): .strip() .split("|") ) - register_rules = ( + + def _get_register_rules(self, register_type): + return ( self.env["bc3.version.register"] .search( [ @@ -841,92 +841,84 @@ def _parse_register(self, line): .rule_ids ) + def _get_model(self, register_rules): if ( register_rules and register_rules[0] and register_rules[0].register_id.model_id ): - model = register_rules[0].register_id.model_id.model.replace(".", "_") - register_line.pop(0) - if len(register_line) < len( - register_rules.filtered(lambda x: not x.is_child) + return register_rules[0].register_id.model_id.model.replace(".", "_") + else: + raise UserError(_("Error parsing the file")) + + def _adjust_register_line(self, register_line, register_rules): + if len(register_line) < len(register_rules.filtered(lambda x: not x.is_child)): + for _i in range( + abs( + len(register_rules.filtered(lambda x: not x.is_child)) + - len(register_line) + ) ): - for i in range( - abs( - len(register_rules.filtered(lambda x: not x.is_child)) - - len(register_line) - ) - ): - register_line.append("") - elif len(register_line) > len( - register_rules.filtered(lambda x: not x.is_child) + register_line.append("") + elif len(register_line) > len( + register_rules.filtered(lambda x: not x.is_child) + ): + for _i in range( + abs( + len(register_rules.filtered(lambda x: not x.is_child)) + - len(register_line) + ) ): - for i in range( - abs( - len(register_rules.filtered(lambda x: not x.is_child)) - - len(register_line) - ) - ): - register_line.pop() - render_func = getattr(self, "_parse_register_" + model, None) - if not render_func: - raise UserError(_("Error parsing the file")) - i = 0 - regular_expression = [] - parser_result = [] - for r in register_rules.filtered(lambda x: not x.is_child): - regular_expression.append(r.regular_expression) - if len(regular_expression) == len(register_line): - i = 0 - while i < len(regular_expression): - parser_result.append( - self._get_results( - regular_expression[i], register_line[i].replace("\n", "") - ) - ) - i += 1 + register_line.pop() + return register_line + + def _get_regular_expression(self, register_rules): + regular_expression = [] + for r in register_rules.filtered(lambda x: not x.is_child): + regular_expression.append(r.regular_expression) + return regular_expression + + def _parse_register_line(self, regular_expression, register_line): + parser_result = [] + i = 0 + while i < len(regular_expression): + parser_result.append( + self._get_results( + regular_expression[i], register_line[i].replace("\n", "") + ) + ) + i += 1 + return parser_result + + def _flatten_parser_result(self, parser_result): + final_result = [] + for i in parser_result: + if len(i) > 1: + for j in i: + final_result.append(j) + elif not len(i) == 0: + final_result.append(i[0]) else: - raise ValidationError(_("Parsing error, missing data")) - if len(parser_result) > 0: - final_result = [] - for i in parser_result: - if len(i) > 1: - for j in i: - final_result.append(j) - elif not len(i) == 0: - final_result.append(i[0]) - else: - final_result.append([]) - if register_rules[0].register_id.edit_existent: - repeat_value_rule = {} - rule_ids = [] - temp_r = [] - for r in register_rules: - if r.field_ids: - for a in register_rules.filtered( - lambda rule: rule.field_id in r.field_ids - ): - temp_r.append(a) - temp_r.insert(0, r) - repeat_value_rule[r] = temp_r - rule_ids.append(r.id) - rule_ids += register_rules.filtered( - lambda rule: rule.field_id in r.field_ids - ).ids + final_result.append([]) + return final_result - render_func = getattr(self, "_parse_register_edit_" + model, None) - if not render_func: - raise UserError(_("Error parsing the file")) - render_func( - final_result, - register_rules, - repeat_value_rule, - rule_ids, - current_register, - ) - return - else: - render_func(final_result, register_rules, current_register) + def _get_repeat_value_rule(self, register_rules): + repeat_value_rule = {} + rule_ids = [] + temp_r = [] + for r in register_rules: + if r.field_ids: + for a in register_rules.filtered( + lambda rule: rule.field_id in r.field_ids + ): + temp_r.append(a) + temp_r.insert(0, r) + repeat_value_rule[r] = temp_r + rule_ids.append(r.id) + rule_ids += register_rules.filtered( + lambda rule: rule.field_id in r.field_ids + ).ids + return repeat_value_rule, rule_ids # Parseo def get_groups(self, id_pattern, check_list, text, group_pattern): @@ -951,6 +943,40 @@ def get_groups(self, id_pattern, check_list, text, group_pattern): else: return True + def parse_match(self, matches, group_pattern, result, text): + for match in matches: + # Recorro los grupos + # Empiezo en 1 porque el primer grupo es todo el match, no me interesa + last_index = (0, 0) + if match.lastindex: + if match.lastindex > 1: + for index in range(1, match.lastindex + 1): + if str(index) in group_pattern and match.group(index): + group_pattern[str(index)]["groups"].append( + match.group(index) + ) + # Es el primer grupo + if index == 1: + last_index = match.span(index) + else: + if not last_index[1] == match.span(index)[0]: + group_pattern[str(index)]["check"].append( + (last_index[1], match.span(index)[0]) + ) + last_index = match.span(index) + else: + for index in range(1, match.lastindex + 1): + if str(index) in group_pattern and match.group(index): + group_pattern[str(index)]["groups"].append( + match.group(index) + ) + if not last_index[1] == match.span(index)[0]: + group_pattern[str(index)]["check"].append( + (last_index[1], match.span(index)[0]) + ) + last_index = match.span(index) + return group_pattern + def _get_results(self, pattern, text): text = text.rstrip() result = [] @@ -967,37 +993,8 @@ def _get_results(self, pattern, text): } counter += 1 matches = re.finditer(pattern, text) - for match in matches: - # Recorro los grupos - # Empiezo en 1 porque el primer grupo es todo el match, no me interesa - last_index = (0, 0) - if match.lastindex: - if match.lastindex > 1: - for index in range(1, match.lastindex + 1): - if str(index) in group_pattern and match.group(index): - group_pattern[str(index)]["groups"].append( - match.group(index) - ) - # Es el primer grupo - if index == 1: - last_index = match.span(index) - else: - if not last_index[1] == match.span(index)[0]: - group_pattern[str(index)]["check"].append( - (last_index[1], match.span(index)[0]) - ) - last_index = match.span(index) - else: - for index in range(1, match.lastindex + 1): - if str(index) in group_pattern and match.group(index): - group_pattern[str(index)]["groups"].append( - match.group(index) - ) - if not last_index[1] == match.span(index)[0]: - group_pattern[str(index)]["check"].append( - (last_index[1], match.span(index)[0]) - ) - last_index = match.span(index) + group_pattern = self.parse_match(matches, group_pattern, result, text) + # Reviso los checks for i in group_pattern: if len(group_pattern[i]["check"]) > 0: diff --git a/setup/.setuptools-odoo-make-default-ignore b/setup/.setuptools-odoo-make-default-ignore old mode 100644 new mode 100755 diff --git a/setup/README b/setup/README old mode 100644 new mode 100755 diff --git a/setup/bc3_importer/setup.py b/setup/bc3_importer/setup.py old mode 100644 new mode 100755