From 50bd92af9ea686f7f985664cef9c805865f6b1e2 Mon Sep 17 00:00:00 2001 From: Alexis de Lattre Date: Thu, 25 Jan 2024 00:03:35 +0100 Subject: [PATCH] [MIG] intrastat_product to v17 --- intrastat_product/__manifest__.py | 5 +- intrastat_product/hooks.py | 6 +- intrastat_product/models/account_move.py | 8 +- .../models/intrastat_product_declaration.py | 78 ++++----- .../models/intrastat_transaction.py | 6 +- .../models/intrastat_transport_mode.py | 7 +- intrastat_product/models/intrastat_unit.py | 9 + intrastat_product/models/res_company.py | 1 - .../report/intrastat_product_report_xls.py | 17 +- .../security/ir.model.access.csv | 8 +- .../static/description/index.html | 1 - intrastat_product/tests/common_purchase.py | 4 +- intrastat_product/tests/common_sale.py | 4 +- .../tests/test_purchase_order.py | 5 +- intrastat_product/tests/test_sale_order.py | 20 +-- intrastat_product/views/account_move.xml | 4 +- .../views/intrastat_product_declaration.xml | 156 ++++++++++-------- .../views/intrastat_transaction.xml | 2 +- intrastat_product/views/intrastat_unit.xml | 2 +- .../views/res_config_settings.xml | 71 ++++---- intrastat_product/views/sale_order.xml | 2 +- 21 files changed, 205 insertions(+), 211 deletions(-) diff --git a/intrastat_product/__manifest__.py b/intrastat_product/__manifest__.py index 3b88e11b4..527b83d42 100644 --- a/intrastat_product/__manifest__.py +++ b/intrastat_product/__manifest__.py @@ -7,11 +7,12 @@ { "name": "Intrastat Product", - "version": "16.0.1.6.1", + "version": "17.0.1.0.0", "category": "Intrastat", "license": "AGPL-3", "summary": "Base module for Intrastat Product", - "author": "ACSONE SA/NV, brain-tec AG, Akretion, Noviat, Odoo Community Association (OCA)", + "author": "ACSONE SA/NV, brain-tec AG, Akretion, Noviat," + " Odoo Community Association (OCA)", "website": "https://github.com/OCA/intrastat-extrastat", "depends": [ "intrastat_base", diff --git a/intrastat_product/hooks.py b/intrastat_product/hooks.py index 6877121bb..c295c3c57 100644 --- a/intrastat_product/hooks.py +++ b/intrastat_product/hooks.py @@ -3,17 +3,17 @@ import logging -def pre_init_hook(cr): +def pre_init_hook(env): """Prepopulate stored computed fields for faster installation""" logger = logging.getLogger(__name__) logger.info("Prepopulating stored computed fields") - cr.execute( + env.cr.execute( """ alter table account_move add column if not exists src_dest_country_id integer; """ ) - cr.execute( + env.cr.execute( """ with countries as ( select am.id as move_id, diff --git a/intrastat_product/models/account_move.py b/intrastat_product/models/account_move.py index abfc0c3b1..b1f622804 100644 --- a/intrastat_product/models/account_move.py +++ b/intrastat_product/models/account_move.py @@ -3,7 +3,7 @@ # @author Alexis de Lattre # @author Luc de Meyer -from odoo import api, fields, models +from odoo import Command, api, fields, models class AccountMove(models.Model): @@ -73,9 +73,9 @@ def compute_intrastat_lines(self): for line in inv.invoice_line_ids: vals = self._get_intrastat_line_vals(line) if vals: - line_vals.append(vals) + line_vals.append(Command.create(vals)) if line_vals: - inv.intrastat_line_ids = [(0, 0, x) for x in line_vals] + inv.intrastat_line_ids = line_vals def _get_intrastat_line_vals(self, line): vals = {} @@ -149,7 +149,7 @@ class AccountMoveLine(models.Model): def _compute_hs_code_id(self): for rec in self: intrastat_line = self.move_id.intrastat_line_ids.filtered( - lambda r: r.invoice_line_id == rec + lambda r, rec: r.invoice_line_id == rec ) rec.hs_code_id = ( intrastat_line.hs_code_id or rec.product_id.get_hs_code_recursively() diff --git a/intrastat_product/models/intrastat_product_declaration.py b/intrastat_product/models/intrastat_product_declaration.py index e7670ff3c..4ec1ed709 100644 --- a/intrastat_product/models/intrastat_product_declaration.py +++ b/intrastat_product/models/intrastat_product_declaration.py @@ -10,7 +10,7 @@ from dateutil.relativedelta import relativedelta from stdnum.vatin import is_valid -from odoo import _, api, fields, models +from odoo import Command, _, api, fields, models from odoo.exceptions import RedirectWarning, UserError, ValidationError from odoo.tools import float_is_zero @@ -46,8 +46,6 @@ def default_get(self, fields_list): comodel_name="res.company", string="Company", required=True, - readonly=True, - states={"draft": [("readonly", False)]}, default=lambda self: self.env.company, ) company_country_code = fields.Char( @@ -65,11 +63,7 @@ def default_get(self, fields_list): note = fields.Html( string="Notes", ) - year = fields.Char( - required=True, - readonly=True, - states={"draft": [("readonly", False)]}, - ) + year = fields.Char(required=True) month = fields.Selection( selection=[ ("01", "01"), @@ -86,8 +80,6 @@ def default_get(self, fields_list): ("12", "12"), ], required=True, - readonly=True, - states={"draft": [("readonly", False)]}, ) year_month = fields.Char( compute="_compute_year_month", @@ -101,27 +93,21 @@ def default_get(self, fields_list): string="Type", required=True, tracking=True, - readonly=True, - states={"draft": [("readonly", False)]}, ) action = fields.Selection( selection="_get_action", required=True, default="replace", - states={"done": [("readonly", True)]}, tracking=True, ) revision = fields.Integer( default=1, - states={"done": [("readonly", True)]}, help="Used to keep track of changes", ) computation_line_ids = fields.One2many( comodel_name="intrastat.product.computation.line", inverse_name="parent_id", string="Intrastat Product Computation Lines", - readonly=True, - states={"draft": [("readonly", False)]}, ) declaration_line_ids = fields.One2many( comodel_name="intrastat.product.declaration.line", @@ -147,9 +133,8 @@ def default_get(self, fields_list): reporting_level = fields.Selection( selection="_get_reporting_level", compute="_compute_reporting_level", - readonly=True, + readonly=False, store=True, - states={"draft": [("readonly", False)]}, ) xml_attachment_id = fields.Many2one("ir.attachment", string="XML Attachment") xml_attachment_datas = fields.Binary( @@ -241,8 +226,7 @@ def _compute_reporting_level(self): this.reporting_level = reporting_level @api.depends("declaration_type", "year_month") - def name_get(self): - res = [] + def _compute_display_name(self): type2label = dict( self.fields_get("declaration_type", "selection")["declaration_type"][ "selection" @@ -254,8 +238,7 @@ def name_get(self): year_month=rec.year_month, declaration_type=type2label.get(rec.declaration_type), ) - res.append((rec.id, name)) - return res + rec.display_name = name def copy(self, default=None): self.ensure_one() @@ -618,7 +601,7 @@ def _gather_invoices(self, notedict): "line_nbr": line_nbr, } inv_intrastat_line = invoice.intrastat_line_ids.filtered( - lambda r: r.invoice_line_id == inv_line + lambda r, inv_line: r.invoice_line_id == inv_line ) if ( @@ -639,8 +622,10 @@ def _gather_invoices(self, notedict): if float_is_zero(inv_line.quantity, precision_digits=qty_prec): _logger.info( "Skipping invoice line %s qty %s " - "of invoice %s. Reason: qty = 0" - % (inv_line.name, inv_line.quantity, invoice.name) + "of invoice %s. Reason: qty = 0", + inv_line.name, + inv_line.quantity, + invoice.name, ) continue @@ -652,8 +637,10 @@ def _gather_invoices(self, notedict): _logger.info( "Skipping invoice line %s qty %s " "of invoice %s. Reason: partner_country = " - "company country" - % (inv_line.name, inv_line.quantity, invoice.name) + "company country", + inv_line.name, + inv_line.quantity, + invoice.name, ) continue @@ -670,8 +657,10 @@ def _gather_invoices(self, notedict): else: _logger.info( "Skipping invoice line %s qty %s " - "of invoice %s. Reason: no product nor Intrastat Code" - % (inv_line.name, inv_line.quantity, invoice.name) + "of invoice %s. Reason: no product nor Intrastat Code", + inv_line.name, + inv_line.quantity, + invoice.name, ) continue @@ -775,10 +764,8 @@ def _prepare_html_note(self, notedict, key2label): messages, dict ): # 2 layers of dict (partner, product) for message, origins in messages.items(): - note += "
  • %s (%s)
  • " % ( - message, - ", ".join(origins), - ) + origin_str = ", ".join(origins) + note += f"
  • {message} ({origin_str})
  • " else: # 1st layer=dict, 2nd layer=set (invoice) for message in messages: note += "
  • %s
  • " % message @@ -818,12 +805,11 @@ def action_gather(self): vals = {"note": self._prepare_html_note(notedict, key2label)} if not lines: vals["action"] = "nihil" - vals["note"] += "

    %s

    %s

    " % ( - _("No records found for the selected period !"), - _("The declaration Action has been set to nihil."), - ) + nihil_title = _("No records found for the selected period !") + nihil_note = _("The declaration Action has been set to nihil.") + vals["note"] += f"

    {nihil_title}

    {nihil_note}

    " else: - vals["computation_line_ids"] = [(0, 0, x) for x in lines] + vals["computation_line_ids"] = [Command.create(x) for x in lines] self.write(vals) if vals["note"]: @@ -852,12 +838,8 @@ def generate_declaration(self): ipdl = self.declaration_line_ids line_number = 1 for cl_lines in dl_group.values(): - # TODO v17: pass line_number as argument of _prepare_declaration_line() - # we can't afford to modify the proto of _prepare_declaration_line() in v16 - vals = cl_lines._prepare_declaration_line() - declaration_line = ipdl.with_context( - default_line_number=line_number - ).create(vals) + vals = cl_lines._prepare_declaration_line(line_number) + declaration_line = ipdl.create(vals) cl_lines.write({"declaration_line_id": declaration_line.id}) line_number += 1 @@ -1198,7 +1180,7 @@ def _fields_to_sum(self): fields_to_sum = ["weight", "suppl_unit_qty"] return fields_to_sum - def _prepare_declaration_line(self): + def _prepare_declaration_line(self, line_number): fields_to_sum = self._fields_to_sum() vals = self[0]._prepare_grouped_fields(fields_to_sum) for computation_line in self: @@ -1209,7 +1191,7 @@ def _prepare_declaration_line(self): + computation_line["amount_accessory_cost_company_currency"] ) # on computation lines, weight and suppl_unit_qty are floats - # on declaration lines, weight and suppl_unit_qty are integer => so we must round() + # on declaration lines, weight and suppl_unit_qty are integer => so must round() for field in fields_to_sum: vals[field] = int(round(vals[field])) # the intrastat specs say that, if the value is between 0 and 0.5, @@ -1219,6 +1201,7 @@ def _prepare_declaration_line(self): if vals["intrastat_unit_id"] and not vals["suppl_unit_qty"]: vals["suppl_unit_qty"] = 1 vals["amount_company_currency"] = int(round(vals["amount_company_currency"])) + vals["line_number"] = line_number return vals @@ -1283,7 +1266,8 @@ class IntrastatProductDeclarationLine(models.Model): product_origin_country_code = fields.Char( string="Country of Origin of the Product", size=2, - help="2 letters ISO code of the country of origin of the product except for the UK.\n" + help="2 letters ISO code of the country of origin of the product " + "except for the UK.\n" "Specify 'XI' for Northern Ireland and 'XU' for Great Britain.\n" "Specify 'QU' when the country is unknown.\n", ) diff --git a/intrastat_product/models/intrastat_transaction.py b/intrastat_product/models/intrastat_transaction.py index 2454395c6..8df5b1b2e 100644 --- a/intrastat_product/models/intrastat_transaction.py +++ b/intrastat_product/models/intrastat_transaction.py @@ -28,12 +28,10 @@ class IntrastatTransaction(models.Model): active = fields.Boolean(default=True) @api.depends("code", "description") - def name_get(self): - res = [] + def _compute_display_name(self): for this in self: name = this.code if this.description: name += " " + this.description name = shorten(name, 55) - res.append((this.id, name)) - return res + this.display_name = name diff --git a/intrastat_product/models/intrastat_transport_mode.py b/intrastat_product/models/intrastat_transport_mode.py index 9186234b1..616c3689c 100644 --- a/intrastat_product/models/intrastat_transport_mode.py +++ b/intrastat_product/models/intrastat_transport_mode.py @@ -19,9 +19,6 @@ class IntrastatTransportMode(models.Model): description = fields.Char(translate=True) @api.depends("name", "code") - def name_get(self): - res = [] + def _compute_display_name(self): for mode in self: - name = f"{mode.code}. {mode.name}" - res.append((mode.id, name)) - return res + mode.display_name = f"{mode.code}. {mode.name}" diff --git a/intrastat_product/models/intrastat_unit.py b/intrastat_product/models/intrastat_unit.py index eb5706c41..fb3d48b2c 100644 --- a/intrastat_product/models/intrastat_unit.py +++ b/intrastat_product/models/intrastat_unit.py @@ -9,6 +9,7 @@ class IntrastatUnit(models.Model): _name = "intrastat.unit" _description = "Intrastat Supplementary Units" + _order = "name" name = fields.Char(required=True) description = fields.Char(required=True) @@ -19,3 +20,11 @@ class IntrastatUnit(models.Model): "to this Intrastat Supplementary Unit.", ) active = fields.Boolean(default=True) + + _sql_constraints = [ + ( + "name_uniq", + "unique(name)", + "An intrastat supplementary unit with the same name already exists!", + ) + ] diff --git a/intrastat_product/models/res_company.py b/intrastat_product/models/res_company.py index 78e7f8a42..bca94bac9 100644 --- a/intrastat_product/models/res_company.py +++ b/intrastat_product/models/res_company.py @@ -29,7 +29,6 @@ class ResCompany(models.Model): intrastat = fields.Char( string="Intrastat Declaration", store=True, - readonly=True, compute="_compute_intrastat", ) intrastat_region_id = fields.Many2one( diff --git a/intrastat_product/report/intrastat_product_report_xls.py b/intrastat_product/report/intrastat_product_report_xls.py index 7d9eef1fb..baf62365c 100644 --- a/intrastat_product/report/intrastat_product_report_xls.py +++ b/intrastat_product/report/intrastat_product_report_xls.py @@ -205,20 +205,25 @@ def _get_ws_params(self, wb, data, declarations): res = [] wanted_list_computation = declarations._xls_computation_line_fields() wanted_list_declaration = declarations._xls_declaration_line_fields() - for declaration in declarations: - dname = declaration.display_name + type2label = dict( + self.env["intrastat.product.declaration"].fields_get( + "declaration_type", "selection" + )["declaration_type"]["selection"] + ) + for decl in declarations: + dname = " ".join([decl.year_month, type2label[decl.declaration_type]]) res += [ { - "ws_name": "%s %s" % (dname, _("comput.")), + "ws_name": " ".join([dname, _("comput.")]), "generate_ws_method": "_intrastat_report_computation", - "title": "%s : %s" % (dname, _("Computation Lines")), + "title": " : ".join([dname, _("Computation Lines")]), "wanted_list": wanted_list_computation, "col_specs": template, }, { - "ws_name": "%s %s" % (dname, _("decl.")), + "ws_name": " ".join([dname, _("decl.")]), "generate_ws_method": "_intrastat_report_declaration", - "title": "%s : %s" % (dname, _("Declaration Lines")), + "title": " : ".join([dname, _("Declaration Lines")]), "wanted_list": wanted_list_declaration, "col_specs": template, }, diff --git a/intrastat_product/security/ir.model.access.csv b/intrastat_product/security/ir.model.access.csv index 30cc5b1e1..f9fa3e102 100644 --- a/intrastat_product/security/ir.model.access.csv +++ b/intrastat_product/security/ir.model.access.csv @@ -1,11 +1,11 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_intrastat_unit_read,Read access on Intrastat Supplementary Units to everybody,model_intrastat_unit,,1,0,0,0 +access_intrastat_unit_read,Read access on Intrastat Supplementary Units to employees,model_intrastat_unit,base.group_user,1,0,0,0 access_intrastat_unit_full,Full access on Intrastat Supplementary Units to Finance manager,model_intrastat_unit,account.group_account_manager,1,1,1,1 -access_intrastat_transaction_read,Read access on Intrastat Transaction Types to everybody,model_intrastat_transaction,,1,0,0,0 +access_intrastat_transaction_read,Read access on Intrastat Transaction Types to employees,model_intrastat_transaction,base.group_user,1,0,0,0 access_intrastat_transaction_full,Full access on Intrastat Transaction Types to Finance manager,model_intrastat_transaction,account.group_account_manager,1,1,1,1 -access_intrastat_transport_mode_read,Read access on Intrastat Transport Modes to everybody,model_intrastat_transport_mode,,1,0,0,0 +access_intrastat_transport_mode_read,Read access on Intrastat Transport Modes to employees,model_intrastat_transport_mode,base.group_user,1,0,0,0 access_intrastat_transport_mode_full,Full access on Intrastat Transport Modes to Finance manager,model_intrastat_transport_mode,account.group_account_manager,1,1,1,1 -access_intrastat_region_read,Read access on Intrastat Regions,model_intrastat_region,,1,0,0,0 +access_intrastat_region_read,Read access on Intrastat Regions to employees,model_intrastat_region,base.group_user,1,0,0,0 access_intrastat_region_full,Full access on Intrastat Regions,model_intrastat_region,account.group_account_manager,1,1,1,1 access_hs_code_financial_mgr_full,Full access on H.S. Code to financial mgr,product_harmonized_system.model_hs_code,account.group_account_manager,1,1,1,1 access_read_sale_move_intrastat_line,Read access to Sale User on Invoice Intrastat Lines,model_account_move_intrastat_line,sales_team.group_sale_salesman,1,0,0,0 diff --git a/intrastat_product/static/description/index.html b/intrastat_product/static/description/index.html index 6d4a44b21..8686e52b3 100644 --- a/intrastat_product/static/description/index.html +++ b/intrastat_product/static/description/index.html @@ -1,4 +1,3 @@ - diff --git a/intrastat_product/tests/common_purchase.py b/intrastat_product/tests/common_purchase.py index 2133e949b..74bafef31 100644 --- a/intrastat_product/tests/common_purchase.py +++ b/intrastat_product/tests/common_purchase.py @@ -33,14 +33,14 @@ def _check_line_values(self, final=False, declaration=None, purchase=None): for line in purchase.order_line: expected_vals = self._get_expected_vals(line) comp_line = declaration.computation_line_ids.filtered( - lambda cline: cline.product_id == line.product_id + lambda cline, line: cline.product_id == line.product_id ) self.assertTrue( all(comp_line[key] == val for key, val in expected_vals.items()) ) if final: decl_line = declaration.declaration_line_ids.filtered( - lambda dline: comp_line in dline.computation_line_ids + lambda dline, comp_line: comp_line in dline.computation_line_ids ) self.assertTrue( all(decl_line[key] == val for key, val in expected_vals.items()) diff --git a/intrastat_product/tests/common_sale.py b/intrastat_product/tests/common_sale.py index 875c33d04..d4eb3a1e6 100644 --- a/intrastat_product/tests/common_sale.py +++ b/intrastat_product/tests/common_sale.py @@ -31,14 +31,14 @@ def _check_line_values(self, final=False, declaration=None, sale=None): for line in sale.order_line: expected_vals = self._get_expected_vals(line) comp_line = declaration.computation_line_ids.filtered( - lambda cline: cline.product_id == line.product_id + lambda cline, line: cline.product_id == line.product_id ) self.assertTrue( all(comp_line[key] == val for key, val in expected_vals.items()) ) if final: decl_line = declaration.declaration_line_ids.filtered( - lambda dline: comp_line in dline.computation_line_ids + lambda dline, comp_line: comp_line in dline.computation_line_ids ) self.assertTrue( all(decl_line[key] == val for key, val in expected_vals.items()) diff --git a/intrastat_product/tests/test_purchase_order.py b/intrastat_product/tests/test_purchase_order.py index f88e806be..f0356a47a 100644 --- a/intrastat_product/tests/test_purchase_order.py +++ b/intrastat_product/tests/test_purchase_order.py @@ -17,10 +17,7 @@ def test_purchase_to_invoice_default(self): with freeze_time(date_order): self._create_purchase_order() self.purchase.button_confirm() - self.purchase.picking_ids.action_assign() - for line in self.purchase.picking_ids.move_line_ids: - line.qty_done = line.reserved_uom_qty - self.purchase.picking_ids._action_done() + self.purchase.picking_ids.button_validate() self.assertEqual("done", self.purchase.picking_ids.state) with freeze_time(date_order): diff --git a/intrastat_product/tests/test_sale_order.py b/intrastat_product/tests/test_sale_order.py index 6eefce5af..205be214a 100644 --- a/intrastat_product/tests/test_sale_order.py +++ b/intrastat_product/tests/test_sale_order.py @@ -13,10 +13,7 @@ class TestIntrastatProductSale(IntrastatSaleCommon): def test_sale_to_invoice_default(self): self._create_sale_order(self.customer) self.sale.action_confirm() - self.sale.picking_ids.action_assign() - for line in self.sale.picking_ids.move_line_ids: - line.qty_done = line.reserved_uom_qty - self.sale.picking_ids._action_done() + self.sale.picking_ids.button_validate() self.assertEqual("done", self.sale.picking_ids.state) invoice = self.sale._create_invoices() @@ -34,10 +31,7 @@ def test_sale_to_invoice(self): # Set intrastat transport mode to rail self.sale.intrastat_transport_id = self.transport_rail self.sale.action_confirm() - self.sale.picking_ids.action_assign() - for line in self.sale.picking_ids.move_line_ids: - line.qty_done = line.reserved_uom_qty - self.sale.picking_ids._action_done() + self.sale.picking_ids.button_validate() self.assertEqual("done", self.sale.picking_ids.state) invoice = self.sale._create_invoices() @@ -57,10 +51,7 @@ def test_sale_declaration(self): # Set intrastat transport mode to rail self.sale.intrastat_transport_id = self.transport_rail self.sale.action_confirm() - self.sale.picking_ids.action_assign() - for line in self.sale.picking_ids.move_line_ids: - line.qty_done = line.reserved_uom_qty - self.sale.picking_ids._action_done() + self.sale.picking_ids.button_validate() self.assertEqual("done", self.sale.picking_ids.state) with freeze_time(date_order): @@ -96,10 +87,7 @@ def test_sale_declaration_b2c_no_vat(self): # Set intrastat transport mode to rail self.sale.intrastat_transport_id = self.transport_rail self.sale.action_confirm() - self.sale.picking_ids.action_assign() - for line in self.sale.picking_ids.move_line_ids: - line.qty_done = line.reserved_uom_qty - self.sale.picking_ids._action_done() + self.sale.picking_ids.button_validate() self.assertEqual("done", self.sale.picking_ids.state) with freeze_time(date_order): diff --git a/intrastat_product/views/account_move.xml b/intrastat_product/views/account_move.xml index b7a660674..b055f6feb 100644 --- a/intrastat_product/views/account_move.xml +++ b/intrastat_product/views/account_move.xml @@ -13,7 +13,7 @@ @@ -24,7 +24,7 @@ id="intrastat_lines" string="Intrastat transaction details" groups="intrastat_product.group_invoice_intrastat_transaction_details" - attrs="{'invisible': [('move_type', 'not in', ('out_invoice', 'out_refund', 'in_invoice', 'in_refund'))]}" + invisible="move_type not in ('out_invoice', 'out_refund', 'in_invoice', 'in_refund')" >
    - - - - + + + + - - + + @@ -88,6 +92,7 @@ @@ -95,7 +100,7 @@ + + @@ -220,15 +235,17 @@