From 087ad2c1de69e0dea6fc58630467979c51f8a2db Mon Sep 17 00:00:00 2001 From: Ernad Husremovic Date: Fri, 29 Aug 2025 15:49:21 +0200 Subject: [PATCH] Initial commit: Akretion Odoo packages (2 packages) --- README.md | 52 +++ .../README.md | 53 +++ .../account_invoice_margin/__init__.py | 1 + .../account_invoice_margin/__manifest__.py | 26 ++ .../account_invoice_margin/i18n/fr.po | 98 +++++ .../account_invoice_margin/models/__init__.py | 2 + .../models/account_invoice_report.py | 17 + .../models/account_move.py | 109 +++++ .../views/account_move.xml | 55 +++ .../doc/ARCHITECTURE.md | 32 ++ .../doc/CONFIGURATION.md | 3 + .../doc/CONTROLLERS.md | 3 + .../doc/DEPENDENCIES.md | 5 + .../doc/FAQ.md | 4 + .../doc/INSTALL.md | 7 + .../doc/MODELS.md | 14 + .../doc/OVERVIEW.md | 6 + .../doc/REPORTS.md | 3 + .../doc/SECURITY.md | 8 + .../doc/TROUBLESHOOTING.md | 5 + .../doc/USAGE.md | 7 + .../doc/WIZARDS.md | 3 + .../pyproject.toml | 42 ++ .../README.md | 70 ++++ .../doc/ARCHITECTURE.md | 32 ++ .../doc/CONFIGURATION.md | 3 + .../doc/CONTROLLERS.md | 3 + .../doc/DEPENDENCIES.md | 7 + .../doc/FAQ.md | 4 + .../doc/INSTALL.md | 7 + .../doc/MODELS.md | 14 + .../doc/OVERVIEW.md | 6 + .../doc/REPORTS.md | 3 + .../doc/SECURITY.md | 34 ++ .../doc/TROUBLESHOOTING.md | 5 + .../doc/USAGE.md | 7 + .../doc/WIZARDS.md | 10 + .../product_print_zpl_barcode/__init__.py | 2 + .../product_print_zpl_barcode/__manifest__.py | 55 +++ .../data/barcode_sequence.xml | 26 ++ .../product_print_zpl_barcode/i18n/bs.po | 392 ++++++++++++++++++ .../i18n/product_print_zpl_barcode.pot | 392 ++++++++++++++++++ .../models/__init__.py | 2 + .../models/product.py | 98 +++++ .../models/stock_picking.py | 25 ++ .../security/ir.model.access.csv | 3 + .../views/product.xml | 67 +++ .../views/stock_picking.xml | 21 + .../wizard/__init__.py | 2 + .../wizard/product_print_zpl_barcode.py | 376 +++++++++++++++++ .../wizard/product_print_zpl_barcode_view.xml | 62 +++ .../wizard/res_config_settings.py | 24 ++ .../wizard/res_config_settings_view.xml | 30 ++ .../pyproject.toml | 44 ++ 54 files changed, 2381 insertions(+) create mode 100644 README.md create mode 100644 odoo-bringout-akretion-account_invoice_margin/README.md create mode 100644 odoo-bringout-akretion-account_invoice_margin/account_invoice_margin/__init__.py create mode 100644 odoo-bringout-akretion-account_invoice_margin/account_invoice_margin/__manifest__.py create mode 100644 odoo-bringout-akretion-account_invoice_margin/account_invoice_margin/i18n/fr.po create mode 100644 odoo-bringout-akretion-account_invoice_margin/account_invoice_margin/models/__init__.py create mode 100644 odoo-bringout-akretion-account_invoice_margin/account_invoice_margin/models/account_invoice_report.py create mode 100644 odoo-bringout-akretion-account_invoice_margin/account_invoice_margin/models/account_move.py create mode 100644 odoo-bringout-akretion-account_invoice_margin/account_invoice_margin/views/account_move.xml create mode 100644 odoo-bringout-akretion-account_invoice_margin/doc/ARCHITECTURE.md create mode 100644 odoo-bringout-akretion-account_invoice_margin/doc/CONFIGURATION.md create mode 100644 odoo-bringout-akretion-account_invoice_margin/doc/CONTROLLERS.md create mode 100644 odoo-bringout-akretion-account_invoice_margin/doc/DEPENDENCIES.md create mode 100644 odoo-bringout-akretion-account_invoice_margin/doc/FAQ.md create mode 100644 odoo-bringout-akretion-account_invoice_margin/doc/INSTALL.md create mode 100644 odoo-bringout-akretion-account_invoice_margin/doc/MODELS.md create mode 100644 odoo-bringout-akretion-account_invoice_margin/doc/OVERVIEW.md create mode 100644 odoo-bringout-akretion-account_invoice_margin/doc/REPORTS.md create mode 100644 odoo-bringout-akretion-account_invoice_margin/doc/SECURITY.md create mode 100644 odoo-bringout-akretion-account_invoice_margin/doc/TROUBLESHOOTING.md create mode 100644 odoo-bringout-akretion-account_invoice_margin/doc/USAGE.md create mode 100644 odoo-bringout-akretion-account_invoice_margin/doc/WIZARDS.md create mode 100644 odoo-bringout-akretion-account_invoice_margin/pyproject.toml create mode 100644 odoo-bringout-akretion-product_print_zpl_barcode/README.md create mode 100644 odoo-bringout-akretion-product_print_zpl_barcode/doc/ARCHITECTURE.md create mode 100644 odoo-bringout-akretion-product_print_zpl_barcode/doc/CONFIGURATION.md create mode 100644 odoo-bringout-akretion-product_print_zpl_barcode/doc/CONTROLLERS.md create mode 100644 odoo-bringout-akretion-product_print_zpl_barcode/doc/DEPENDENCIES.md create mode 100644 odoo-bringout-akretion-product_print_zpl_barcode/doc/FAQ.md create mode 100644 odoo-bringout-akretion-product_print_zpl_barcode/doc/INSTALL.md create mode 100644 odoo-bringout-akretion-product_print_zpl_barcode/doc/MODELS.md create mode 100644 odoo-bringout-akretion-product_print_zpl_barcode/doc/OVERVIEW.md create mode 100644 odoo-bringout-akretion-product_print_zpl_barcode/doc/REPORTS.md create mode 100644 odoo-bringout-akretion-product_print_zpl_barcode/doc/SECURITY.md create mode 100644 odoo-bringout-akretion-product_print_zpl_barcode/doc/TROUBLESHOOTING.md create mode 100644 odoo-bringout-akretion-product_print_zpl_barcode/doc/USAGE.md create mode 100644 odoo-bringout-akretion-product_print_zpl_barcode/doc/WIZARDS.md create mode 100644 odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/__init__.py create mode 100644 odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/__manifest__.py create mode 100644 odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/data/barcode_sequence.xml create mode 100644 odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/i18n/bs.po create mode 100644 odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/i18n/product_print_zpl_barcode.pot create mode 100644 odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/models/__init__.py create mode 100644 odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/models/product.py create mode 100644 odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/models/stock_picking.py create mode 100644 odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/security/ir.model.access.csv create mode 100644 odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/views/product.xml create mode 100644 odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/views/stock_picking.xml create mode 100644 odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/wizard/__init__.py create mode 100644 odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/wizard/product_print_zpl_barcode.py create mode 100644 odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/wizard/product_print_zpl_barcode_view.xml create mode 100644 odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/wizard/res_config_settings.py create mode 100644 odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/wizard/res_config_settings_view.xml create mode 100644 odoo-bringout-akretion-product_print_zpl_barcode/pyproject.toml diff --git a/README.md b/README.md new file mode 100644 index 0000000..933fb9b --- /dev/null +++ b/README.md @@ -0,0 +1,52 @@ +# Akretion Odoo Packages + +This repository contains **2** Odoo packages from Akretion vendor. + +## About Akretion + +Akretion is a recognized vendor in the Odoo ecosystem, providing specialized addons and customizations. + +## Packages Included (2 packages) + +- **odoo-bringout-akretion-account_invoice_margin** - Account Invoice Margin +- **odoo-bringout-akretion-product_print_zpl_barcode** - Product Print Zpl Barcode + + +## Installation + +Install any package from this collection: + +```bash +# Install from local directory +pip install packages/akretion/PACKAGE_NAME/ + +# Install in development mode +pip install -e packages/akretion/PACKAGE_NAME/ + +# Using uv (recommended for speed) +uv add packages/akretion/PACKAGE_NAME/ +``` + +## Repository Structure + +Each package in this repository follows the standard Odoo addon structure: + +``` +akretion/ +├── odoo-bringout-akretion-ADDON/ +│ ├── ADDON_NAME/ # Complete addon code +│ │ ├── __init__.py +│ │ ├── __manifest__.py +│ │ └── ... (models, views, etc.) +│ ├── pyproject.toml # Python package configuration +│ └── README.md # Package documentation +└── ... +``` + +## License + +Each package maintains its original license as specified by Akretion. + +## Support + +For support with these packages, please refer to the original Akretion documentation or community resources. diff --git a/odoo-bringout-akretion-account_invoice_margin/README.md b/odoo-bringout-akretion-account_invoice_margin/README.md new file mode 100644 index 0000000..3765ca8 --- /dev/null +++ b/odoo-bringout-akretion-account_invoice_margin/README.md @@ -0,0 +1,53 @@ +# Account Invoice Margin + + +This module copies the field *standard_price* of the product on the invoice line when the invoice line is created. The allows the computation of the margin of the invoice. + +A new measure *Margin* is available in the Invoice Analysis. + +This module has been written by Alexis de Lattre from Akretion +. + + +## Installation + +```bash +pip install odoo-bringout-akretion-account_invoice_margin +``` + +## Dependencies + +This addon depends on: +- account + +## Manifest Information + +- **Name**: Account Invoice Margin +- **Version**: 16.0.1.0.0 +- **Category**: Invoicing Management +- **License**: AGPL-3 +- **Installable**: True + +## Source + +Custom addon from bringout-akretion vendor, addon `account_invoice_margin`. + +## License + +This package maintains the original AGPL-3 license from the addon. + +## Documentation + +- Overview: doc/OVERVIEW.md +- Architecture: doc/ARCHITECTURE.md +- Models: doc/MODELS.md +- Controllers: doc/CONTROLLERS.md +- Wizards: doc/WIZARDS.md +- Reports: doc/REPORTS.md +- Security: doc/SECURITY.md +- Install: doc/INSTALL.md +- Usage: doc/USAGE.md +- Configuration: doc/CONFIGURATION.md +- Dependencies: doc/DEPENDENCIES.md +- Troubleshooting: doc/TROUBLESHOOTING.md +- FAQ: doc/FAQ.md diff --git a/odoo-bringout-akretion-account_invoice_margin/account_invoice_margin/__init__.py b/odoo-bringout-akretion-account_invoice_margin/account_invoice_margin/__init__.py new file mode 100644 index 0000000..0650744 --- /dev/null +++ b/odoo-bringout-akretion-account_invoice_margin/account_invoice_margin/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/odoo-bringout-akretion-account_invoice_margin/account_invoice_margin/__manifest__.py b/odoo-bringout-akretion-account_invoice_margin/account_invoice_margin/__manifest__.py new file mode 100644 index 0000000..d140802 --- /dev/null +++ b/odoo-bringout-akretion-account_invoice_margin/account_invoice_margin/__manifest__.py @@ -0,0 +1,26 @@ +# Copyright 2015-2025 Akretion France (https://www.akretion.com) +# @author Alexis de Lattre +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + 'name': 'Account Invoice Margin', + 'version': '16.0.1.0.0', + 'category': 'Invoicing Management', + 'license': 'AGPL-3', + 'summary': 'Copy standard price on invoice line and compute margins', + 'description': """ +This module copies the field *standard_price* of the product on the invoice line when the invoice line is created. The allows the computation of the margin of the invoice. + +A new measure *Margin* is available in the Invoice Analysis. + +This module has been written by Alexis de Lattre from Akretion +. + """, + 'author': 'Akretion', + 'website': 'https://github.com/akretion/odoo-usability', + 'depends': ['account'], + 'data': [ + 'views/account_move.xml', + ], + 'installable': True, +} diff --git a/odoo-bringout-akretion-account_invoice_margin/account_invoice_margin/i18n/fr.po b/odoo-bringout-akretion-account_invoice_margin/account_invoice_margin/i18n/fr.po new file mode 100644 index 0000000..634073d --- /dev/null +++ b/odoo-bringout-akretion-account_invoice_margin/account_invoice_margin/i18n/fr.po @@ -0,0 +1,98 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * account_invoice_margin +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2025-01-16 16:24+0000\n" +"PO-Revision-Date: 2025-01-16 16:24+0000\n" +"Last-Translator: Alexis de Lattre \n" +"Language-Team: \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: account_invoice_margin +#: model:ir.model,name:account_invoice_margin.model_account_invoice_report +msgid "Invoices Statistics" +msgstr "Statistiques des factures" + +#. module: account_invoice_margin +#: model:ir.model,name:account_invoice_margin.model_account_move +msgid "Journal Entry" +msgstr "Pièce comptable" + +#. module: account_invoice_margin +#: model:ir.model,name:account_invoice_margin.model_account_move_line +msgid "Journal Item" +msgstr "Écriture comptable" + +#. module: account_invoice_margin +#: model:ir.model.fields,field_description:account_invoice_margin.field_account_invoice_report__margin +#: model_terms:ir.ui.view,arch_db:account_invoice_margin.view_invoice_tree +#: model_terms:ir.ui.view,arch_db:account_invoice_margin.view_move_form +msgid "Margin" +msgstr "Marge" + +#. module: account_invoice_margin +#: model_terms:ir.ui.view,arch_db:account_invoice_margin.view_move_form +msgid "Margin %" +msgstr "Marge %" + +#. module: account_invoice_margin +#: model:ir.model.fields,field_description:account_invoice_margin.field_account_move_line__margin_rate +msgid "Margin Rate" +msgstr "Taux de marge" + +#. module: account_invoice_margin +#: model:ir.model.fields,field_description:account_invoice_margin.field_account_bank_statement_line__margin_company_currency +#: model:ir.model.fields,field_description:account_invoice_margin.field_account_move__margin_company_currency +#: model:ir.model.fields,field_description:account_invoice_margin.field_account_move_line__margin_company_currency +#: model:ir.model.fields,field_description:account_invoice_margin.field_account_payment__margin_company_currency +msgid "Margin in Company Currency" +msgstr "Marge dans la devise de la société" + +#. module: account_invoice_margin +#: model:ir.model.fields,field_description:account_invoice_margin.field_account_bank_statement_line__margin_invoice_currency +#: model:ir.model.fields,field_description:account_invoice_margin.field_account_move__margin_invoice_currency +#: model:ir.model.fields,field_description:account_invoice_margin.field_account_move_line__margin_invoice_currency +#: model:ir.model.fields,field_description:account_invoice_margin.field_account_payment__margin_invoice_currency +msgid "Margin in Invoice Currency" +msgstr "Marge dans la devise de la facture" + +#. module: account_invoice_margin +#: model:ir.model.fields,help:account_invoice_margin.field_account_move_line__margin_rate +msgid "Margin rate in percentage of the sale price" +msgstr "Taux de marge en pourcentage du prix de vente" + +#. module: account_invoice_margin +#: model:ir.model.fields,field_description:account_invoice_margin.field_account_move_line__standard_price_company_currency +msgid "Unit Cost in Company Currency" +msgstr "Coût unitaire dans la devise de la société" + +#. module: account_invoice_margin +#: model:ir.model.fields,field_description:account_invoice_margin.field_account_move_line__standard_price_invoice_currency +msgid "Unit Cost in Invoice Currency" +msgstr "Coût unitaire dans la devise de la facture" + +#. module: account_invoice_margin +#: model:ir.model.fields,help:account_invoice_margin.field_account_move_line__standard_price_company_currency +msgid "" +"Unit Cost in company currency in the unit of measure of the invoice line " +"(which may be different from the unit of measure of the product)." +msgstr "" +"Coût unitaire dans la devise de la société dans l'unité de mesure de la " +"ligne de facture (qui peut être différente de l'unité de mesure du produit)." + +#. module: account_invoice_margin +#: model:ir.model.fields,help:account_invoice_margin.field_account_move_line__standard_price_invoice_currency +msgid "" +"Unit Cost in invoice currency in the unit of measure of the invoice line " +"(which may be different from the unit of measure of the product)." +msgstr "" +"Coût unitaire dans la devise de la facture dans l'unité de mesure " +"de la ligne de la facture (qui peut être différente de l'unité de mesure du produit)." diff --git a/odoo-bringout-akretion-account_invoice_margin/account_invoice_margin/models/__init__.py b/odoo-bringout-akretion-account_invoice_margin/account_invoice_margin/models/__init__.py new file mode 100644 index 0000000..15214dd --- /dev/null +++ b/odoo-bringout-akretion-account_invoice_margin/account_invoice_margin/models/__init__.py @@ -0,0 +1,2 @@ +from . import account_move +from . import account_invoice_report diff --git a/odoo-bringout-akretion-account_invoice_margin/account_invoice_margin/models/account_invoice_report.py b/odoo-bringout-akretion-account_invoice_margin/account_invoice_margin/models/account_invoice_report.py new file mode 100644 index 0000000..a151216 --- /dev/null +++ b/odoo-bringout-akretion-account_invoice_margin/account_invoice_margin/models/account_invoice_report.py @@ -0,0 +1,17 @@ +# Copyright 2018-2025 Akretion France (https://www.akretion.com) +# @author Alexis de Lattre +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class AccountInvoiceReport(models.Model): + _inherit = 'account.invoice.report' + + margin = fields.Float(string='Margin', readonly=True) + + @api.model + def _select(self): + select_str = super()._select() + select_str += ", line.margin_company_currency * currency_table.rate AS margin" + return select_str diff --git a/odoo-bringout-akretion-account_invoice_margin/account_invoice_margin/models/account_move.py b/odoo-bringout-akretion-account_invoice_margin/account_invoice_margin/models/account_move.py new file mode 100644 index 0000000..2581c36 --- /dev/null +++ b/odoo-bringout-akretion-account_invoice_margin/account_invoice_margin/models/account_move.py @@ -0,0 +1,109 @@ +# Copyright 2015-2025 Akretion France (https://www.akretion.com) +# @author Alexis de Lattre +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class AccountMoveLine(models.Model): + _inherit = 'account.move.line' + + standard_price_company_currency = fields.Float( + compute='_compute_margin', store=True, digits='Product Price', + string='Unit Cost in Company Currency', + help="Unit Cost in company currency in the unit of measure " + "of the invoice line (which may be different from the unit " + "of measure of the product).") + standard_price_invoice_currency = fields.Float( + compute='_compute_margin', store=True, digits='Product Price', + string='Unit Cost in Invoice Currency', + help="Unit Cost in invoice currency in the unit of measure " + "of the invoice line (which may be different from the unit " + "of measure of the product).") + margin_invoice_currency = fields.Monetary( + compute='_compute_margin', store=True, + string='Margin in Invoice Currency', currency_field='currency_id') + margin_company_currency = fields.Monetary( + compute='_compute_margin', store=True, + string='Margin in Company Currency', + currency_field='company_currency_id') + margin_rate = fields.Float( + string="Margin Rate", readonly=True, store=True, + compute='_compute_margin', + digits=(16, 2), help="Margin rate in percentage of the sale price") + + @api.depends( + 'product_id', 'product_uom_id', 'display_type', 'quantity', 'price_subtotal', + 'move_id.currency_id', 'move_id.move_type', 'move_id.company_id', 'move_id.date') + def _compute_margin(self): + for ml in self: + standard_price_comp_cur = 0.0 + standard_price_inv_cur = 0.0 + margin_inv_cur = 0.0 + margin_comp_cur = 0.0 + margin_rate = 0.0 + if ( + ml.display_type == 'product' and + ml.product_id and + ml.move_type in ('out_invoice', 'out_refund')): + move = ml.move_id + date = move.date + company = move.company_id + company_currency = company.currency_id + move_currency = move.currency_id + standard_price_comp_cur = ml.product_id.with_company(company.id).standard_price + if ml.product_uom_id and ml.product_uom_id != ml.product_id.uom_id: + standard_price_comp_cur = ml.product_id.uom_id._compute_price( + standard_price_comp_cur, ml.product_uom_id) + standard_price_inv_cur = company_currency._convert( + standard_price_comp_cur, move_currency, company, date) + margin_inv_cur =\ + ml.price_subtotal - (ml.quantity * standard_price_inv_cur) + margin_comp_cur = move_currency._convert( + margin_inv_cur, company_currency, company, date) + if ml.price_subtotal: + margin_rate = 100 * margin_inv_cur / ml.price_subtotal + # for a refund, margin should be negative + # but margin rate should stay positive + if ml.move_type == 'out_refund': + margin_inv_cur *= -1 + margin_comp_cur *= -1 + ml.standard_price_company_currency = standard_price_comp_cur + ml.standard_price_invoice_currency = standard_price_inv_cur + ml.margin_invoice_currency = margin_inv_cur + ml.margin_company_currency = margin_comp_cur + ml.margin_rate = margin_rate + + +class AccountMove(models.Model): + _inherit = 'account.move' + + margin_invoice_currency = fields.Monetary( + string='Margin in Invoice Currency', + compute='_compute_margin', store=True, + currency_field='currency_id') + margin_company_currency = fields.Monetary( + string='Margin in Company Currency', + compute='_compute_margin', store=True, + currency_field='company_currency_id') + + @api.depends( + 'move_type', + 'invoice_line_ids.margin_invoice_currency', + 'invoice_line_ids.margin_company_currency') + def _compute_margin(self): + rg_res = self.env['account.move.line'].read_group( + [ + ('move_id', 'in', self.ids), + ('display_type', '=', 'product'), + ('move_id.move_type', 'in', ('out_invoice', 'out_refund')), + ], + ['move_id', 'margin_invoice_currency:sum', 'margin_company_currency:sum'], + ['move_id']) + mapped_data = dict([(x['move_id'][0], { + 'margin_invoice_currency': x['margin_invoice_currency'], + 'margin_company_currency': x['margin_company_currency'], + }) for x in rg_res]) + for move in self: + move.margin_invoice_currency = mapped_data.get(move.id, {}).get('margin_invoice_currency') + move.margin_company_currency = mapped_data.get(move.id, {}).get('margin_company_currency') diff --git a/odoo-bringout-akretion-account_invoice_margin/account_invoice_margin/views/account_move.xml b/odoo-bringout-akretion-account_invoice_margin/account_invoice_margin/views/account_move.xml new file mode 100644 index 0000000..9f72317 --- /dev/null +++ b/odoo-bringout-akretion-account_invoice_margin/account_invoice_margin/views/account_move.xml @@ -0,0 +1,55 @@ + + + + + + + margin.account.move.form + account.move + + + + + + + + + + + + + + + + + + + + + + account.move + + + + + + + + + diff --git a/odoo-bringout-akretion-account_invoice_margin/doc/ARCHITECTURE.md b/odoo-bringout-akretion-account_invoice_margin/doc/ARCHITECTURE.md new file mode 100644 index 0000000..c7cfc81 --- /dev/null +++ b/odoo-bringout-akretion-account_invoice_margin/doc/ARCHITECTURE.md @@ -0,0 +1,32 @@ +# Architecture + +```mermaid +flowchart TD + U[Users] -->|HTTP| V[Views and QWeb Templates] + V --> C[Controllers] + V --> W[Wizards – Transient Models] + C --> M[Models and ORM] + W --> M + M --> R[Reports] + DX[Data XML] --> M + S[Security – ACLs and Groups] -. enforces .-> M + + subgraph Account_invoice_margin Module - account_invoice_margin + direction LR + M:::layer + W:::layer + C:::layer + V:::layer + R:::layer + S:::layer + DX:::layer + end + + classDef layer fill:#eef8ff,stroke:#6ea8fe,stroke-width:1px +``` + +Notes +- Views include tree/form/kanban templates and report templates. +- Controllers provide website/portal routes when present. +- Wizards are UI flows implemented with `models.TransientModel`. +- Data XML loads data/demo records; Security defines groups and access. diff --git a/odoo-bringout-akretion-account_invoice_margin/doc/CONFIGURATION.md b/odoo-bringout-akretion-account_invoice_margin/doc/CONFIGURATION.md new file mode 100644 index 0000000..2a13585 --- /dev/null +++ b/odoo-bringout-akretion-account_invoice_margin/doc/CONFIGURATION.md @@ -0,0 +1,3 @@ +# Configuration + +Refer to Odoo settings for account_invoice_margin. Configure related models, access rights, and options as needed. diff --git a/odoo-bringout-akretion-account_invoice_margin/doc/CONTROLLERS.md b/odoo-bringout-akretion-account_invoice_margin/doc/CONTROLLERS.md new file mode 100644 index 0000000..f628e77 --- /dev/null +++ b/odoo-bringout-akretion-account_invoice_margin/doc/CONTROLLERS.md @@ -0,0 +1,3 @@ +# Controllers + +This module does not define custom HTTP controllers. diff --git a/odoo-bringout-akretion-account_invoice_margin/doc/DEPENDENCIES.md b/odoo-bringout-akretion-account_invoice_margin/doc/DEPENDENCIES.md new file mode 100644 index 0000000..99c6b28 --- /dev/null +++ b/odoo-bringout-akretion-account_invoice_margin/doc/DEPENDENCIES.md @@ -0,0 +1,5 @@ +# Dependencies + +This addon depends on: + +- [account](../../odoo-bringout-oca-ocb-account) diff --git a/odoo-bringout-akretion-account_invoice_margin/doc/FAQ.md b/odoo-bringout-akretion-account_invoice_margin/doc/FAQ.md new file mode 100644 index 0000000..5e2ae84 --- /dev/null +++ b/odoo-bringout-akretion-account_invoice_margin/doc/FAQ.md @@ -0,0 +1,4 @@ +# FAQ + +- Q: Which Odoo version? A: 16.0 (OCA/OCB packaged). +- Q: How to enable? A: Start server with --addon account_invoice_margin or install in UI. diff --git a/odoo-bringout-akretion-account_invoice_margin/doc/INSTALL.md b/odoo-bringout-akretion-account_invoice_margin/doc/INSTALL.md new file mode 100644 index 0000000..6e5e3f4 --- /dev/null +++ b/odoo-bringout-akretion-account_invoice_margin/doc/INSTALL.md @@ -0,0 +1,7 @@ +# Install + +```bash +pip install odoo-bringout-akretion-account_invoice_margin" +# or +uv pip install odoo-bringout-akretion-account_invoice_margin" +``` diff --git a/odoo-bringout-akretion-account_invoice_margin/doc/MODELS.md b/odoo-bringout-akretion-account_invoice_margin/doc/MODELS.md new file mode 100644 index 0000000..50d5d19 --- /dev/null +++ b/odoo-bringout-akretion-account_invoice_margin/doc/MODELS.md @@ -0,0 +1,14 @@ +# Models + +Detected core models and extensions in account_invoice_margin. + +```mermaid +classDiagram + class account_invoice_report + class account_move + class account_move_line +``` + +Notes +- Classes show model technical names; fields omitted for brevity. +- Items listed under _inherit are extensions of existing models. diff --git a/odoo-bringout-akretion-account_invoice_margin/doc/OVERVIEW.md b/odoo-bringout-akretion-account_invoice_margin/doc/OVERVIEW.md new file mode 100644 index 0000000..bb8f106 --- /dev/null +++ b/odoo-bringout-akretion-account_invoice_margin/doc/OVERVIEW.md @@ -0,0 +1,6 @@ +# Overview + +Packaged Odoo addon: account_invoice_margin. Provides features documented in upstream Odoo 16 under this addon. + +- Source: OCA/OCB 16.0, addon account_invoice_margin +- License: LGPL-3 diff --git a/odoo-bringout-akretion-account_invoice_margin/doc/REPORTS.md b/odoo-bringout-akretion-account_invoice_margin/doc/REPORTS.md new file mode 100644 index 0000000..e0ea35f --- /dev/null +++ b/odoo-bringout-akretion-account_invoice_margin/doc/REPORTS.md @@ -0,0 +1,3 @@ +# Reports + +This module does not define custom reports. diff --git a/odoo-bringout-akretion-account_invoice_margin/doc/SECURITY.md b/odoo-bringout-akretion-account_invoice_margin/doc/SECURITY.md new file mode 100644 index 0000000..e07da9d --- /dev/null +++ b/odoo-bringout-akretion-account_invoice_margin/doc/SECURITY.md @@ -0,0 +1,8 @@ +# Security + +This module does not define custom security rules or access controls beyond Odoo defaults. + +Default Odoo security applies: +- Base user access through standard groups +- Model access inherited from dependencies +- No custom row-level security rules diff --git a/odoo-bringout-akretion-account_invoice_margin/doc/TROUBLESHOOTING.md b/odoo-bringout-akretion-account_invoice_margin/doc/TROUBLESHOOTING.md new file mode 100644 index 0000000..56853cb --- /dev/null +++ b/odoo-bringout-akretion-account_invoice_margin/doc/TROUBLESHOOTING.md @@ -0,0 +1,5 @@ +# Troubleshooting + +- Ensure Python and Odoo environment matches repo guidance. +- Check database connectivity and logs if startup fails. +- Validate that dependent addons listed in DEPENDENCIES.md are installed. diff --git a/odoo-bringout-akretion-account_invoice_margin/doc/USAGE.md b/odoo-bringout-akretion-account_invoice_margin/doc/USAGE.md new file mode 100644 index 0000000..53f3e57 --- /dev/null +++ b/odoo-bringout-akretion-account_invoice_margin/doc/USAGE.md @@ -0,0 +1,7 @@ +# Usage + +Start Odoo including this addon (from repo root): + +```bash +python3 scripts/nix_odoo_web_server.py --db-name mydb --addon account_invoice_margin +``` diff --git a/odoo-bringout-akretion-account_invoice_margin/doc/WIZARDS.md b/odoo-bringout-akretion-account_invoice_margin/doc/WIZARDS.md new file mode 100644 index 0000000..48e790d --- /dev/null +++ b/odoo-bringout-akretion-account_invoice_margin/doc/WIZARDS.md @@ -0,0 +1,3 @@ +# Wizards + +This module does not include UI wizards. diff --git a/odoo-bringout-akretion-account_invoice_margin/pyproject.toml b/odoo-bringout-akretion-account_invoice_margin/pyproject.toml new file mode 100644 index 0000000..b07aac5 --- /dev/null +++ b/odoo-bringout-akretion-account_invoice_margin/pyproject.toml @@ -0,0 +1,42 @@ +[project] +name = "odoo-bringout-akretion-account_invoice_margin" +version = "16.0.0" +description = "Account Invoice Margin - Copy standard price on invoice line and compute margins" +authors = [ + { name = "Ernad Husremovic", email = "hernad@bring.out.ba" } +] +dependencies = [ + "odoo-bringout-oca-ocb-account>=16.0.0", + "requests>=2.25.1" +] +readme = "README.md" +requires-python = ">= 3.11" +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Topic :: Office/Business", +] + +[project.urls] +homepage = "https://github.com/bringout/0" +repository = "https://github.com/bringout/0" + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[tool.hatch.metadata] +allow-direct-references = true + +[tool.hatch.build.targets.wheel] +packages = ["account_invoice_margin"] + +[tool.rye] +managed = true +dev-dependencies = [ + "pytest>=8.4.1", +] diff --git a/odoo-bringout-akretion-product_print_zpl_barcode/README.md b/odoo-bringout-akretion-product_print_zpl_barcode/README.md new file mode 100644 index 0000000..14b5799 --- /dev/null +++ b/odoo-bringout-akretion-product_print_zpl_barcode/README.md @@ -0,0 +1,70 @@ +# Product Generate Price Weight Barcode + + +Print product barcode stickers on ZPL printer +============================================= + +This module adds a wizard on product.product form view which allows to generate and print a product barcode sticker on a ZPL printer (such as Zebra GC420, GK420, ...). It can print: + +* regular product barcode stickers. These stickers will show: + * product name + * product price + * EAN13 or EAN8 barcode + +* price/weight barcode stickers. These stickers will show: + * product name + * weight (the wizard asks for this info) + * price + * price per kg + * EAN13 barcode + +It also allows to generate a private barcode for products without barcode. For that, you must configure the sequence "private.product.barcode". This sequence must be configured to produce 12 digits (for EAN13) or 7 digits (for EAN8) ; the checksum will be added automatically. + +This module has been written by Alexis de Lattre from Akretion +. + + +## Installation + +```bash +pip install odoo-bringout-akretion-product_print_zpl_barcode +``` + +## Dependencies + +This addon depends on: +- product +- barcodes +- stock + +## Manifest Information + +- **Name**: Product Generate Price Weight Barcode +- **Version**: 16.0.1.0.0 +- **Category**: Extra Tools +- **License**: AGPL-3 +- **Installable**: True + +## Source + +Custom addon from bringout-akretion vendor, addon `product_print_zpl_barcode`. + +## License + +This package maintains the original AGPL-3 license from the addon. + +## Documentation + +- Overview: doc/OVERVIEW.md +- Architecture: doc/ARCHITECTURE.md +- Models: doc/MODELS.md +- Controllers: doc/CONTROLLERS.md +- Wizards: doc/WIZARDS.md +- Reports: doc/REPORTS.md +- Security: doc/SECURITY.md +- Install: doc/INSTALL.md +- Usage: doc/USAGE.md +- Configuration: doc/CONFIGURATION.md +- Dependencies: doc/DEPENDENCIES.md +- Troubleshooting: doc/TROUBLESHOOTING.md +- FAQ: doc/FAQ.md diff --git a/odoo-bringout-akretion-product_print_zpl_barcode/doc/ARCHITECTURE.md b/odoo-bringout-akretion-product_print_zpl_barcode/doc/ARCHITECTURE.md new file mode 100644 index 0000000..8ee83bf --- /dev/null +++ b/odoo-bringout-akretion-product_print_zpl_barcode/doc/ARCHITECTURE.md @@ -0,0 +1,32 @@ +# Architecture + +```mermaid +flowchart TD + U[Users] -->|HTTP| V[Views and QWeb Templates] + V --> C[Controllers] + V --> W[Wizards – Transient Models] + C --> M[Models and ORM] + W --> M + M --> R[Reports] + DX[Data XML] --> M + S[Security – ACLs and Groups] -. enforces .-> M + + subgraph Product_print_zpl_barcode Module - product_print_zpl_barcode + direction LR + M:::layer + W:::layer + C:::layer + V:::layer + R:::layer + S:::layer + DX:::layer + end + + classDef layer fill:#eef8ff,stroke:#6ea8fe,stroke-width:1px +``` + +Notes +- Views include tree/form/kanban templates and report templates. +- Controllers provide website/portal routes when present. +- Wizards are UI flows implemented with `models.TransientModel`. +- Data XML loads data/demo records; Security defines groups and access. diff --git a/odoo-bringout-akretion-product_print_zpl_barcode/doc/CONFIGURATION.md b/odoo-bringout-akretion-product_print_zpl_barcode/doc/CONFIGURATION.md new file mode 100644 index 0000000..f614775 --- /dev/null +++ b/odoo-bringout-akretion-product_print_zpl_barcode/doc/CONFIGURATION.md @@ -0,0 +1,3 @@ +# Configuration + +Refer to Odoo settings for product_print_zpl_barcode. Configure related models, access rights, and options as needed. diff --git a/odoo-bringout-akretion-product_print_zpl_barcode/doc/CONTROLLERS.md b/odoo-bringout-akretion-product_print_zpl_barcode/doc/CONTROLLERS.md new file mode 100644 index 0000000..f628e77 --- /dev/null +++ b/odoo-bringout-akretion-product_print_zpl_barcode/doc/CONTROLLERS.md @@ -0,0 +1,3 @@ +# Controllers + +This module does not define custom HTTP controllers. diff --git a/odoo-bringout-akretion-product_print_zpl_barcode/doc/DEPENDENCIES.md b/odoo-bringout-akretion-product_print_zpl_barcode/doc/DEPENDENCIES.md new file mode 100644 index 0000000..8ce2b45 --- /dev/null +++ b/odoo-bringout-akretion-product_print_zpl_barcode/doc/DEPENDENCIES.md @@ -0,0 +1,7 @@ +# Dependencies + +This addon depends on: + +- [product](../../odoo-bringout-oca-ocb-product) +- [barcodes](../../odoo-bringout-oca-ocb-barcodes) +- [stock](../../odoo-bringout-oca-ocb-stock) diff --git a/odoo-bringout-akretion-product_print_zpl_barcode/doc/FAQ.md b/odoo-bringout-akretion-product_print_zpl_barcode/doc/FAQ.md new file mode 100644 index 0000000..8e99fe0 --- /dev/null +++ b/odoo-bringout-akretion-product_print_zpl_barcode/doc/FAQ.md @@ -0,0 +1,4 @@ +# FAQ + +- Q: Which Odoo version? A: 16.0 (OCA/OCB packaged). +- Q: How to enable? A: Start server with --addon product_print_zpl_barcode or install in UI. diff --git a/odoo-bringout-akretion-product_print_zpl_barcode/doc/INSTALL.md b/odoo-bringout-akretion-product_print_zpl_barcode/doc/INSTALL.md new file mode 100644 index 0000000..6f622cb --- /dev/null +++ b/odoo-bringout-akretion-product_print_zpl_barcode/doc/INSTALL.md @@ -0,0 +1,7 @@ +# Install + +```bash +pip install odoo-bringout-akretion-product_print_zpl_barcode" +# or +uv pip install odoo-bringout-akretion-product_print_zpl_barcode" +``` diff --git a/odoo-bringout-akretion-product_print_zpl_barcode/doc/MODELS.md b/odoo-bringout-akretion-product_print_zpl_barcode/doc/MODELS.md new file mode 100644 index 0000000..f0c599f --- /dev/null +++ b/odoo-bringout-akretion-product_print_zpl_barcode/doc/MODELS.md @@ -0,0 +1,14 @@ +# Models + +Detected core models and extensions in product_print_zpl_barcode. + +```mermaid +classDiagram + class product_product + class product_template + class stock_picking +``` + +Notes +- Classes show model technical names; fields omitted for brevity. +- Items listed under _inherit are extensions of existing models. diff --git a/odoo-bringout-akretion-product_print_zpl_barcode/doc/OVERVIEW.md b/odoo-bringout-akretion-product_print_zpl_barcode/doc/OVERVIEW.md new file mode 100644 index 0000000..97b3927 --- /dev/null +++ b/odoo-bringout-akretion-product_print_zpl_barcode/doc/OVERVIEW.md @@ -0,0 +1,6 @@ +# Overview + +Packaged Odoo addon: product_print_zpl_barcode. Provides features documented in upstream Odoo 16 under this addon. + +- Source: OCA/OCB 16.0, addon product_print_zpl_barcode +- License: LGPL-3 diff --git a/odoo-bringout-akretion-product_print_zpl_barcode/doc/REPORTS.md b/odoo-bringout-akretion-product_print_zpl_barcode/doc/REPORTS.md new file mode 100644 index 0000000..e0ea35f --- /dev/null +++ b/odoo-bringout-akretion-product_print_zpl_barcode/doc/REPORTS.md @@ -0,0 +1,3 @@ +# Reports + +This module does not define custom reports. diff --git a/odoo-bringout-akretion-product_print_zpl_barcode/doc/SECURITY.md b/odoo-bringout-akretion-product_print_zpl_barcode/doc/SECURITY.md new file mode 100644 index 0000000..54c8e0a --- /dev/null +++ b/odoo-bringout-akretion-product_print_zpl_barcode/doc/SECURITY.md @@ -0,0 +1,34 @@ +# Security + +Access control and security definitions in product_print_zpl_barcode. + +## Access Control Lists (ACLs) + +Model access permissions defined in: +- **[ir.model.access.csv](../product_print_zpl_barcode/security/ir.model.access.csv)** + - 2 model access rules + +## Record Rules + +Row-level security rules defined in: + +```mermaid +graph TB + subgraph "Security Layers" + A[Users] --> B[Groups] + B --> C[Access Control Lists] + C --> D[Models] + B --> E[Record Rules] + E --> F[Individual Records] + end +``` + +Security files overview: +- **[ir.model.access.csv](../product_print_zpl_barcode/security/ir.model.access.csv)** + - Model access permissions (CRUD rights) + +Notes +- Access Control Lists define which groups can access which models +- Record Rules provide row-level security (filter records by user/group) +- Security groups organize users and define permission sets +- All security is enforced at the ORM level by Odoo diff --git a/odoo-bringout-akretion-product_print_zpl_barcode/doc/TROUBLESHOOTING.md b/odoo-bringout-akretion-product_print_zpl_barcode/doc/TROUBLESHOOTING.md new file mode 100644 index 0000000..56853cb --- /dev/null +++ b/odoo-bringout-akretion-product_print_zpl_barcode/doc/TROUBLESHOOTING.md @@ -0,0 +1,5 @@ +# Troubleshooting + +- Ensure Python and Odoo environment matches repo guidance. +- Check database connectivity and logs if startup fails. +- Validate that dependent addons listed in DEPENDENCIES.md are installed. diff --git a/odoo-bringout-akretion-product_print_zpl_barcode/doc/USAGE.md b/odoo-bringout-akretion-product_print_zpl_barcode/doc/USAGE.md new file mode 100644 index 0000000..a801852 --- /dev/null +++ b/odoo-bringout-akretion-product_print_zpl_barcode/doc/USAGE.md @@ -0,0 +1,7 @@ +# Usage + +Start Odoo including this addon (from repo root): + +```bash +python3 scripts/nix_odoo_web_server.py --db-name mydb --addon product_print_zpl_barcode +``` diff --git a/odoo-bringout-akretion-product_print_zpl_barcode/doc/WIZARDS.md b/odoo-bringout-akretion-product_print_zpl_barcode/doc/WIZARDS.md new file mode 100644 index 0000000..aa37caa --- /dev/null +++ b/odoo-bringout-akretion-product_print_zpl_barcode/doc/WIZARDS.md @@ -0,0 +1,10 @@ +# Wizards + +Transient models exposed as UI wizards in product_print_zpl_barcode. + +```mermaid +classDiagram + class ProductPrintZplBarcode + class ProductPrintZplBarcodeLine + class ResConfigSettings +``` diff --git a/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/__init__.py b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/__init__.py new file mode 100644 index 0000000..9b42961 --- /dev/null +++ b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import wizard diff --git a/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/__manifest__.py b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/__manifest__.py new file mode 100644 index 0000000..54c4b11 --- /dev/null +++ b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/__manifest__.py @@ -0,0 +1,55 @@ +# Copyright 2016-2020 Akretion (http://www.akretion.com/) +# @author: Alexis de Lattre +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + 'name': 'Product Generate Price Weight Barcode', + 'version': '16.0.1.0.0', + 'category': 'Extra Tools', + 'license': 'AGPL-3', + 'summary': 'Add a wizard to print product barcode stickers on ZPL printer', + 'description': """ +Print product barcode stickers on ZPL printer +============================================= + +This module adds a wizard on product.product form view which allows to generate and print a product barcode sticker on a ZPL printer (such as Zebra GC420, GK420, ...). It can print: + +* regular product barcode stickers. These stickers will show: + * product name + * product price + * EAN13 or EAN8 barcode + +* price/weight barcode stickers. These stickers will show: + * product name + * weight (the wizard asks for this info) + * price + * price per kg + * EAN13 barcode + +It also allows to generate a private barcode for products without barcode. For that, you must configure the sequence "private.product.barcode". This sequence must be configured to produce 12 digits (for EAN13) or 7 digits (for EAN8) ; the checksum will be added automatically. + +This module has been written by Alexis de Lattre from Akretion +. + """, + 'author': 'Akretion', + 'website': 'https://github.com/akretion/odoo-usability', + # We depend on point_of_sale and not only 'product' + # because the price barcode rule is added by the point_of_sale module + # (the weight barcode rule is added by the stock module) + 'depends': [ + #'point_of_sale', + 'product', + 'barcodes', + 'stock' # stock.picking model + ], + 'external_dependencies': {'python': ['python-barcode>=0.14.0']}, + 'data': [ + 'security/ir.model.access.csv', + 'wizard/product_print_zpl_barcode_view.xml', + 'wizard/res_config_settings_view.xml', + 'views/product.xml', + 'views/stock_picking.xml', + 'data/barcode_sequence.xml', + ], + 'installable': True, +} diff --git a/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/data/barcode_sequence.xml b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/data/barcode_sequence.xml new file mode 100644 index 0000000..840c760 --- /dev/null +++ b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/data/barcode_sequence.xml @@ -0,0 +1,26 @@ + + + + + + + + Private Product Barcode + private.product.barcode + 298 + 9 + 1 + + + + + + diff --git a/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/i18n/bs.po b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/i18n/bs.po new file mode 100644 index 0000000..0e5599f --- /dev/null +++ b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/i18n/bs.po @@ -0,0 +1,392 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_print_zpl_barcode +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-07-15 13:39+0000\n" +"PO-Revision-Date: 2023-07-15 13:39+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__copies +msgid "# Labels" +msgstr "# Labele" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields.selection,name:product_print_zpl_barcode.selection__product_print_zpl_barcode__label_size__38x25 +msgid "38x25 mm" +msgstr "38x25 mm" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__barcode +msgid "Barcode" +msgstr "Barkod" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode__nomenclature_id +msgid "Barcode Nomenclature" +msgstr "Barkod nomenklatura" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__rule_id +msgid "Barcode Rule" +msgstr "Barkod pravilo" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__barcode_type +msgid "Barcode Type" +msgstr "Barkod tip" + +#. module: product_print_zpl_barcode +#: model_terms:ir.ui.view,arch_db:product_print_zpl_barcode.product_print_zpl_barcode_form +msgid "Cancel" +msgstr "Otkaži" + +#. module: product_print_zpl_barcode +#: model_terms:ir.ui.view,arch_db:product_print_zpl_barcode.product_print_zpl_barcode_form +msgid "Close" +msgstr "Zatvori" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode__company_id +msgid "Company" +msgstr "Preduzeće" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode__create_uid +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__create_uid +msgid "Created by" +msgstr "Kreirao" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode__create_date +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__create_date +msgid "Created on" +msgstr "Kreirano" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__currency_id +msgid "Currency" +msgstr "Valuta" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,help:product_print_zpl_barcode.field_product_print_zpl_barcode_line__uom_id +msgid "Default unit of measure used for all stock operations." +msgstr "Predefinirana mjerna jedinica za sve funkcije zalihe." + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode__display_name +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__display_name +msgid "Display Name" +msgstr "Prikazani naziv" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,help:product_print_zpl_barcode.field_product_product__must_print_barcode +#: model:ir.model.fields,help:product_print_zpl_barcode.field_product_template__must_print_barcode +msgid "" +"Enable that option for products for which you must print a barcode upon " +"reception in stock." +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.actions.act_window,name:product_print_zpl_barcode.product_print_zpl_barcode_action +#: model_terms:ir.ui.view,arch_db:product_print_zpl_barcode.product_normal_form_view +#: model_terms:ir.ui.view,arch_db:product_print_zpl_barcode.product_template_only_form_view +msgid "Generate Barcode" +msgstr "Generiraj barkodove" + +#. module: product_print_zpl_barcode +#: model_terms:ir.ui.view,arch_db:product_print_zpl_barcode.product_print_zpl_barcode_form +msgid "Generate Labels" +msgstr "Generate Labels" + +#. module: product_print_zpl_barcode +#: model:ir.model,name:product_print_zpl_barcode.model_product_print_zpl_barcode +msgid "Generate and print product barcodes in ZPL" +msgstr "Generate and Štampaj Proizvod barcodes in ZPL" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode__id +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__id +msgid "ID" +msgstr "ID" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode__label_size +msgid "Label Size" +msgstr "Label Size" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode____last_update +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line____last_update +msgid "Last Modified on" +msgstr "Zadnje mijenjano" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode__write_uid +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__write_uid +msgid "Last Updated by" +msgstr "Zadnji ažurirao" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode__write_date +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__write_date +msgid "Last Updated on" +msgstr "Zadnje ažurirano" + +#. module: product_print_zpl_barcode +#. odoo-python +#: code:addons/product_print_zpl_barcode/wizard/product_print_zpl_barcode.py:0 +#, python-format +msgid "" +"Line '%s': barcode '%s' has %d digits. This wizard only supports EAN8 and " +"EAN13 for the moment." +msgstr "" + +#. module: product_print_zpl_barcode +#. odoo-python +#: code:addons/product_print_zpl_barcode/wizard/product_print_zpl_barcode.py:0 +#, python-format +msgid "Line '%s': barcode type '%s' is not supported for the moment" +msgstr "Štampanje barkoda" + +#. module: product_print_zpl_barcode +#. odoo-python +#: code:addons/product_print_zpl_barcode/wizard/product_print_zpl_barcode.py:0 +#, python-format +msgid "" +"Line '%s': the barcode '%s' is not a valid EAN barcode (wrong checksum)." +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model,name:product_print_zpl_barcode.model_product_print_zpl_barcode_line +msgid "Line of the print ZPL barcode wizard" +msgstr "Line of the Štampaj ZPL barcode wizard" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode__line_ids +msgid "Lines" +msgstr "Linije" + +#. module: product_print_zpl_barcode +#. odoo-python +#: code:addons/product_print_zpl_barcode/wizard/product_print_zpl_barcode.py:0 +#, python-format +msgid "Missing Products" +msgstr "Missing Proizvodi" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_product__must_print_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_template__must_print_barcode +msgid "Must Print Barcode" +msgstr "Barkod se mora štampati" + +#. module: product_print_zpl_barcode +#. odoo-python +#: code:addons/product_print_zpl_barcode/wizard/product_print_zpl_barcode.py:0 +#, python-format +msgid "On line '%s', the number of copies must be strictly positive." +msgstr "On line '%s', the Broj of copies Mora be strictly positive." + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_product__barcode_image_png +msgid "PNG Barcode Image" +msgstr "PNG Barcode Image" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__parent_id +msgid "Parent" +msgstr "IP adresa ZPL štampača" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__price +msgid "Price" +msgstr "Cijena" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__price_uom +msgid "Price/UoM" +msgstr "Cijena/JMJ" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode__pricelist_id +msgid "Pricelist" +msgstr "Cjenovnik" + +#. module: product_print_zpl_barcode +#: model_terms:ir.ui.view,arch_db:product_print_zpl_barcode.product_print_zpl_barcode_form +msgid "Print" +msgstr "Štampaj" + +#. module: product_print_zpl_barcode +#: model_terms:ir.ui.view,arch_db:product_print_zpl_barcode.product_normal_form_view +#: model_terms:ir.ui.view,arch_db:product_print_zpl_barcode.product_template_only_form_view +msgid "Print Barcode" +msgstr "Štampa barkoda" + +#. module: product_print_zpl_barcode +#: model_terms:ir.ui.view,arch_db:product_print_zpl_barcode.product_product_tree_view +#: model_terms:ir.ui.view,arch_db:product_print_zpl_barcode.product_template_tree_view +#: model_terms:ir.ui.view,arch_db:product_print_zpl_barcode.view_picking_form +msgid "Print Barcodes" +msgstr "Štampa barkodova" + +#. module: product_print_zpl_barcode +#: model:ir.model,name:product_print_zpl_barcode.model_product_template +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__product_id +msgid "Product" +msgstr "Artikal" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__product_name +msgid "Product Label" +msgstr "Oznaka artikla" + +#. module: product_print_zpl_barcode +#: model:ir.model,name:product_print_zpl_barcode.model_product_product +msgid "Product Variant" +msgstr "Morate konfigurirati IP adresu ZPL štampača." + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__quantity +msgid "Qty" +msgstr "Količina" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_product__barcode_image_svg +msgid "SVG Barcode Image" +msgstr "SVG Barcode Image" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_stock_picking__show_print_zpl_barcode +msgid "Show Print Zpl Barcode" +msgstr "Prikaži Štampaj Zpl Barcode" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode__state +msgid "State" +msgstr "Status" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields.selection,name:product_print_zpl_barcode.selection__product_print_zpl_barcode__state__step1 +msgid "Step1" +msgstr "Step1" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields.selection,name:product_print_zpl_barcode.selection__product_print_zpl_barcode__state__step2 +msgid "Step2" +msgstr "Step2" + +#. module: product_print_zpl_barcode +#. odoo-python +#: code:addons/product_print_zpl_barcode/wizard/product_print_zpl_barcode.py:0 +#, python-format +msgid "" +"The barcode of the product (%s) has %d characters, which is smaller than the" +" %d characters of the prefix of the barcode pattern (%s)." +msgstr "" + +#. module: product_print_zpl_barcode +#. odoo-python +#: code:addons/product_print_zpl_barcode/wizard/product_print_zpl_barcode.py:0 +#, python-format +msgid "" +"The barcode rule '%s' has a pattern '%s' which doesn't contain a integer and" +" decimal part between '{}'." +msgstr "" + +#. module: product_print_zpl_barcode +#. odoo-python +#: code:addons/product_print_zpl_barcode/models/product.py:0 +#, python-format +msgid "The product '%s' already has a barcode." +msgstr "The Proizvod '%s' already has a barcode." + +#. module: product_print_zpl_barcode +#. odoo-python +#: code:addons/product_print_zpl_barcode/wizard/product_print_zpl_barcode.py:0 +#, python-format +msgid "The quantity (%s) must be positive !" +msgstr "The Količina (%s) Mora be positive !" + +#. module: product_print_zpl_barcode +#. odoo-python +#: code:addons/product_print_zpl_barcode/models/product.py:0 +#, python-format +msgid "" +"The sequence 'private.product.barcode' is not properly configured. The " +"generated sequence should have 7 digits (for EAN-8) or 12 digits (for " +"EAN-13). It currently has %d digits." +msgstr "" + +#. module: product_print_zpl_barcode +#. odoo-python +#: code:addons/product_print_zpl_barcode/wizard/product_print_zpl_barcode.py:0 +#, python-format +msgid "" +"The value to encode in the barcode (%s) is superior to the maximum value " +"allowed by the barcode pattern (%s)." +msgstr "" + +#. module: product_print_zpl_barcode +#. odoo-python +#: code:addons/product_print_zpl_barcode/wizard/product_print_zpl_barcode.py:0 +#, python-format +msgid "There are no pricelist in company '%s'." +msgstr "There are no pricelist in Kompanija '%s'." + +#. module: product_print_zpl_barcode +#: model:ir.model,name:product_print_zpl_barcode.model_stock_picking +msgid "Transfer" +msgstr "Prenos" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__uom_id +msgid "UoM" +msgstr "JMJ" + +#. module: product_print_zpl_barcode +#. odoo-python +#: code:addons/product_print_zpl_barcode/wizard/product_print_zpl_barcode.py:0 +#, python-format +msgid "Wrong active_model in context (%s)." +msgstr "Wrong active_model in context (%s)." + +#. module: product_print_zpl_barcode +#. odoo-python +#: code:addons/product_print_zpl_barcode/models/product.py:0 +#, python-format +msgid "" +"You cannot call the method generate_barcode_from_product_template on product" +" '%s' because it has %d variants and not just one." +msgstr "" + +#. module: product_print_zpl_barcode +#. odoo-python +#: code:addons/product_print_zpl_barcode/wizard/product_print_zpl_barcode.py:0 +#, python-format +msgid "You must select a ZPL Printer." +msgstr "You Mora select a ZPL Printer." + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode__zpl_file +msgid "ZPL File" +msgstr "ZPL File" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode__zpl_filename +msgid "ZPL Filename" +msgstr "ZPL Filename" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode__zpl_printer_id +msgid "ZPL Printer" +msgstr "ZPL Printer" diff --git a/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/i18n/product_print_zpl_barcode.pot b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/i18n/product_print_zpl_barcode.pot new file mode 100644 index 0000000..17c7698 --- /dev/null +++ b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/i18n/product_print_zpl_barcode.pot @@ -0,0 +1,392 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * product_print_zpl_barcode +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2023-07-15 13:39+0000\n" +"PO-Revision-Date: 2023-07-15 13:39+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__copies +msgid "# Labels" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields.selection,name:product_print_zpl_barcode.selection__product_print_zpl_barcode__label_size__38x25 +msgid "38x25 mm" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__barcode +msgid "Barcode" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode__nomenclature_id +msgid "Barcode Nomenclature" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__rule_id +msgid "Barcode Rule" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__barcode_type +msgid "Barcode Type" +msgstr "" + +#. module: product_print_zpl_barcode +#: model_terms:ir.ui.view,arch_db:product_print_zpl_barcode.product_print_zpl_barcode_form +msgid "Cancel" +msgstr "" + +#. module: product_print_zpl_barcode +#: model_terms:ir.ui.view,arch_db:product_print_zpl_barcode.product_print_zpl_barcode_form +msgid "Close" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode__company_id +msgid "Company" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode__create_uid +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__create_uid +msgid "Created by" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode__create_date +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__create_date +msgid "Created on" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__currency_id +msgid "Currency" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,help:product_print_zpl_barcode.field_product_print_zpl_barcode_line__uom_id +msgid "Default unit of measure used for all stock operations." +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode__display_name +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__display_name +msgid "Display Name" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,help:product_print_zpl_barcode.field_product_product__must_print_barcode +#: model:ir.model.fields,help:product_print_zpl_barcode.field_product_template__must_print_barcode +msgid "" +"Enable that option for products for which you must print a barcode upon " +"reception in stock." +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.actions.act_window,name:product_print_zpl_barcode.product_print_zpl_barcode_action +#: model_terms:ir.ui.view,arch_db:product_print_zpl_barcode.product_normal_form_view +#: model_terms:ir.ui.view,arch_db:product_print_zpl_barcode.product_template_only_form_view +msgid "Generate Barcode" +msgstr "" + +#. module: product_print_zpl_barcode +#: model_terms:ir.ui.view,arch_db:product_print_zpl_barcode.product_print_zpl_barcode_form +msgid "Generate Labels" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model,name:product_print_zpl_barcode.model_product_print_zpl_barcode +msgid "Generate and print product barcodes in ZPL" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode__id +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__id +msgid "ID" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode__label_size +msgid "Label Size" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode____last_update +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line____last_update +msgid "Last Modified on" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode__write_uid +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode__write_date +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__write_date +msgid "Last Updated on" +msgstr "" + +#. module: product_print_zpl_barcode +#. odoo-python +#: code:addons/product_print_zpl_barcode/wizard/product_print_zpl_barcode.py:0 +#, python-format +msgid "" +"Line '%s': barcode '%s' has %d digits. This wizard only supports EAN8 and " +"EAN13 for the moment." +msgstr "" + +#. module: product_print_zpl_barcode +#. odoo-python +#: code:addons/product_print_zpl_barcode/wizard/product_print_zpl_barcode.py:0 +#, python-format +msgid "Line '%s': barcode type '%s' is not supported for the moment" +msgstr "" + +#. module: product_print_zpl_barcode +#. odoo-python +#: code:addons/product_print_zpl_barcode/wizard/product_print_zpl_barcode.py:0 +#, python-format +msgid "" +"Line '%s': the barcode '%s' is not a valid EAN barcode (wrong checksum)." +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model,name:product_print_zpl_barcode.model_product_print_zpl_barcode_line +msgid "Line of the print ZPL barcode wizard" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode__line_ids +msgid "Lines" +msgstr "" + +#. module: product_print_zpl_barcode +#. odoo-python +#: code:addons/product_print_zpl_barcode/wizard/product_print_zpl_barcode.py:0 +#, python-format +msgid "Missing Products" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_product__must_print_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_template__must_print_barcode +msgid "Must Print Barcode" +msgstr "" + +#. module: product_print_zpl_barcode +#. odoo-python +#: code:addons/product_print_zpl_barcode/wizard/product_print_zpl_barcode.py:0 +#, python-format +msgid "On line '%s', the number of copies must be strictly positive." +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_product__barcode_image_png +msgid "PNG Barcode Image" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__parent_id +msgid "Parent" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__price +msgid "Price" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__price_uom +msgid "Price/UoM" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode__pricelist_id +msgid "Pricelist" +msgstr "" + +#. module: product_print_zpl_barcode +#: model_terms:ir.ui.view,arch_db:product_print_zpl_barcode.product_print_zpl_barcode_form +msgid "Print" +msgstr "" + +#. module: product_print_zpl_barcode +#: model_terms:ir.ui.view,arch_db:product_print_zpl_barcode.product_normal_form_view +#: model_terms:ir.ui.view,arch_db:product_print_zpl_barcode.product_template_only_form_view +msgid "Print Barcode" +msgstr "" + +#. module: product_print_zpl_barcode +#: model_terms:ir.ui.view,arch_db:product_print_zpl_barcode.product_product_tree_view +#: model_terms:ir.ui.view,arch_db:product_print_zpl_barcode.product_template_tree_view +#: model_terms:ir.ui.view,arch_db:product_print_zpl_barcode.view_picking_form +msgid "Print Barcodes" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model,name:product_print_zpl_barcode.model_product_template +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__product_id +msgid "Product" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__product_name +msgid "Product Label" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model,name:product_print_zpl_barcode.model_product_product +msgid "Product Variant" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__quantity +msgid "Qty" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_product__barcode_image_svg +msgid "SVG Barcode Image" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_stock_picking__show_print_zpl_barcode +msgid "Show Print Zpl Barcode" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode__state +msgid "State" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields.selection,name:product_print_zpl_barcode.selection__product_print_zpl_barcode__state__step1 +msgid "Step1" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields.selection,name:product_print_zpl_barcode.selection__product_print_zpl_barcode__state__step2 +msgid "Step2" +msgstr "" + +#. module: product_print_zpl_barcode +#. odoo-python +#: code:addons/product_print_zpl_barcode/wizard/product_print_zpl_barcode.py:0 +#, python-format +msgid "" +"The barcode of the product (%s) has %d characters, which is smaller than the" +" %d characters of the prefix of the barcode pattern (%s)." +msgstr "" + +#. module: product_print_zpl_barcode +#. odoo-python +#: code:addons/product_print_zpl_barcode/wizard/product_print_zpl_barcode.py:0 +#, python-format +msgid "" +"The barcode rule '%s' has a pattern '%s' which doesn't contain a integer and" +" decimal part between '{}'." +msgstr "" + +#. module: product_print_zpl_barcode +#. odoo-python +#: code:addons/product_print_zpl_barcode/models/product.py:0 +#, python-format +msgid "The product '%s' already has a barcode." +msgstr "" + +#. module: product_print_zpl_barcode +#. odoo-python +#: code:addons/product_print_zpl_barcode/wizard/product_print_zpl_barcode.py:0 +#, python-format +msgid "The quantity (%s) must be positive !" +msgstr "" + +#. module: product_print_zpl_barcode +#. odoo-python +#: code:addons/product_print_zpl_barcode/models/product.py:0 +#, python-format +msgid "" +"The sequence 'private.product.barcode' is not properly configured. The " +"generated sequence should have 7 digits (for EAN-8) or 12 digits (for " +"EAN-13). It currently has %d digits." +msgstr "" + +#. module: product_print_zpl_barcode +#. odoo-python +#: code:addons/product_print_zpl_barcode/wizard/product_print_zpl_barcode.py:0 +#, python-format +msgid "" +"The value to encode in the barcode (%s) is superior to the maximum value " +"allowed by the barcode pattern (%s)." +msgstr "" + +#. module: product_print_zpl_barcode +#. odoo-python +#: code:addons/product_print_zpl_barcode/wizard/product_print_zpl_barcode.py:0 +#, python-format +msgid "There are no pricelist in company '%s'." +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model,name:product_print_zpl_barcode.model_stock_picking +msgid "Transfer" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode_line__uom_id +msgid "UoM" +msgstr "" + +#. module: product_print_zpl_barcode +#. odoo-python +#: code:addons/product_print_zpl_barcode/wizard/product_print_zpl_barcode.py:0 +#, python-format +msgid "Wrong active_model in context (%s)." +msgstr "" + +#. module: product_print_zpl_barcode +#. odoo-python +#: code:addons/product_print_zpl_barcode/models/product.py:0 +#, python-format +msgid "" +"You cannot call the method generate_barcode_from_product_template on product" +" '%s' because it has %d variants and not just one." +msgstr "" + +#. module: product_print_zpl_barcode +#. odoo-python +#: code:addons/product_print_zpl_barcode/wizard/product_print_zpl_barcode.py:0 +#, python-format +msgid "You must select a ZPL Printer." +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode__zpl_file +msgid "ZPL File" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode__zpl_filename +msgid "ZPL Filename" +msgstr "" + +#. module: product_print_zpl_barcode +#: model:ir.model.fields,field_description:product_print_zpl_barcode.field_product_print_zpl_barcode__zpl_printer_id +msgid "ZPL Printer" +msgstr "" diff --git a/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/models/__init__.py b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/models/__init__.py new file mode 100644 index 0000000..f2abf71 --- /dev/null +++ b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/models/__init__.py @@ -0,0 +1,2 @@ +from . import product +from . import stock_picking diff --git a/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/models/product.py b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/models/product.py new file mode 100644 index 0000000..dd9ce9c --- /dev/null +++ b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/models/product.py @@ -0,0 +1,98 @@ +# Copyright 2020-2023 Akretion France (http://www.akretion.com/) +# @author: Alexis de Lattre +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models, _ +from odoo.exceptions import UserError +from stdnum.ean import calc_check_digit, is_valid +from barcode import EAN13, EAN8 +from barcode.writer import ImageWriter, SVGWriter +import base64 +import io + + +class ProductTemplate(models.Model): + _inherit = "product.template" + + must_print_barcode = fields.Boolean( + string="Must Print Barcode", + help="Enable that option for products for which you must " + "print a barcode upon reception in stock.") + + def generate_barcode_from_product_template(self): + self.ensure_one() + if self.product_variant_count != 1: + raise UserError(_( + "You cannot call the method " + "generate_barcode_from_product_template on product '%s' " + "because it has %d variants and not just one.") + % (self.display_name, self.product_variant_count)) + return self.product_variant_ids[0].generate_barcode_from_product_product() + + +class ProductProduct(models.Model): + _inherit = 'product.product' + + # Not useful for ZPL, but it is often useful to have a barcode image field + barcode_image_png = fields.Binary( + compute='_compute_barcode_image_png', + string='PNG Barcode Image') + barcode_image_svg = fields.Binary( + compute='_compute_barcode_image_svg', + string='SVG Barcode Image') + + def _get_barcode_image(self, img_format): + self.ensure_one() + barcode = self.barcode + if not barcode: + return False + res = False + if isinstance(barcode, str) and len(barcode) in (8, 13) and is_valid(barcode): + barcode_obj = False + if img_format == 'svg': + writer = SVGWriter() + elif img_format == 'png': + writer = ImageWriter() + else: + return False + if len(barcode) == 13: + barcode_obj = EAN13(barcode, writer=writer, guardbar=True) + elif len(barcode) == 8: + barcode_obj = EAN8(barcode, writer=writer, guardbar=True) + if barcode_obj: + barcode_file = io.BytesIO() + barcode_obj.write(barcode_file) + barcode_file.seek(0) + barcode_img = barcode_file.read() + res = base64.b64encode(barcode_img) + return res + + @api.depends('barcode') + def _compute_barcode_image_svg(self): + for product in self: + product.barcode_image_svg = product._get_barcode_image('svg') + + @api.depends('barcode') + def _compute_barcode_image_png(self): + for product in self: + product.barcode_image_png = product._get_barcode_image('png') + + def generate_barcode_from_product_product(self): + self.ensure_one() + if self.barcode: + raise UserError(_( + "The product '%s' already has a barcode.") % self.display_name) + barcode_without_checksum = self.env['ir.sequence'].next_by_code( + 'private.product.barcode') + if len(barcode_without_checksum) not in (7, 12): + raise UserError(_( + "The sequence 'private.product.barcode' is not properly " + "configured. The generated sequence should have 7 digits " + "(for EAN-8) or 12 digits (for EAN-13). " + "It currently has %d digits." % len(barcode_without_checksum))) + checksum = calc_check_digit(barcode_without_checksum) + barcode = barcode_without_checksum + str(checksum) + self.write({ + 'barcode': barcode, + 'must_print_barcode': True, + }) diff --git a/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/models/stock_picking.py b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/models/stock_picking.py new file mode 100644 index 0000000..55e31a0 --- /dev/null +++ b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/models/stock_picking.py @@ -0,0 +1,25 @@ +# Copyright 2023 Akretion France (http://www.akretion.com/) +# @author: Alexis de Lattre +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models +from odoo.tools import float_compare + + +class StockPicking(models.Model): + _inherit = "stock.picking" + + show_print_zpl_barcode = fields.Boolean(compute='_compute_show_print_zpl_barcode') + + @api.depends('state') + def _compute_show_print_zpl_barcode(self): + prec = self.env['decimal.precision'].precision_get('Product Unit of Measure') + for picking in self: + show = False + if picking.state == 'done' and picking.picking_type_code != 'outgoing': + for line in picking.move_line_ids: + if ( + line.product_id.must_print_barcode and + float_compare(line.qty_done, 0, precision_digits=prec) > 0): + show = True + picking.show_print_zpl_barcode = show diff --git a/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/security/ir.model.access.csv b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/security/ir.model.access.csv new file mode 100644 index 0000000..e3fd58e --- /dev/null +++ b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_product_print_zpl_barcode,Full access to product.print.zpl.barcode wizard,model_product_print_zpl_barcode,base.group_user,1,1,1,1 +access_product_print_zpl_barcode_line,Full access to product.print.zpl.barcode.line wizard,model_product_print_zpl_barcode_line,base.group_user,1,1,1,1 diff --git a/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/views/product.xml b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/views/product.xml new file mode 100644 index 0000000..6829fe9 --- /dev/null +++ b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/views/product.xml @@ -0,0 +1,67 @@ + + + + + + + product.template + + +
+
+ +
+
+
+
+ + + + product.template + + + + + + + + product.template + + + + + + + + + product.product + + + + + + + + product.product + + + + + + +
diff --git a/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/views/stock_picking.xml b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/views/stock_picking.xml new file mode 100644 index 0000000..0815f19 --- /dev/null +++ b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/views/stock_picking.xml @@ -0,0 +1,21 @@ + + + + + + + stock.picking + + + + + + + diff --git a/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/wizard/__init__.py b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/wizard/__init__.py new file mode 100644 index 0000000..3d74426 --- /dev/null +++ b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/wizard/__init__.py @@ -0,0 +1,2 @@ +from . import product_print_zpl_barcode +from . import res_config_settings diff --git a/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/wizard/product_print_zpl_barcode.py b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/wizard/product_print_zpl_barcode.py new file mode 100644 index 0000000..6c99a46 --- /dev/null +++ b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/wizard/product_print_zpl_barcode.py @@ -0,0 +1,376 @@ +# Copyright 2016-2023 Akretion France (http://www.akretion.com/) +# @author: Alexis de Lattre +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models, _ +from odoo.exceptions import UserError +from odoo.tools import float_compare, float_is_zero +from stdnum.ean import is_valid, calc_check_digit +import base64 +import re +import socket +import ipaddress + +import logging +logger = logging.getLogger(__name__) + + +class ProductPrintZplBarcode(models.TransientModel): + _name = 'product.print.zpl.barcode' + _description = 'Generate and print product barcodes in ZPL' + _check_company_auto = True + + @api.model + def default_get(self, fields_list): + res = super().default_get(fields_list) + nomenclature = self.env.ref('barcodes.default_barcode_nomenclature') + company = self.env.company + #posconfig = self.env['pos.config'].sudo().search( + # [('company_id', '=', company.id)], limit=1) + #if posconfig: + # pricelist = posconfig.pricelist_id + #else: + pricelist = self.env['product.pricelist'].search([ + '|', ('company_id', '=', False), + ('company_id', '=', company.id), + ], limit=1) + if not pricelist: + raise UserError(_( + "There are no pricelist in company '%s'.") % company.name) + + printer_ip = self.env['ir.config_parameter'].sudo().get_param( + 'product_print_zpl_barcode.printer_ip') + + line_ids = [] + if self._context.get('active_model') == 'product.product': + product_ids = self._context.get('active_ids') + products = self.env['product.product'].browse(product_ids) + if not products: + raise UserError(_('Missing Products')) + for product in products: + self._update_line_ids(line_ids, product) + elif self._context.get('active_model') == 'product.template': + product_tmpl_ids = self._context.get('active_ids') + product_tmpls = self.env['product.template'].browse(product_tmpl_ids) + for product_tmpl in product_tmpls: + for product in product_tmpl.product_variant_ids: + self._update_line_ids(line_ids, product) + elif self._context.get('active_model') == 'stock.picking': + prec = self.env['decimal.precision'].precision_get( + 'Product Unit of Measure') + picking = self.env['stock.picking'].browse(self._context['active_id']) + for ml in picking.move_line_ids: + if ( + ml.product_id and + ml.product_id.must_print_barcode and + float_compare(ml.qty_done, 0, precision_digits=prec) > 0): + self._update_line_ids( + line_ids, ml.product_id, int(round(ml.qty_done))) + else: + raise UserError(_( + "Wrong active_model in context (%s).") + % self._context.get('active_model')) + res.update({ + 'company_id': company.id, + 'nomenclature_id': nomenclature.id, + 'pricelist_id': pricelist.id, + 'zpl_printer_ip': printer_ip, + 'line_ids': line_ids, + }) + return res + + @api.model + def _update_line_ids(self, line_ids, product, copies=1): + if product.barcode: + line_ids.append((0, 0, { + 'barcode': product.barcode, + 'product_name': product.display_name, + 'product_id': product.id, + 'copies': copies, + })) + else: + logger.warning("Product '%s' doesn't have a barcode", product.display_name) + + company_id = fields.Many2one( # default value set by default_get + 'res.company', required=True, ondelete='cascade') + nomenclature_id = fields.Many2one( + 'barcode.nomenclature', 'Barcode Nomenclature', required=True, + states={'step2': [('readonly', True)]}) + # label_size: remove readonly=True when we will support more labels + label_size = fields.Selection([ + ('38x25', '38x25 mm'), + ], required=True, default='38x25', readonly=True) + pricelist_id = fields.Many2one( + 'product.pricelist', string='Pricelist', required=True, + states={'step2': [('readonly', True)]}, check_company=True, + domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]" + ) + state = fields.Selection([ + ('step1', 'Step1'), + ('step2', 'Step2'), + ], default='step1', readonly=True) + zpl_file = fields.Binary(string='ZPL File', readonly=True) + zpl_filename = fields.Char('ZPL Filename') + zpl_printer_ip = fields.Char(string='ZPL Printer IP Address') + line_ids = fields.One2many( + 'product.print.zpl.barcode.line', 'parent_id', + string='Lines', states={'step2': [('readonly', True)]}) + + def generate(self): + """Called by button for the wizard, 1st step""" + self.ensure_one() + zpl_strings = [] + print_price = False + for line in self.line_ids: + barcode = line.barcode + product_name = line.product_name + + assert barcode + barcode_len = len(barcode) + if barcode_len not in (8, 13): + raise UserError(_( + "Line '%s': barcode '%s' has %d digits. " + "This wizard only supports EAN8 and EAN13 for the moment.") + % (product_name, barcode, barcode_len)) + if not is_valid(barcode): + raise UserError(_( + "Line '%s': the barcode '%s' is not a valid EAN barcode " + "(wrong checksum).") % (product_name, barcode)) + if line.copies <= 0: + raise UserError(_( + "On line '%s', the number of copies must be strictly positive." + ) % product_name) + if line.barcode_type in ('price', 'weight'): + barcode, zpl_str = line._prepare_price_weight_barcode_type() + elif line.barcode_type == 'product': + barcode, zpl_str = line._prepare_product_barcode_type(print_price) + else: + raise UserError(_( + "Line '%s': barcode type '%s' is not supported for the moment") + % (product_name, line.barcode_type)) + line.write({'barcode': barcode}) + zpl_strings.append(zpl_str) + + zpl_filename = "barcodes.zpl" + if len(self.line_ids) == 1: + zpl_filename = "barcode_%s.zpl" % self.line_ids[0].barcode + + zpl_str = '\n'.join(zpl_strings) + zpl_bytes = zpl_str.encode('utf-8') + vals = { + 'zpl_file': base64.encodebytes(zpl_bytes), + 'state': 'step2', + 'zpl_filename': zpl_filename, + } + self.write(vals) + action = self.env["ir.actions.actions"]._for_xml_id( + 'product_print_zpl_barcode.product_print_zpl_barcode_action') + action.update({ + 'res_id': self.id, + 'context': self._context, + 'views': False}) + return action + + def print_zpl(self): + if not self.zpl_printer_ip: + raise UserError(_( + "You must configure the IP address of the ZPL Printer.")) + try: + ip = ipaddress.ip_address(self.zpl_printer_ip) + except Exception as e: + raise UserError(str(e)) + version = ip.version + # TODO works with DNS ? + if version == 6: # IPv6 + socket_inet = socket.AF_INET6 + else: # IPv4 + socket_inet = socket.AF_INET + with socket.socket(socket_inet, socket.SOCK_STREAM) as s: + try: + s.connect((str(ip), 9100)) + except Exception as e: + raise UserError(str(e)) + zpl_file_bytes = base64.decodebytes(self.zpl_file) + s.send(zpl_file_bytes) + s.close() + + +class ProductPrintZplBarcodeLine(models.TransientModel): + _name = 'product.print.zpl.barcode.line' + _description = 'Line of the print ZPL barcode wizard' + + parent_id = fields.Many2one( + 'product.print.zpl.barcode', ondelete='cascade') + product_id = fields.Many2one( + 'product.product', string='Product', readonly=True) + uom_id = fields.Many2one(related='product_id.uom_id', string='UoM') + # 1 line = a bit less than 30 + # I don't make product_name a stored computed field because I'm afraid + # that we may not take the lang of the user + product_name = fields.Char('Product Label', required=True) #, size=56) + rule_id = fields.Many2one( + 'barcode.rule', string='Barcode Rule', compute='_compute_rule_id') + barcode_type = fields.Selection(related='rule_id.type', string="Barcode Type") + currency_id = fields.Many2one(related='parent_id.pricelist_id.currency_id') + # TODO: for the moment, we only support weight, but... + quantity = fields.Float(digits='Stock Weight', string='Qty') + price_uom = fields.Monetary( + string="Price/UoM", compute='_compute_price') # given by pricelist + price = fields.Monetary(compute='_compute_price') + barcode = fields.Char(readonly=True) + copies = fields.Integer(string='# Labels', default=1, required=True) + + @api.depends('parent_id.pricelist_id', 'quantity', 'product_id') + def _compute_price(self): + # for regular barcodes + for line in self: + pricelist = line.parent_id.pricelist_id + price_uom = price = 0.0 + if pricelist and line.product_id: + price_uom = pricelist._get_product_price(line.product_id, 1, False) + price = price_uom * line.quantity + line.price_uom = price_uom + line.price = price + + @api.depends('parent_id.nomenclature_id') + def _compute_rule_id(self): + for line in self: + nomenclature = line.parent_id.nomenclature_id + match_rule = False + if nomenclature and line.barcode: + for rule in nomenclature.rule_ids: + match = nomenclature.match_pattern( + line.barcode, rule.pattern) + if match.get('match'): + match_rule = rule.id + break + line.rule_id = match_rule + + def _prepare_price_weight_barcode_type(self): + dpo = self.env['decimal.precision'] + prec = dpo.precision_get('Stock Weight') + value = self.quantity + pbarcode = self.barcode + if float_is_zero(value, precision_digits=prec): + raise UserError(_( + "The quantity (%s) must be positive !") % value) + # check prefix + pattern = self.rule_id.pattern + if '{' not in pattern: + raise UserError(_( + "The barcode rule '%s' has a pattern '%s' which doesn't " + "contain a integer and decimal part between '{}'.") + % (self.rule_id.name, pattern)) + prefix = pattern.split('{')[0] + assert len(prefix) >= 1 + if len(prefix) > len(pbarcode): + raise UserError(_( + "The barcode of the product (%s) has %d characters, " + "which is smaller than the %d characters of the prefix " + "of the barcode pattern (%s).") + % (pbarcode, len(pbarcode), len(prefix), prefix)) + barcode = pbarcode[0:len(prefix)] + # print("barcode=", barcode) + # print("pattern=", pattern) + m = re.search(r'\{N+D+\}', pattern) + # print("m=", m) + assert m + pattern_val = m.group(0) + pattern_val = pattern_val[1:-1] + # print("pattern_val=", pattern_val) + max_value = 10**pattern_val.count('N') + if float_compare(value, max_value, precision_digits=prec) != -1: + raise UserError(_( + "The value to encode in the barcode (%s) is superior " + "to the maximum value allowed by the barcode pattern (%s).") + % (value, max_value)) + value_str = str(value) + value_str_split = value_str.split('.') + assert len(value_str_split) == 2 + value_n = value_str_split[0] + value_d = value_str_split[1] + assert len(value_n) <= pattern_val.count('N') + barcode += value_n.zfill(pattern_val.count('N')) + # end fill doesn't exists... so: + # 1) make sure we have enough 0 after + value_d_ext = value_d + '0' * pattern_val.count('D') + # 2) cut at the right size + barcode += value_d_ext[0:pattern_val.count('D')] + # print("barcode=", barcode) + # Add checksum + if self.rule_id.encoding == 'ean13': + # I don't call bno.sanitize_ean() due to this bug: + # https://github.com/odoo/odoo/pull/114112 + barcode = barcode + calc_check_digit(barcode) + assert len(barcode) == 13 + assert is_valid(barcode) + # print("barcode FINAL=", barcode) + zpl_str = self._price_weight_barcode_type_zpl() % { + 'product_name': self.product_name, + 'ean_zpl_command': len(self.barcode) == 8 and 'B8' or 'BE', + 'ean_no_checksum': barcode[:-1], + 'price_uom': self.price_uom, + 'price': self.price, + 'currency_symbol': self.currency_id.symbol, + 'copies': self.copies, + 'quantity': value, + 'uom_name': self.uom_id.name, + } + return (barcode, zpl_str) + + @api.model + def _price_weight_barcode_type_zpl(self): + label = """ +^XA +^CI28 +^PW304 +^LL200 +^LH0,20 +^CF0,30 +^FO15,0^FB270,1,0,C^FD%(price).2f %(currency_symbol)s^FS +^CF0,20 +^FO15,30^FB290,4,0,C^FD%(product_name)s^FS +^CF0,25 +^FO15,75^FB270,1,0,C^FD%(quantity).3f %(uom_name)s %(price_uom).2f %(currency_symbol)s/%(uom_name)s^FS +^FO60,110^%(ean_zpl_command)sN,50^FD%(ean_no_checksum)s^FS +^PQ%(copies)s +^XZ +""" + return label + + @api.model + def _product_barcode_type_zpl(self, print_price): + label_start = """ +^XA +^CI28 +^PW304 +^LL200 +^LH0,20 +^CF0,30 +""" + if print_price: + label_price = """ +^FO15,0^FB270,1,0,C^FD%(price_uom).2f %(currency_symbol)s^FS +""" + else: + label_price = "" + + label_end = """ +^CF0,20 +^FO15,30^FB290,4,0,C^FD%(product_name)s^FS +^FO60,110^%(ean_zpl_command)sN,60^FD%(ean_no_checksum)s^FS +^PQ%(copies)s +^XZ +""" + return label_start + label_price + label_end + + def _prepare_product_barcode_type(self, print_price): + zpl_str = self._product_barcode_type_zpl(print_price) % { + 'product_name': self.product_name, + 'ean_zpl_command': len(self.barcode) == 8 and 'B8' or 'BE', + 'ean_no_checksum': self.barcode[:-1], + 'price_uom': self.price_uom, + 'currency_symbol': self.currency_id.symbol, # symbol is a required field + 'copies': self.copies, + } + return (self.barcode, zpl_str) diff --git a/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/wizard/product_print_zpl_barcode_view.xml b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/wizard/product_print_zpl_barcode_view.xml new file mode 100644 index 0000000..d6d860c --- /dev/null +++ b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/wizard/product_print_zpl_barcode_view.xml @@ -0,0 +1,62 @@ + + + + + + + product_print_zpl_barcode.form + product.print.zpl.barcode + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ + + Generate Barcode + product.print.zpl.barcode + form + new + + +
diff --git a/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/wizard/res_config_settings.py b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/wizard/res_config_settings.py new file mode 100644 index 0000000..7a860c8 --- /dev/null +++ b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/wizard/res_config_settings.py @@ -0,0 +1,24 @@ +# Copyright 2023 Akretion France (http://www.akretion.com/) +# @author: Alexis de Lattre +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models +from odoo.exceptions import ValidationError +import ipaddress + + +class ResConfigSettings(models.TransientModel): + _inherit = "res.config.settings" + + zpl_printer_ip = fields.Char( + config_parameter="product_print_zpl_barcode.printer_ip", + string="ZPL Printer IP Address") + + @api.constrains('zpl_printer_ip') + def _check_zpl_printer_ip(self): + for wiz in self: + if wiz.zpl_printer_ip: + try: + ipaddress.ip_address(wiz.zpl_printer_ip) + except Exception as e: + raise ValidationError(str(e)) diff --git a/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/wizard/res_config_settings_view.xml b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/wizard/res_config_settings_view.xml new file mode 100644 index 0000000..584cb5c --- /dev/null +++ b/odoo-bringout-akretion-product_print_zpl_barcode/product_print_zpl_barcode/wizard/res_config_settings_view.xml @@ -0,0 +1,30 @@ + + + + + + + res.config.settings + + + +

