diff --git a/intrastat_product/README.rst b/intrastat_product/README.rst index dbd2ca3..9d61b10 100644 --- a/intrastat_product/README.rst +++ b/intrastat_product/README.rst @@ -47,6 +47,24 @@ Installation This module is NOT compatible with the *account_intrastat* module from Odoo Enterprise. +Configuration +============= + +By default the intrastat declaration is generated based upon the product record master data. +Hence unexpected results may occur in case this master data is not accurate, +e.g. wrong or missing weight, country of origin, ... + +| + +This can be corrected by changing the appropriate fields when analysing the intrastat declaration +but this can be challenging in case of large transaction volumes and especially in the specific use +case where the product weight cannot be encoded correctly on the product records (e.g. products with variable weight). + +| + +It is possible to allow encoding the intrastat transaction details on the purchase/sale invoice +via the "intrastat_product.group_invoice_intrastat_transaction_detail" usability group. + Usage ===== diff --git a/intrastat_product/__manifest__.py b/intrastat_product/__manifest__.py index 3a31c30..5bafc9e 100644 --- a/intrastat_product/__manifest__.py +++ b/intrastat_product/__manifest__.py @@ -21,6 +21,8 @@ ], "excludes": ["account_intrastat"], "data": [ + "security/intrastat_security.xml", + "security/ir.model.access.csv", "views/hs_code.xml", "views/intrastat_region.xml", "views/intrastat_unit.xml", @@ -31,8 +33,6 @@ "views/account_move.xml", "views/sale_order.xml", "views/stock_warehouse.xml", - "security/intrastat_security.xml", - "security/ir.model.access.csv", "data/intrastat_transport_mode.xml", "data/intrastat_unit.xml", ], diff --git a/intrastat_product/i18n/fr.po b/intrastat_product/i18n/fr.po index b58b3c0..6ffae12 100644 --- a/intrastat_product/i18n/fr.po +++ b/intrastat_product/i18n/fr.po @@ -16,6 +16,12 @@ msgstr "" "Content-Transfer-Encoding: \n" "Plural-Forms: \n" +#. module: intrastat_product +#: model_terms:ir.ui.view,arch_db:intrastat_product.view_move_form +msgid "" +"(Re)compute the intrastat transaction details from the product master data." +msgstr "" + #. module: intrastat_product #: model:ir.model.fields.selection,name:intrastat_product.selection__intrastat_product_declaration__month__01 msgid "01" @@ -142,6 +148,11 @@ msgstr "Air" msgid "Air Transport" msgstr "Transport par air" +#. module: intrastat_product +#: model:res.groups,comment:intrastat_product.group_invoice_intrastat_transaction_details +msgid "Allow to encode Intrastat Transaction Details on Invoices" +msgstr "" + #. module: intrastat_product #: model:ir.model.fields,help:intrastat_product.field_intrastat_product_computation_line__amount_accessory_cost_company_currency msgid "" @@ -260,6 +271,11 @@ msgstr "Monnaie de la société" msgid "Computation Lines" msgstr "Lignes de transaction" +#. module: intrastat_product +#: model_terms:ir.ui.view,arch_db:intrastat_product.view_move_form +msgid "Compute" +msgstr "" + #. module: intrastat_product #: model:ir.model,name:intrastat_product.model_res_config_settings #, fuzzy @@ -301,6 +317,11 @@ msgstr "" msgid "Country" msgstr "Pays" +#. module: intrastat_product +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__product_origin_country_id +msgid "Country of Origin" +msgstr "" + #. module: intrastat_product #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_computation_line__product_origin_country_id #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__product_origin_country_id @@ -322,6 +343,12 @@ msgid "Country of origin of the product i.e. product 'made in ____'" msgstr "Pays d'origine de l'article i.e. article 'made in ____'" #. module: intrastat_product +#: model:ir.model.fields,help:intrastat_product.field_account_move_intrastat_line__product_origin_country_id +msgid "Country of origin of the product i.e. product 'made in ____'." +msgstr "" + +#. module: intrastat_product +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__create_uid #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_computation_line__create_uid #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration__create_uid #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__create_uid @@ -333,6 +360,7 @@ msgid "Created by" msgstr "Créé par" #. module: intrastat_product +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__create_date #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_computation_line__create_date #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration__create_date #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__create_date @@ -446,6 +474,7 @@ msgid "Dispatches" msgstr "Expéditions" #. module: intrastat_product +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__display_name #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_computation_line__display_name #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration__display_name #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__display_name @@ -565,6 +594,7 @@ msgid "H.S. Codes" msgstr "Codes S.H." #. module: intrastat_product +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__id #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_computation_line__id #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration__id #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__id @@ -624,6 +654,7 @@ msgstr "Transport par navigation intérieure" #. module: intrastat_product #: code:addons/intrastat_product/report/intrastat_product_report_xls.py:0 +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__hs_code_id #: model:ir.model.fields,field_description:intrastat_product.field_account_move_line__hs_code_id #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_computation_line__hs_code_id #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__hs_code_id @@ -631,6 +662,12 @@ msgstr "Transport par navigation intérieure" msgid "Intrastat Code" msgstr "Code pour la DEB" +#. module: intrastat_product +#: code:addons/intrastat_product/models/intrastat_product_declaration.py:0 +#, python-format +msgid "Intrastat Code %s:" +msgstr "" + #. module: intrastat_product #: code:addons/intrastat_product/models/hs_code.py:0 #, python-format @@ -785,11 +822,22 @@ msgstr "Modes de transport pour la DEB" msgid "Intrastat declaration" msgstr "DEB" +#. module: intrastat_product +#: model:ir.model,name:intrastat_product.model_account_move_intrastat_line +#: model:ir.model.fields,field_description:intrastat_product.field_account_move__intrastat_line_ids +msgid "Intrastat declaration details" +msgstr "" + #. module: intrastat_product #: model:ir.model.fields,help:intrastat_product.field_account_move__intrastat_transaction_id msgid "Intrastat nature of transaction" msgstr "Nature de la transaction pour la DEB" +#. module: intrastat_product +#: model_terms:ir.ui.view,arch_db:intrastat_product.view_move_form +msgid "Intrastat transaction details" +msgstr "" + #. module: intrastat_product #: code:addons/intrastat_product/models/intrastat_product_declaration.py:0 #, python-format @@ -803,12 +851,25 @@ msgstr "Emplacements de stock" #. module: intrastat_product #: code:addons/intrastat_product/report/intrastat_product_report_xls.py:0 +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__move_id #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_computation_line__invoice_id #, python-format msgid "Invoice" msgstr "Facture" #. module: intrastat_product +#: code:addons/intrastat_product/models/intrastat_product_declaration.py:0 +#, python-format +msgid "Invoice %s, line %s" +msgstr "" + +#. module: intrastat_product +#: model:res.groups,name:intrastat_product.group_invoice_intrastat_transaction_details +msgid "Invoice Intrastat Transaction Details" +msgstr "" + +#. module: intrastat_product +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__invoice_line_id #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_computation_line__invoice_line_id msgid "Invoice Line" msgstr "Ligne de facture" @@ -835,6 +896,7 @@ msgid "Kg" msgstr "Kg" #. module: intrastat_product +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line____last_update #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_computation_line____last_update #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration____last_update #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line____last_update @@ -847,6 +909,7 @@ msgid "Last Modified on" msgstr "Dernière Modification le" #. module: intrastat_product +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__write_uid #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_computation_line__write_uid #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration__write_uid #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__write_uid @@ -858,6 +921,7 @@ msgid "Last Updated by" msgstr "Dernière modification par" #. module: intrastat_product +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__write_date #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_computation_line__write_date #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration__write_date #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__write_date @@ -886,19 +950,14 @@ msgstr "" #. module: intrastat_product #: code:addons/intrastat_product/models/intrastat_product_declaration.py:0 #, python-format -msgid "Missing H.S. code on product %s. This product is present in invoice %s." +msgid "Missing Intrastat Code on product %s. " msgstr "" -"Code S.H. manquant sur l'article %s. Cet article est présent sur la facture " -"%s." #. module: intrastat_product #: code:addons/intrastat_product/models/intrastat_product_declaration.py:0 #, python-format -msgid "" -"Missing unit of measure on the line with %d product(s) '%s' on invoice '%s'." +msgid "Missing unit of measure." msgstr "" -"Unité de mesure manquante sur la ligne où figurent %d article(s) '%s' sur la " -"facture '%s'." #. module: intrastat_product #: code:addons/intrastat_product/models/intrastat_product_declaration.py:0 @@ -1050,43 +1109,6 @@ msgstr "" msgid "Period" msgstr "Période" -#. module: intrastat_product -#: code:addons/intrastat_product/models/intrastat_product_declaration.py:0 -#, python-format -msgid "Please adjust this line manually." -msgstr "Ligne à finaliser manuellement." - -#. module: intrastat_product -#: code:addons/intrastat_product/models/intrastat_product_declaration.py:0 -#, python-format -msgid "" -"Please correct the Intrastat Supplementary Unit settings and regenerate the " -"lines or adjust the lines with Intrastat Code '%s' manually" -msgstr "" -"Corrigez le paramétrage de l'unité de mesure supplémentaire pour la DEB et " -"regénérez les lignes ou ajustez manuellement les lignes avec le code pour la " -"DEB '%s'" - -#. module: intrastat_product -#: code:addons/intrastat_product/models/intrastat_product_declaration.py:0 -#, python-format -msgid "" -"Please correct the product record and regenerate the lines or adjust the " -"impacted lines manually" -msgstr "" -"Corrigez le paramétrage de l'article et regénérez les lignes ou ajustez " -"manuellement les lignes concernées." - -#. module: intrastat_product -#: code:addons/intrastat_product/models/intrastat_product_declaration.py:0 -#, python-format -msgid "" -"Please correct the unit of measure settings and regenerate the lines or " -"adjust the impacted lines manually" -msgstr "" -"Corrigez le paramétrage de l'unité de mesure et regénérez les lignes ou " -"ajustez manuellement les lignes concernées" - #. module: intrastat_product #: model:intrastat.transport_mode,name:intrastat_product.intrastat_transport_5 msgid "Post" @@ -1099,6 +1121,7 @@ msgstr "Envois postaux" #. module: intrastat_product #: code:addons/intrastat_product/report/intrastat_product_report_xls.py:0 +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__product_id #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_computation_line__product_id #, python-format msgid "Product" @@ -1112,6 +1135,11 @@ msgstr "Article" msgid "Product C/O" msgstr "Pays ori. article" +#. module: intrastat_product +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__quantity +msgid "Quantity" +msgstr "" + #. module: intrastat_product #: model:intrastat.transport_mode,name:intrastat_product.intrastat_transport_2 msgid "Rail" @@ -1224,6 +1252,11 @@ msgstr "" "Sélectionnez l'unité de mesure normale d'Odoo qui correspond à cette unité " "de mesure supplémentaire pour la DEB" +#. module: intrastat_product +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__sequence +msgid "Sequence" +msgstr "" + #. module: intrastat_product #: code:addons/intrastat_product/models/intrastat_product_declaration.py:0 #, python-format @@ -1318,6 +1351,13 @@ msgstr "" msgid "The move of this entry line." msgstr "" +#. module: intrastat_product +#: model:ir.model.fields,help:intrastat_product.field_account_move_intrastat_line__quantity +msgid "" +"The optional quantity expressed by this line, eg: number of product sold. " +"The quantity is not a legal requirement but is very useful for some reports." +msgstr "" + #. module: intrastat_product #: model:ir.model.fields,help:intrastat_product.field_sale_order__intrastat_transport_id msgid "This information is used in Intrastat reports" @@ -1345,12 +1385,32 @@ msgstr "Année et mois de la DEB." msgid "Transaction" msgstr "Transaction" +#. module: intrastat_product +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__transaction_suppl_unit_qty +msgid "Transaction Suppl Unit Qty" +msgstr "" + #. module: intrastat_product #: model:ir.actions.act_window,name:intrastat_product.intrastat_transaction_action #: model:ir.ui.menu,name:intrastat_product.intrastat_transaction_menu msgid "Transaction Types" msgstr "Types de transaction" +#. module: intrastat_product +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__transaction_weight +msgid "Transaction Weight" +msgstr "" + +#. module: intrastat_product +#: model:ir.model.fields,help:intrastat_product.field_account_move_intrastat_line__transaction_suppl_unit_qty +msgid "Transaction quantity in Intrastat Supplementary Unit" +msgstr "" + +#. module: intrastat_product +#: model:ir.model.fields,help:intrastat_product.field_account_move_intrastat_line__transaction_weight +msgid "Transaction weight in Kg: Quantity x Product Weight" +msgstr "" + #. module: intrastat_product #: model_terms:ir.ui.view,arch_db:intrastat_product.intrastat_product_computation_line_view_tree #: model_terms:ir.ui.view,arch_db:intrastat_product.intrastat_product_declaration_view_form @@ -1467,6 +1527,44 @@ msgstr "Vous devez configurer le pays de la société !" msgid "for period %s" msgstr "" +#~ msgid "" +#~ "Missing H.S. code on product %s. This product is present in invoice %s." +#~ msgstr "" +#~ "Code S.H. manquant sur l'article %s. Cet article est présent sur la " +#~ "facture %s." + +#~ msgid "" +#~ "Missing unit of measure on the line with %d product(s) '%s' on invoice " +#~ "'%s'." +#~ msgstr "" +#~ "Unité de mesure manquante sur la ligne où figurent %d article(s) '%s' sur " +#~ "la facture '%s'." + +#~ msgid "Please adjust this line manually." +#~ msgstr "Ligne à finaliser manuellement." + +#~ msgid "" +#~ "Please correct the Intrastat Supplementary Unit settings and regenerate " +#~ "the lines or adjust the lines with Intrastat Code '%s' manually" +#~ msgstr "" +#~ "Corrigez le paramétrage de l'unité de mesure supplémentaire pour la DEB " +#~ "et regénérez les lignes ou ajustez manuellement les lignes avec le code " +#~ "pour la DEB '%s'" + +#~ msgid "" +#~ "Please correct the product record and regenerate the lines or adjust the " +#~ "impacted lines manually" +#~ msgstr "" +#~ "Corrigez le paramétrage de l'article et regénérez les lignes ou ajustez " +#~ "manuellement les lignes concernées." + +#~ msgid "" +#~ "Please correct the unit of measure settings and regenerate the lines or " +#~ "adjust the impacted lines manually" +#~ msgstr "" +#~ "Corrigez le paramétrage de l'unité de mesure et regénérez les lignes ou " +#~ "ajustez manuellement les lignes concernées" + #, fuzzy #~| msgid "Company Country Code" #~ msgid "Country Code" diff --git a/intrastat_product/i18n/intrastat_product.pot b/intrastat_product/i18n/intrastat_product.pot index 41b3be1..3827354 100644 --- a/intrastat_product/i18n/intrastat_product.pot +++ b/intrastat_product/i18n/intrastat_product.pot @@ -13,6 +13,12 @@ msgstr "" "Content-Transfer-Encoding: \n" "Plural-Forms: \n" +#. module: intrastat_product +#: model_terms:ir.ui.view,arch_db:intrastat_product.view_move_form +msgid "" +"(Re)compute the intrastat transaction details from the product master data." +msgstr "" + #. module: intrastat_product #: model:ir.model.fields.selection,name:intrastat_product.selection__intrastat_product_declaration__month__01 msgid "01" @@ -132,6 +138,11 @@ msgstr "" msgid "Air Transport" msgstr "" +#. module: intrastat_product +#: model:res.groups,comment:intrastat_product.group_invoice_intrastat_transaction_details +msgid "Allow to encode Intrastat Transaction Details on Invoices" +msgstr "" + #. module: intrastat_product #: model:ir.model.fields,help:intrastat_product.field_intrastat_product_computation_line__amount_accessory_cost_company_currency msgid "" @@ -243,6 +254,11 @@ msgstr "" msgid "Computation Lines" msgstr "" +#. module: intrastat_product +#: model_terms:ir.ui.view,arch_db:intrastat_product.view_move_form +msgid "Compute" +msgstr "" + #. module: intrastat_product #: model:ir.model,name:intrastat_product.model_res_config_settings msgid "Config Settings" @@ -278,6 +294,11 @@ msgstr "" msgid "Country" msgstr "" +#. module: intrastat_product +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__product_origin_country_id +msgid "Country of Origin" +msgstr "" + #. module: intrastat_product #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_computation_line__product_origin_country_id #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__product_origin_country_id @@ -299,6 +320,12 @@ msgid "Country of origin of the product i.e. product 'made in ____'" msgstr "" #. module: intrastat_product +#: model:ir.model.fields,help:intrastat_product.field_account_move_intrastat_line__product_origin_country_id +msgid "Country of origin of the product i.e. product 'made in ____'." +msgstr "" + +#. module: intrastat_product +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__create_uid #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_computation_line__create_uid #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration__create_uid #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__create_uid @@ -310,6 +337,7 @@ msgid "Created by" msgstr "" #. module: intrastat_product +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__create_date #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_computation_line__create_date #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration__create_date #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__create_date @@ -422,6 +450,7 @@ msgid "Dispatches" msgstr "" #. module: intrastat_product +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__display_name #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_computation_line__display_name #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration__display_name #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__display_name @@ -541,6 +570,7 @@ msgid "H.S. Codes" msgstr "" #. module: intrastat_product +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__id #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_computation_line__id #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration__id #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__id @@ -600,6 +630,7 @@ msgstr "" #. module: intrastat_product #: code:addons/intrastat_product/report/intrastat_product_report_xls.py:0 +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__hs_code_id #: model:ir.model.fields,field_description:intrastat_product.field_account_move_line__hs_code_id #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_computation_line__hs_code_id #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__hs_code_id @@ -607,6 +638,12 @@ msgstr "" msgid "Intrastat Code" msgstr "" +#. module: intrastat_product +#: code:addons/intrastat_product/models/intrastat_product_declaration.py:0 +#, python-format +msgid "Intrastat Code %s:" +msgstr "" + #. module: intrastat_product #: code:addons/intrastat_product/models/hs_code.py:0 #, python-format @@ -755,11 +792,22 @@ msgstr "" msgid "Intrastat declaration" msgstr "" +#. module: intrastat_product +#: model:ir.model,name:intrastat_product.model_account_move_intrastat_line +#: model:ir.model.fields,field_description:intrastat_product.field_account_move__intrastat_line_ids +msgid "Intrastat declaration details" +msgstr "" + #. module: intrastat_product #: model:ir.model.fields,help:intrastat_product.field_account_move__intrastat_transaction_id msgid "Intrastat nature of transaction" msgstr "" +#. module: intrastat_product +#: model_terms:ir.ui.view,arch_db:intrastat_product.view_move_form +msgid "Intrastat transaction details" +msgstr "" + #. module: intrastat_product #: code:addons/intrastat_product/models/intrastat_product_declaration.py:0 #, python-format @@ -773,12 +821,25 @@ msgstr "" #. module: intrastat_product #: code:addons/intrastat_product/report/intrastat_product_report_xls.py:0 +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__move_id #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_computation_line__invoice_id #, python-format msgid "Invoice" msgstr "" #. module: intrastat_product +#: code:addons/intrastat_product/models/intrastat_product_declaration.py:0 +#, python-format +msgid "Invoice %s, line %s" +msgstr "" + +#. module: intrastat_product +#: model:res.groups,name:intrastat_product.group_invoice_intrastat_transaction_details +msgid "Invoice Intrastat Transaction Details" +msgstr "" + +#. module: intrastat_product +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__invoice_line_id #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_computation_line__invoice_line_id msgid "Invoice Line" msgstr "" @@ -805,6 +866,7 @@ msgid "Kg" msgstr "" #. module: intrastat_product +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line____last_update #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_computation_line____last_update #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration____last_update #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line____last_update @@ -817,6 +879,7 @@ msgid "Last Modified on" msgstr "" #. module: intrastat_product +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__write_uid #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_computation_line__write_uid #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration__write_uid #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__write_uid @@ -828,6 +891,7 @@ msgid "Last Updated by" msgstr "" #. module: intrastat_product +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__write_date #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_computation_line__write_date #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration__write_date #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_declaration_line__write_date @@ -856,15 +920,13 @@ msgstr "" #. module: intrastat_product #: code:addons/intrastat_product/models/intrastat_product_declaration.py:0 #, python-format -msgid "" -"Missing H.S. code on product %s. This product is present in invoice %s." +msgid "Missing Intrastat Code on product %s. " msgstr "" #. module: intrastat_product #: code:addons/intrastat_product/models/intrastat_product_declaration.py:0 #, python-format -msgid "" -"Missing unit of measure on the line with %d product(s) '%s' on invoice '%s'." +msgid "Missing unit of measure." msgstr "" #. module: intrastat_product @@ -1010,37 +1072,6 @@ msgstr "" msgid "Period" msgstr "" -#. module: intrastat_product -#: code:addons/intrastat_product/models/intrastat_product_declaration.py:0 -#, python-format -msgid "Please adjust this line manually." -msgstr "" - -#. module: intrastat_product -#: code:addons/intrastat_product/models/intrastat_product_declaration.py:0 -#, python-format -msgid "" -"Please correct the Intrastat Supplementary Unit settings and regenerate the " -"lines or adjust the lines with Intrastat Code '%s' manually" -msgstr "" - -#. module: intrastat_product -#: code:addons/intrastat_product/models/intrastat_product_declaration.py:0 -#, python-format -msgid "" -"Please correct the product record and regenerate the lines or adjust the " -"impacted lines manually" -msgstr "" - -#. module: intrastat_product -#: code:addons/intrastat_product/models/intrastat_product_declaration.py:0 -#: code:addons/intrastat_product/models/intrastat_product_declaration.py:0 -#, python-format -msgid "" -"Please correct the unit of measure settings and regenerate the lines or " -"adjust the impacted lines manually" -msgstr "" - #. module: intrastat_product #: model:intrastat.transport_mode,name:intrastat_product.intrastat_transport_5 msgid "Post" @@ -1053,6 +1084,7 @@ msgstr "" #. module: intrastat_product #: code:addons/intrastat_product/report/intrastat_product_report_xls.py:0 +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__product_id #: model:ir.model.fields,field_description:intrastat_product.field_intrastat_product_computation_line__product_id #, python-format msgid "Product" @@ -1066,6 +1098,11 @@ msgstr "" msgid "Product C/O" msgstr "" +#. module: intrastat_product +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__quantity +msgid "Quantity" +msgstr "" + #. module: intrastat_product #: model:intrastat.transport_mode,name:intrastat_product.intrastat_transport_2 msgid "Rail" @@ -1176,6 +1213,11 @@ msgid "" "Intrastat Supplementary Unit." msgstr "" +#. module: intrastat_product +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__sequence +msgid "Sequence" +msgstr "" + #. module: intrastat_product #: code:addons/intrastat_product/models/intrastat_product_declaration.py:0 #, python-format @@ -1264,6 +1306,13 @@ msgstr "" msgid "The move of this entry line." msgstr "" +#. module: intrastat_product +#: model:ir.model.fields,help:intrastat_product.field_account_move_intrastat_line__quantity +msgid "" +"The optional quantity expressed by this line, eg: number of product sold. " +"The quantity is not a legal requirement but is very useful for some reports." +msgstr "" + #. module: intrastat_product #: model:ir.model.fields,help:intrastat_product.field_sale_order__intrastat_transport_id msgid "This information is used in Intrastat reports" @@ -1289,12 +1338,32 @@ msgstr "" msgid "Transaction" msgstr "" +#. module: intrastat_product +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__transaction_suppl_unit_qty +msgid "Transaction Suppl Unit Qty" +msgstr "" + #. module: intrastat_product #: model:ir.actions.act_window,name:intrastat_product.intrastat_transaction_action #: model:ir.ui.menu,name:intrastat_product.intrastat_transaction_menu msgid "Transaction Types" msgstr "" +#. module: intrastat_product +#: model:ir.model.fields,field_description:intrastat_product.field_account_move_intrastat_line__transaction_weight +msgid "Transaction Weight" +msgstr "" + +#. module: intrastat_product +#: model:ir.model.fields,help:intrastat_product.field_account_move_intrastat_line__transaction_suppl_unit_qty +msgid "Transaction quantity in Intrastat Supplementary Unit" +msgstr "" + +#. module: intrastat_product +#: model:ir.model.fields,help:intrastat_product.field_account_move_intrastat_line__transaction_weight +msgid "Transaction weight in Kg: Quantity x Product Weight" +msgstr "" + #. module: intrastat_product #: model_terms:ir.ui.view,arch_db:intrastat_product.intrastat_product_computation_line_view_tree #: model_terms:ir.ui.view,arch_db:intrastat_product.intrastat_product_declaration_view_form diff --git a/intrastat_product/models/account_move.py b/intrastat_product/models/account_move.py index d81ed54..cca4c99 100644 --- a/intrastat_product/models/account_move.py +++ b/intrastat_product/models/account_move.py @@ -46,6 +46,11 @@ class AccountMove(models.Model): intrastat = fields.Char( string="Intrastat Declaration", related="company_id.intrastat" ) + intrastat_line_ids = fields.One2many( + comodel_name="account.move.intrastat.line", + inverse_name="move_id", + string="Intrastat declaration details", + ) @api.depends("partner_shipping_id.country_id", "partner_id.country_id") def _compute_intrastat_country(self): @@ -60,23 +65,107 @@ class AccountMove(models.Model): def _default_src_dest_region_id(self): return self.env.company.intrastat_region_id + def compute_intrastat_lines(self): + """ + Compute the Intrastat Lines so that they can be modified + when encoding the Customer/Supplier Invoice. + """ + self.mapped("intrastat_line_ids").unlink() + for inv in self: + if inv.type not in ("out_invoice", "out_refund", "in_invoice", "in_refund"): + continue + line_vals = [] + for line in inv.invoice_line_ids: + vals = self._get_intrastat_line_vals(line) + if vals: + line_vals.append(vals) + if line_vals: + inv.intrastat_line_ids = [(0, 0, x) for x in line_vals] + + def _get_intrastat_line_vals(self, line): + vals = {} + decl_model = self.env["intrastat.product.declaration"] + if decl_model._is_product(line): + hs_code = line.product_id.get_hs_code_recursively() + if not hs_code: + return vals + weight, qty = decl_model._get_weight_and_supplunits(line, hs_code) + vals.update( + { + "invoice_line_id": line.id, + "hs_code_id": hs_code.id, + "transaction_weight": int(weight), + "transaction_suppl_unit_qty": qty, + "product_origin_country_id": line.product_id.origin_country_id.id, + } + ) + return vals + class AccountMoveLine(models.Model): _inherit = "account.move.line" hs_code_id = fields.Many2one( - comodel_name="hs.code", string="Intrastat Code", ondelete="restrict" + comodel_name="hs.code", compute="_compute_hs_code_id", string="Intrastat Code", + ) + + 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 + ) + rec.hs_code_id = intrastat_line.hs_code_id or rec.get_hs_code_recursively() + + +class AccountMoveIntrastatLine(models.Model): + _name = "account.move.intrastat.line" + _description = "Intrastat declaration details" + _order = "sequence" + + move_id = fields.Many2one( + comodel_name="account.move", + string="Invoice", + ondelete="cascade", + required=True, + ) + invoice_line_id = fields.Many2one( + comodel_name="account.move.line", + string="Invoice Line", + ondelete="cascade", + required=True, + ) + sequence = fields.Integer(related="invoice_line_id.sequence", store=True) + product_id = fields.Many2one( + comodel_name="product.product", + string="Product", + related="invoice_line_id.product_id", + ) + quantity = fields.Float(related="invoice_line_id.quantity") + transaction_suppl_unit_qty = fields.Float( + help="Transaction quantity in Intrastat Supplementary Unit" + ) + hs_code_id = fields.Many2one( + comodel_name="hs.code", + string="Intrastat Code", + ondelete="restrict", + required=True, + ) + transaction_weight = fields.Integer( + help="Transaction weight in Kg: Quantity x Product Weight" ) - weight = fields.Integer(string="Weight", help="Net weight in Kg") product_origin_country_id = fields.Many2one( comodel_name="res.country", string="Country of Origin", help="Country of origin of the product i.e. product " "'made in ____'.", ) - @api.onchange("product_id") - def intrastat_product_id_change(self): - if self.product_id: - self.hs_code_id = self.product_id.get_hs_code_recursively() - self.product_origin_country_id = self.product_id.origin_country_id - self.weight = self.product_id.weight + @api.onchange("invoice_line_id") + def _onchange_move_id(self): + moves = self.mapped("move_id") + dom = [ + ("exclude_from_invoice_tab", "=", False), + ("display_type", "=", False), + ("id", "in", moves.mapped("invoice_line_ids").ids), + ("id", "not in", moves.mapped("intrastat_line_ids.invoice_line_id").ids), + ] + return {"domain": {"invoice_line_id": dom}} diff --git a/intrastat_product/models/intrastat_product_declaration.py b/intrastat_product/models/intrastat_product_declaration.py index 8b4c3cf..bab8276 100644 --- a/intrastat_product/models/intrastat_product_declaration.py +++ b/intrastat_product/models/intrastat_product_declaration.py @@ -29,6 +29,11 @@ class IntrastatProductDeclaration(models.Model): "or change the revision number of this one.", ) ] + # TODO: + # drop the use of self._note & self._line_nbr when migrating to Odoo 14 + # refactoring this now may break the localisation modules + _note = "" + _line_nbr = "" @api.model def default_get(self, fields_list): @@ -261,9 +266,9 @@ class IntrastatProductDeclaration(models.Model): return company.intrastat_transaction_in_refund def _get_weight_and_supplunits(self, inv_line, hs_code): + line_nbr = self._line_nbr line_qty = inv_line.quantity product = inv_line.product_id - invoice = inv_line.move_id intrastat_unit_id = hs_code.intrastat_unit_id source_uom = inv_line.product_uom_id weight_uom_categ = self._get_uom_refs("weight_uom_categ") @@ -272,80 +277,50 @@ class IntrastatProductDeclaration(models.Model): pce_uom = self._get_uom_refs("pce_uom") weight = suppl_unit_qty = 0.0 - if not product: - weight = inv_line.weight - if not weight: - note = "\n" + _( - "Missing weight on invoice %s, line with intrastat code %s." - ) % (inv_line.move_id.name, inv_line.hs_code_id.local_code) - note += "\n" + _( - "Please correct the product record and regenerate " - "the lines or adjust the impacted lines manually" - ) - self._note += note - return weight, suppl_unit_qty - return weight, suppl_unit_qty - if not source_uom: - note = "\n" + _( - "Missing unit of measure on the line with %d " - "product(s) '%s' on invoice '%s'." - ) % (line_qty, product.name_get()[0][1], invoice.name) - note += "\n" + _("Please adjust this line manually.") - self._note += note + line_notes = [_("Missing unit of measure.")] + self._note += self._format_line_note(inv_line, line_nbr, line_notes) return weight, suppl_unit_qty if intrastat_unit_id: target_uom = intrastat_unit_id.uom_id if not target_uom: - note = ( - "\n" - + _( + line_notes = [ + _("Intrastat Code %s:") % hs_code.display_name, + _( "Conversion from Intrastat Supplementary Unit '%s' to " "Unit of Measure is not implemented yet." ) - % intrastat_unit_id.name - ) - note += ( - "\n" - + _( - "Please correct the Intrastat Supplementary Unit " - "settings and regenerate the lines or adjust the lines " - "with Intrastat Code '%s' manually" - ) - % hs_code.display_name - ) - self._note += note + % intrastat_unit_id.name, + ] + self._note += self._format_line_note(inv_line, line_nbr, line_notes) return weight, suppl_unit_qty if target_uom.category_id == source_uom.category_id: suppl_unit_qty = source_uom._compute_quantity(line_qty, target_uom) else: - note = "\n" + _( - "Conversion from unit of measure '%s' to '%s' " - "is not implemented yet." - ) % (source_uom.name, target_uom.name) - note += "\n" + _( - "Please correct the unit of measure settings and " - "regenerate the lines or adjust the impacted " - "lines manually" - ) - self._note += note + line_notes = [ + _( + "Conversion from unit of measure '%s' to '%s' " + "is not implemented yet." + ) + % (source_uom.name, target_uom.name) + ] + self._note += self._format_line_note(inv_line, line_nbr, line_notes) return weight, suppl_unit_qty + if weight: + return weight, suppl_unit_qty + if source_uom == kg_uom: weight = line_qty elif source_uom.category_id == weight_uom_categ: weight = source_uom._compute_quantity(line_qty, kg_uom) elif source_uom.category_id == pce_uom_categ: if not product.weight: # re-create weight_net ? - note = ( - "\n" + _("Missing weight on product %s.") % product.name_get()[0][1] - ) - note += "\n" + _( - "Please correct the product record and regenerate " - "the lines or adjust the impacted lines manually" - ) - self._note += note + line_notes = [ + _("Missing weight on product %s.") % product.name_get()[0][1] + ] + self._note += self._format_line_note(inv_line, line_nbr, line_notes) return weight, suppl_unit_qty if source_uom == pce_uom: weight = product.weight * line_qty # product.weight_net @@ -357,16 +332,14 @@ class IntrastatProductDeclaration(models.Model): line_qty, pce_uom ) else: - note = "\n" + _( - "Conversion from unit of measure '%s' to 'Kg' " - "is not implemented yet. It is needed for product '%s'." - ) % (source_uom.name, product.name_get()[0][1]) - note += "\n" + _( - "Please correct the unit of measure settings and " - "regenerate the lines or adjust the impacted lines " - "manually" - ) - self._note += note + line_notes = [ + _( + "Conversion from unit of measure '%s' to 'Kg' " + "is not implemented yet. It is needed for product '%s'." + ) + % (source_uom.name, product.name_get()[0][1]) + ] + self._note += self._format_line_note(inv_line, line_nbr, line_notes) return weight, suppl_unit_qty return weight, suppl_unit_qty @@ -449,9 +422,7 @@ class IntrastatProductDeclaration(models.Model): return incoterm def _get_product_origin_country(self, inv_line): - return ( - inv_line.product_origin_country_id or inv_line.product_id.origin_country_id - ) + return inv_line.product_id.origin_country_id def _update_computation_line_vals(self, inv_line, line_vals): """ placeholder for localization modules """ @@ -527,6 +498,15 @@ class IntrastatProductDeclaration(models.Model): """ placeholder for localization modules """ pass + def _format_line_note(self, line, line_nbr, line_notes): + indent = 8 * " " + note = _("Invoice %s, line %s") % (line.move_id.name, line_nbr) + note += ":\n" + for line_note in line_notes: + note += indent + line_note + note += "\n" + return note + def _gather_invoices(self): lines = [] @@ -534,7 +514,8 @@ class IntrastatProductDeclaration(models.Model): self._gather_invoices_init() domain = self._prepare_invoice_domain() - invoices = self.env["account.move"].search(domain) + order = "journal_id, name" + invoices = self.env["account.move"].search(domain, order=order) for invoice in invoices: @@ -542,7 +523,11 @@ class IntrastatProductDeclaration(models.Model): total_inv_accessory_costs_cc = 0.0 # in company currency total_inv_product_cc = 0.0 # in company currency total_inv_weight = 0.0 - for inv_line in invoice.invoice_line_ids: + for line_nbr, inv_line in enumerate(invoice.invoice_line_ids, start=1): + self._line_nbr = line_nbr + inv_intrastat_line = invoice.intrastat_line_ids.filtered( + lambda r: r.invoice_line_id == inv_line + ) if ( accessory_costs @@ -587,39 +572,47 @@ class IntrastatProductDeclaration(models.Model): ) continue - if inv_line.hs_code_id: - hs_code = inv_line.hs_code_id + if inv_intrastat_line: + hs_code = inv_intrastat_line.hs_code_id elif inv_line.product_id and self._is_product(inv_line): hs_code = inv_line.product_id.get_hs_code_recursively() if not hs_code: - note = "\n" + _( - "Missing H.S. code on product %s. " - "This product is present in invoice %s." - ) % ( - inv_line.product_id.name_get()[0][1], - inv_line.move_id.name, + line_notes = [ + _("Missing Intrastat Code on product %s. ") + % (inv_line.product_id.name_get()[0][1]) + ] + self._note += self._format_line_note( + inv_line, line_nbr, line_notes ) - self._note += note continue else: _logger.info( "Skipping invoice line %s qty %s " - "of invoice %s. Reason: no product nor hs_code" + "of invoice %s. Reason: no product nor Intrastat Code" % (inv_line.name, inv_line.quantity, invoice.name) ) continue intrastat_transaction = self._get_intrastat_transaction(inv_line) - weight, suppl_unit_qty = self._get_weight_and_supplunits( - inv_line, hs_code - ) + if inv_intrastat_line: + weight = inv_intrastat_line.transaction_weight + suppl_unit_qty = inv_intrastat_line.transaction_suppl_unit_qty + else: + weight, suppl_unit_qty = self._get_weight_and_supplunits( + inv_line, hs_code + ) total_inv_weight += weight amount_company_currency = self._get_amount(inv_line) total_inv_product_cc += amount_company_currency - product_origin_country = self._get_product_origin_country(inv_line) + if inv_intrastat_line: + product_origin_country = ( + inv_intrastat_line.product_origin_country_id + ) + else: + product_origin_country = self._get_product_origin_country(inv_line) region = self._get_region(inv_line) diff --git a/intrastat_product/readme/CONFIGURE.rst b/intrastat_product/readme/CONFIGURE.rst new file mode 100644 index 0000000..5ca9a9f --- /dev/null +++ b/intrastat_product/readme/CONFIGURE.rst @@ -0,0 +1,14 @@ +By default the intrastat declaration is generated based upon the product record master data. +Hence unexpected results may occur in case this master data is not accurate, +e.g. wrong or missing weight, country of origin, ... + +| + +This can be corrected by changing the appropriate fields when analysing the intrastat declaration +but this can be challenging in case of large transaction volumes and especially in the specific use +case where the product weight cannot be encoded correctly on the product records (e.g. products with variable weight). + +| + +It is possible to allow encoding the intrastat transaction details on the purchase/sale invoice +via the "intrastat_product.group_invoice_intrastat_transaction_detail" usability group. diff --git a/intrastat_product/security/intrastat_security.xml b/intrastat_product/security/intrastat_security.xml index b1e9d11..82552a5 100644 --- a/intrastat_product/security/intrastat_security.xml +++ b/intrastat_product/security/intrastat_security.xml @@ -1,24 +1,35 @@ - - - Intrastat Transaction Company rule - - ['|', ('company_id', '=', False), ('company_id', 'in', company_ids)] - - - Intrastat Region Company rule - - ['|', ('company_id', '=', False), ('company_id', 'in', company_ids)] - - - Intrastat Product Declaration Company rule - - ['|', ('company_id', '=', False), ('company_id', 'in', company_ids)] - + + + + Invoice Intrastat Transaction Details + Allow to encode Intrastat Transaction Details on Invoices + + + + + + Intrastat Transaction Company rule + + ['|', ('company_id', '=', False), ('company_id', 'in', company_ids)] + + + Intrastat Region Company rule + + ['|', ('company_id', '=', False), ('company_id', 'in', company_ids)] + + + Intrastat Product Declaration Company rule + + ['|', ('company_id', '=', False), ('company_id', 'in', company_ids)] + + diff --git a/intrastat_product/security/ir.model.access.csv b/intrastat_product/security/ir.model.access.csv index bd1ca7c..ac93450 100644 --- a/intrastat_product/security/ir.model.access.csv +++ b/intrastat_product/security/ir.model.access.csv @@ -8,6 +8,7 @@ access_intrastat_transport_mode_full,Full access on Intrastat Transport Modes to access_intrastat_region_read,Read access on Intrastat Regions,model_intrastat_region,,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_account_move_intrastat_line,Full access on Invoice Intrastat Lines,model_account_move_intrastat_line,account.group_account_invoice,1,1,1,1 access_intrastat_product_declaration,Full access on Intrastat Product Declarations to Accountant,model_intrastat_product_declaration,account.group_account_user,1,1,1,1 access_intrastat_product_computation_line,Full access on Intrastat Product Computation Lines to Accountant,model_intrastat_product_computation_line,account.group_account_user,1,1,1,1 access_intrastat_product_declaration_line,Full access on Intrastat Product Declaration Lines to Accountant,model_intrastat_product_declaration_line,account.group_account_user,1,1,1,1 diff --git a/intrastat_product/static/description/index.html b/intrastat_product/static/description/index.html index 4cf023e..7a63185 100644 --- a/intrastat_product/static/description/index.html +++ b/intrastat_product/static/description/index.html @@ -382,12 +382,13 @@ the module for the Intrastat Product Declaration for Belgium
+
+