Barcode printing

+
+
+
+
+
+
+
+
+
+
+
+ +
diff --git a/odoo-bringout-akretion-product_print_zpl_barcode/pyproject.toml b/odoo-bringout-akretion-product_print_zpl_barcode/pyproject.toml new file mode 100644 index 0000000..9327a61 --- /dev/null +++ b/odoo-bringout-akretion-product_print_zpl_barcode/pyproject.toml @@ -0,0 +1,44 @@ +[project] +name = "odoo-bringout-akretion-product_print_zpl_barcode" +version = "16.0.0" +description = "Product Generate Price Weight Barcode - Add a wizard to print product barcode stickers on ZPL printer" +authors = [ + { name = "Ernad Husremovic", email = "hernad@bring.out.ba" } +] +dependencies = [ + "odoo-bringout-oca-ocb-product>=16.0.0", + "odoo-bringout-akretion-barcodes>=16.0.0", + "odoo-bringout-oca-ocb-stock>=16.0.0", + "requests>=2.25.1" +] +readme = "README.md" +requires-python = ">= 3.11" +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Topic :: Office/Business", +] + +[project.urls] +homepage = "https://github.com/bringout/0" +repository = "https://github.com/bringout/0" + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[tool.hatch.metadata] +allow-direct-references = true + +[tool.hatch.build.targets.wheel] +packages = ["product_print_zpl_barcode"] + +[tool.rye] +managed = true +dev-dependencies = [ + "pytest>=8.4.1", +]