Configuration

+

By default the intrastat declaration is generated based upon the product record master data. +Hence unexpected results may occur in case this master data is not accurate, +e.g. wrong or missing weight, country of origin, …

+
+

+
+

This can be corrected by changing the appropriate fields when analysing the intrastat declaration +but this can be challenging in case of large transaction volumes and especially in the specific use +case where the product weight cannot be encoded correctly on the product records (e.g. products with variable weight).

+
+

+
+

It is possible to allow encoding the intrastat transaction details on the purchase/sale invoice +via the “intrastat_product.group_invoice_intrastat_transaction_detail” usability group.

+
-

Usage

+

Usage

This module is used in combination with the country-specific localization module(s).

Coding guidelines for localization module:

@@ -427,7 +445,7 @@ the customization or new method is required for multiple countries).

-

Bug Tracker

+

Bug Tracker

Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us smashing it by providing a detailed and welcomed @@ -435,9 +453,9 @@ If you spotted it first, help us smashing it by providing a detailed and welcome

Do not contact contributors directly about support or help with technical issues.

-

Credits

+

Credits

-

Authors

+

Authors

  • brain-tec AG
  • Akretion
  • @@ -445,14 +463,14 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
-

Contributors

+

Contributors

-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association

OCA, or the Odoo Community Association, is a nonprofit organization whose diff --git a/intrastat_product/views/account_move.xml b/intrastat_product/views/account_move.xml index 7254b8e..09d35bd 100644 --- a/intrastat_product/views/account_move.xml +++ b/intrastat_product/views/account_move.xml @@ -19,22 +19,42 @@ - - - - - - - - - - + + +

+
+ + + + + + + + + + + + +