Penambahan QC dan OEE, serta instalasi Product Label
@@ -0,0 +1,165 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
@@ -0,0 +1,55 @@
|
||||
=====================
|
||||
Custom Product Labels
|
||||
=====================
|
||||
|
||||
.. |badge1| image:: https://img.shields.io/badge/maturity-Production-green.png
|
||||
:alt: Production
|
||||
.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-purple.png
|
||||
:target: https://www.gnu.org/licenses/lgpl-3.0.html
|
||||
:alt: License: LGPL-3
|
||||
.. |badge3| image:: https://img.shields.io/badge/demo-Try%20me-FEA621.png
|
||||
:target: https://garazd.biz/r/r2G
|
||||
:alt: Try me on a Demo Instance
|
||||
.. |badge4| image:: https://img.shields.io/badge/link-Garazd%20Apps-154577.png
|
||||
:target: https://garazd.biz/shop/custom-product-labels-2
|
||||
:alt: Get the app on Garazd Apps store
|
||||
|
||||
|
||||
|badge1| |badge2| |badge3| |badge4|
|
||||
|
||||
|
||||
Print custom product labels with barcode | Barcode Product Label
|
||||
|
||||
|
||||
**Table of contents**
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
Authors
|
||||
~~~~~~~
|
||||
|
||||
* Garazd Creation
|
||||
|
||||
Maintainers
|
||||
~~~~~~~~~~~
|
||||
|
||||
This module is maintained by the Garazd Creation.
|
||||
|
||||
.. image:: https://garazd.biz/logo.png
|
||||
:alt: Garazd Creation
|
||||
:target: https://garazd.biz
|
||||
|
||||
Our mission is to create convenient and effective business solutions
|
||||
based on the Odoo ERP system in the areas in which we have the maximum
|
||||
expertise, such as: eCommerce, marketing, SEO, integration with
|
||||
marketplaces and analytic systems, product label printing and designing.
|
||||
|
||||
To solve these tasks, we create modules that complement each other,
|
||||
extend the functionality of Odoo and improve the usability of the system.
|
||||
Our solutions come with detailed documentation and additional materials
|
||||
for easy use.
|
||||
@@ -0,0 +1 @@
|
||||
from . import wizard
|
||||
@@ -0,0 +1,32 @@
|
||||
# Copyright © 2018 Garazd Creation (https://garazd.biz)
|
||||
# @author: Yurii Razumovskyi (support@garazd.biz)
|
||||
# @author: Iryna Razumovska (support@garazd.biz)
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.html).
|
||||
|
||||
{
|
||||
'name': 'Custom Product Labels',
|
||||
'version': '14.0.2.3.2',
|
||||
'category': 'Extra Tools',
|
||||
'author': 'Garazd Creation',
|
||||
'website': 'https://garazd.biz/en/shop/category/odoo-product-labels-15',
|
||||
'license': 'LGPL-3',
|
||||
'summary': 'Print custom product labels with barcode | Barcode Product Label',
|
||||
'images': ['static/description/banner.png', 'static/description/icon.png'],
|
||||
'depends': [
|
||||
'product',
|
||||
],
|
||||
'data': [
|
||||
'security/ir.model.access.csv',
|
||||
'report/product_label_reports.xml',
|
||||
'report/product_label_templates.xml',
|
||||
'wizard/print_product_label_views.xml',
|
||||
'views/res_config_settings_views.xml',
|
||||
],
|
||||
'demo': [
|
||||
'demo/product_demo.xml',
|
||||
],
|
||||
'support': 'support@garazd.biz',
|
||||
'application': True,
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo noupdate="1">
|
||||
|
||||
<record id="product.product_product_12" model="product.product">
|
||||
<field name="barcode">0500010543219</field>
|
||||
</record>
|
||||
<record id="product.product_product_27" model="product.product">
|
||||
<field name="name">Drawer with three panels and one lockable, on wheels, mobile and respectable</field>
|
||||
<field name="barcode">1234567890128</field>
|
||||
</record>
|
||||
<!-- Product variant with EAN-8-->
|
||||
<record id="product.product_product_10" model="product.product">
|
||||
<field name="name">Cabinet with Doors: minimalistic wooden with brown top, divided by two sides, with drawer</field>
|
||||
<field name="barcode">12345670</field>
|
||||
</record>
|
||||
<!-- Product variant with EAN-13-->
|
||||
<record id="product.product_product_13" model="product.product">
|
||||
<field name="name">Corner Desk Black with metal base and wooden table-top, ergonomic and comfortable</field>
|
||||
<field name="barcode">4444000022222</field>
|
||||
</record>
|
||||
<!-- Product variant with Code 128: Customizable Desk (Legs: Aluminium, Color: White) -->
|
||||
<record id="product.product_product_4c" model="product.product">
|
||||
<field name="name">Customizable Desk: adjustment by height, maximum free space</field>
|
||||
<field name="barcode">10203040506070809</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -0,0 +1,85 @@
|
||||
.. _changelog:
|
||||
|
||||
Changelog
|
||||
=========
|
||||
|
||||
`14.0.2.3.2`
|
||||
------------
|
||||
|
||||
- Add method to get PDF.
|
||||
|
||||
`14.0.2.3.1`
|
||||
------------
|
||||
|
||||
- Add UA translations.
|
||||
|
||||
`14.0.2.3.0`
|
||||
------------
|
||||
|
||||
- Improve getting of labels to print, add excluding of lines with qty=0.
|
||||
|
||||
- Add the "mode" option for technical purposes.
|
||||
|
||||
`14.0.2.2.0`
|
||||
------------
|
||||
|
||||
- Implement sorting of label lines by a product.
|
||||
|
||||
- Add the sequence for the label lines.
|
||||
|
||||
`14.0.2.1.0`
|
||||
------------
|
||||
|
||||
- Add the settings section "Product Labels".
|
||||
|
||||
`14.0.2.0.0`
|
||||
------------
|
||||
|
||||
- Add a product label template 50x38 mm.
|
||||
|
||||
- Improve product demo data.
|
||||
|
||||
- Implement a new logic for print wizard.
|
||||
|
||||
- Add a company selection to the wizard.
|
||||
|
||||
`14.0.1.2.0`
|
||||
------------
|
||||
|
||||
- Add the option "Language" to translate product names.
|
||||
|
||||
`14.0.1.1.1`
|
||||
------------
|
||||
|
||||
- Add method "_get_label_to_print" to define actual product lines.
|
||||
|
||||
`14.0.1.1.0`
|
||||
------------
|
||||
|
||||
- Add the option "Border" to define a border width on multi labels on A4, US letter paper formats.
|
||||
|
||||
`14.0.1.0.3`
|
||||
------------
|
||||
|
||||
- Add barcode types in the 57x35 label template
|
||||
|
||||
- Add currency symbol position before/after in the 57x35 label template
|
||||
|
||||
- Add option Humanreadable barcode to the wizard
|
||||
|
||||
`14.0.1.0.2`
|
||||
------------
|
||||
|
||||
- Fix save_eval error: NameError: name Product_labels_57x35mm is not defined
|
||||
|
||||
`14.0.1.0.1`
|
||||
------------
|
||||
|
||||
- change print_report_name (spaces removed)
|
||||
|
||||
`14.0.1.0.0`
|
||||
------------
|
||||
|
||||
- Migrate to 14.0
|
||||
|
||||
|
||||
@@ -0,0 +1,343 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * garazd_product_label
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 14.0+e\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-08-15 17:27+0000\n"
|
||||
"PO-Revision-Date: 2024-08-15 17:27+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: garazd_product_label
|
||||
#: model:ir.actions.report,print_report_name:garazd_product_label.action_report_product_label_50x38
|
||||
msgid "'Product Labels 50x38mm'"
|
||||
msgstr "'Етикетки 50х38 мм'"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.actions.report,print_report_name:garazd_product_label.action_report_product_label_A4_57x35
|
||||
msgid "'Product Labels 57x35mm'"
|
||||
msgstr "'Етикетки 57х35 мм'"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.actions.report,print_report_name:garazd_product_label.action_report_product_label_from_template
|
||||
msgid "'Product Labels Custom Design'"
|
||||
msgstr "'Етикетки товарів з власний дизайном'"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model_terms:ir.ui.view,arch_db:garazd_product_label.print_product_label_view_form
|
||||
msgid "<span>Get the Label Builder to create your own labels</span>"
|
||||
msgstr ""
|
||||
"<span>Дізнайтеся, як створювати етикетки з власним дизайном за допомогою "
|
||||
"Label Builder</span>"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label_line__barcode
|
||||
#: model_terms:ir.ui.view,arch_db:garazd_product_label.label_57x35
|
||||
#: model_terms:ir.ui.view,arch_db:garazd_product_label.report_product_label_50x38_template
|
||||
msgid "Barcode"
|
||||
msgstr "Штрих-код"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label__border_width
|
||||
msgid "Border"
|
||||
msgstr "Обрамлення"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields,help:garazd_product_label.field_print_product_label__border_width
|
||||
msgid "Border width for labels (in pixels). Set \"0\" for no border."
|
||||
msgstr ""
|
||||
"Ширина рамки для етикеток (у пікселях). Встановіть \"0\", якщо рамка не "
|
||||
"потрібна."
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label__company_id
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label_line__company_id
|
||||
msgid "Company"
|
||||
msgstr "Компанія"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label__create_uid
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label_line__create_uid
|
||||
msgid "Created by"
|
||||
msgstr ""
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label__create_date
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label_line__create_date
|
||||
msgid "Created on"
|
||||
msgstr ""
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.actions.act_window,name:garazd_product_label.action_print_label_from_product
|
||||
#: model:ir.actions.act_window,name:garazd_product_label.action_print_label_from_template
|
||||
msgid "Custom Product Labels"
|
||||
msgstr "Етикетки товарів"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model_terms:ir.ui.view,arch_db:garazd_product_label.print_product_label_view_form
|
||||
msgid "Decrease Qty"
|
||||
msgstr "Зменшити кількість"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label__display_name
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label_line__display_name
|
||||
msgid "Display Name"
|
||||
msgstr ""
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model_terms:ir.ui.view,arch_db:garazd_product_label.print_product_label_view_form
|
||||
msgid "How to get Product Label Builder"
|
||||
msgstr "Як отримати конструктор етикеток \"Product Label Builder\""
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label__humanreadable
|
||||
msgid "Human readable barcode"
|
||||
msgstr "Читабельний штрих-код"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label__id
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label_line__id
|
||||
msgid "ID"
|
||||
msgstr ""
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model_terms:ir.ui.view,arch_db:garazd_product_label.print_product_label_view_form
|
||||
msgid "Increase Qty"
|
||||
msgstr "Збільшити кількість"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label_line__qty_initial
|
||||
msgid "Initial Qty"
|
||||
msgstr "Первісна кількість"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label__is_template_report
|
||||
msgid "Is Template Report"
|
||||
msgstr "Шаблон звіту"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label__report_id
|
||||
#: model_terms:ir.ui.view,arch_db:garazd_product_label.print_product_label_view_form
|
||||
msgid "Label"
|
||||
msgstr "Етикетка"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label_line__qty
|
||||
msgid "Label Qty"
|
||||
msgstr "Кількість етикеток"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label__qty_per_product
|
||||
#: model_terms:ir.ui.view,arch_db:garazd_product_label.print_product_label_view_form
|
||||
msgid "Label quantity per product"
|
||||
msgstr "Кількість етикеток для кожного товару"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model_terms:ir.ui.view,arch_db:garazd_product_label.print_product_label_view_form
|
||||
msgid "Labels"
|
||||
msgstr "Етикетки"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label__label_ids
|
||||
msgid "Labels for Products"
|
||||
msgstr "Етикетки для товарів"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label__lang
|
||||
msgid "Language"
|
||||
msgstr "Мова"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label____last_update
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label_line____last_update
|
||||
msgid "Last Modified on"
|
||||
msgstr ""
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label__write_uid
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label_line__write_uid
|
||||
msgid "Last Updated by"
|
||||
msgstr ""
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label__write_date
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label_line__write_date
|
||||
msgid "Last Updated on"
|
||||
msgstr ""
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model,name:garazd_product_label.model_print_product_label_line
|
||||
msgid "Line with a Product Label Data"
|
||||
msgstr ""
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label__message
|
||||
msgid "Message"
|
||||
msgstr "Повідомлення"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label__mode
|
||||
msgid "Mode"
|
||||
msgstr "Режим"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label__name
|
||||
msgid "Name"
|
||||
msgstr "Назва"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: code:addons/garazd_product_label/wizard/print_product_label.py:0
|
||||
#, python-format
|
||||
msgid "Nothing to print, set the quantity of labels in the table."
|
||||
msgstr "Друкувати нічого, встановіть кількість етикеток у таблиці."
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model_terms:ir.ui.view,arch_db:garazd_product_label.print_product_label_view_form
|
||||
msgid "Options"
|
||||
msgstr "Налаштування"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model_terms:ir.ui.view,arch_db:garazd_product_label.print_product_label_view_form
|
||||
msgid "Output"
|
||||
msgstr "Формат"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields.selection,name:garazd_product_label.selection__print_product_label__output__pdf
|
||||
msgid "PDF"
|
||||
msgstr ""
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: code:addons/garazd_product_label/wizard/print_product_label.py:0
|
||||
#, python-format
|
||||
msgid "Please select a label type."
|
||||
msgstr "Будь ласка, оберіть тип етикетки."
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model_terms:ir.ui.view,arch_db:garazd_product_label.print_product_label_view_form
|
||||
msgid "Preview"
|
||||
msgstr "Попередній перегляд"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model_terms:ir.ui.view,arch_db:garazd_product_label.print_product_label_view_form
|
||||
msgid "Preview product labels"
|
||||
msgstr "Попередній перегляд товарних етикеток"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label_line__selected
|
||||
#: model_terms:ir.ui.view,arch_db:garazd_product_label.print_product_label_view_form
|
||||
msgid "Print"
|
||||
msgstr "Друк"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: code:addons/garazd_product_label/wizard/print_product_label.py:0
|
||||
#: model_terms:ir.ui.view,arch_db:garazd_product_label.print_product_label_view_form
|
||||
#, python-format
|
||||
msgid "Print Product Labels"
|
||||
msgstr "Друк етикеток"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields,help:garazd_product_label.field_print_product_label__humanreadable
|
||||
msgid "Print digital code of barcode."
|
||||
msgstr "Роздрукувати цифровий код штрих-коду."
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model_terms:ir.ui.view,arch_db:garazd_product_label.print_product_label_view_form
|
||||
msgid "Print product labels"
|
||||
msgstr "Друк товарних етикеток"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label__output
|
||||
msgid "Print to"
|
||||
msgstr "Друкувати в"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label_line__product_id
|
||||
msgid "Product"
|
||||
msgstr "Товар"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.actions.report,name:garazd_product_label.action_report_product_label_from_template
|
||||
msgid "Product Label from your own template"
|
||||
msgstr "Етикетки з вашим власним дизайном"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model_terms:ir.ui.view,arch_db:garazd_product_label.res_config_settings_view_form
|
||||
msgid "Product Labels"
|
||||
msgstr "Друк етикеток"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.actions.report,name:garazd_product_label.action_report_product_label_50x38
|
||||
msgid "Product Labels 50x38mm"
|
||||
msgstr "Етикетки 50х38 мм"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.actions.report,name:garazd_product_label.action_report_product_label_A4_57x35
|
||||
msgid "Product Labels 57x35mm (A4, 21 pcs)"
|
||||
msgstr "Етикетки 57x35 мм (A4, 21 шт)"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model_terms:ir.ui.view,arch_db:garazd_product_label.print_product_label_view_form
|
||||
msgid "Restore initial quantity"
|
||||
msgstr "Відновити первісну кількість етикеток"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label_line__sequence
|
||||
msgid "Sequence"
|
||||
msgstr "Послідовність"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model_terms:ir.ui.view,arch_db:garazd_product_label.print_product_label_view_form
|
||||
msgid "Set a certain quantity for each line."
|
||||
msgstr "Встановіть певну кількість для кожного рядка."
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model_terms:ir.ui.view,arch_db:garazd_product_label.print_product_label_view_form
|
||||
msgid "Set quantity"
|
||||
msgstr "Встановити кількість"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model_terms:ir.ui.view,arch_db:garazd_product_label.print_product_label_view_form
|
||||
msgid "Sort labels by a product"
|
||||
msgstr "Сортування етикеток за товаром"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields,help:garazd_product_label.field_print_product_label__company_id
|
||||
msgid "Specify a company for product labels."
|
||||
msgstr "Вкажіть компанію для товарних етикеток."
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields,help:garazd_product_label.field_print_product_label__mode
|
||||
msgid "Technical field"
|
||||
msgstr ""
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model_terms:ir.ui.view,arch_db:garazd_product_label.print_product_label_view_form
|
||||
msgid "Template"
|
||||
msgstr "Шаблон"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields,help:garazd_product_label.field_print_product_label__lang
|
||||
msgid "The language that will be used to translate label names."
|
||||
msgstr "Мова, яка використовуватиметься для перекладу полів етикетки."
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model_terms:ir.ui.view,arch_db:garazd_product_label.print_product_label_view_form
|
||||
msgid "Total"
|
||||
msgstr "Всього"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model.fields,field_description:garazd_product_label.field_print_product_label_line__wizard_id
|
||||
msgid "Wizard"
|
||||
msgstr "Майстер"
|
||||
|
||||
#. module: garazd_product_label
|
||||
#: model:ir.model,name:garazd_product_label.model_print_product_label
|
||||
msgid "Wizard to print Product Labels"
|
||||
msgstr "Майстер для друку етикеток товарів"
|
||||
@@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="paperformat_label_a4_blank" model="report.paperformat">
|
||||
<field name="name">Label A4</field>
|
||||
<field name="format">A4</field>
|
||||
<field name="page_height">0</field>
|
||||
<field name="page_width">0</field>
|
||||
<field name="orientation">Portrait</field>
|
||||
<field name="margin_top">10</field>
|
||||
<field name="margin_bottom">10</field>
|
||||
<field name="margin_left">5</field>
|
||||
<field name="margin_right">5</field>
|
||||
<field name="header_line" eval="False"/>
|
||||
<field name="header_spacing">0</field>
|
||||
<field name="dpi">77</field>
|
||||
<field name="default" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record id="paperformat_label_50x38" model="report.paperformat">
|
||||
<field name="name">Label 50x38 mm</field>
|
||||
<field name="format">custom</field>
|
||||
<field name="page_height">38</field>
|
||||
<field name="page_width">50</field>
|
||||
<field name="orientation">Portrait</field>
|
||||
<field name="margin_top">1</field>
|
||||
<field name="margin_bottom">0</field>
|
||||
<field name="margin_left">0</field>
|
||||
<field name="margin_right">0</field>
|
||||
<field name="header_line" eval="False"/>
|
||||
<field name="header_spacing">0</field>
|
||||
<field name="dpi">77</field>
|
||||
<field name="default" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record id="action_report_product_label_A4_57x35" model="ir.actions.report">
|
||||
<field name="name">Product Labels 57x35mm (A4, 21 pcs)</field>
|
||||
<field name="model">print.product.label.line</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="paperformat_id" ref="paperformat_label_a4_blank"/>
|
||||
<field name="report_name">garazd_product_label.report_product_label_57x35_template</field>
|
||||
<field name="report_file">garazd_product_label.report_product_label_57x35_template</field>
|
||||
<field name="print_report_name">'Product Labels 57x35mm'</field>
|
||||
</record>
|
||||
|
||||
<record id="action_report_product_label_50x38" model="ir.actions.report">
|
||||
<field name="name">Product Labels 50x38mm</field>
|
||||
<field name="model">print.product.label.line</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="paperformat_id" ref="paperformat_label_50x38"/>
|
||||
<field name="report_name">garazd_product_label.report_product_label_50x38_template</field>
|
||||
<field name="report_file">garazd_product_label.report_product_label_50x38_template</field>
|
||||
<field name="print_report_name">'Product Labels 50x38mm'</field>
|
||||
</record>
|
||||
|
||||
<record id="action_report_product_label_from_template" model="ir.actions.report">
|
||||
<field name="name">Product Label from your own template</field>
|
||||
<field name="model">print.product.label.line</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="paperformat_id" ref="garazd_product_label.paperformat_label_a4_blank"/>
|
||||
<field name="report_name">garazd_product_label.report_product_label_from_template</field>
|
||||
<field name="report_file">garazd_product_label.report_product_label_from_template</field>
|
||||
<field name="print_report_name">'Product Labels Custom Design'</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
|
||||
<template id="label_57x35">
|
||||
<table class="table" style="margin: 0; padding: 0;">
|
||||
<tr height="144px" style="border:0;margin:0;padding:0;">
|
||||
<td class="col-xs-4 text-center" style="border:0;margin:0;padding:0;">
|
||||
<div style="overflow:hidden; height:65px !important; width: 215px !important; padding: 5px 5px 0; line-height: 1.3;">
|
||||
<span t-field="label.product_id.name"/>
|
||||
<span t-if="label.product_id.product_template_attribute_value_ids"
|
||||
t-esc="u', '.join(map(lambda x: x.attribute_line_id.attribute_id.name + u': ' + x.name, label.product_id.product_template_attribute_value_ids))"
|
||||
class="badge"
|
||||
/>
|
||||
</div>
|
||||
<div style="width: 100%; padding: 0; margin: 0; font-size: 21px; font-weight: bold;">
|
||||
<span t-if="label.product_id.currency_id.position == 'before'" t-field="label.product_id.currency_id.symbol"/>
|
||||
<span t-field="label.product_id.lst_price"/>
|
||||
<span t-if="label.product_id.currency_id.position == 'after'" t-field="label.product_id.currency_id.symbol"/>
|
||||
</div>
|
||||
<div t-if="label.product_id.default_code" style="width: 100%; padding: 0; margin: 0; font-size: 12px;">
|
||||
<span t-field="label.product_id.default_code"/>
|
||||
</div>
|
||||
<div t-if="label.product_id.barcode" class="text-center align-middle" style="width: 100%; height: 13px; padding: 0 8px;">
|
||||
<t t-if="label.wizard_id.humanreadable" t-set="show_code" t-value="1"/>
|
||||
<t t-else="" t-set="show_code" t-value="0" />
|
||||
<img alt="Barcode" t-if="len(label.product_id.barcode) == 13"
|
||||
t-att-src="'/report/barcode/?type=%s&value=%s&width=%s&height=%s&humanreadable=%s' % ('EAN13', label.product_id.barcode, 600, 100, show_code)"
|
||||
style="overflow: hidden; width: 100%; height: 1.4rem;"
|
||||
/>
|
||||
<img alt="Barcode" t-elif="len(label.product_id.barcode) == 8"
|
||||
t-att-src="'/report/barcode/?type=%s&value=%s&width=%s&height=%s&humanreadable=%s' % ('EAN8', label.product_id.barcode, 600, 100, show_code)"
|
||||
style="overflow: hidden; width: 100%; height: 1.4rem;"/>
|
||||
<img alt="Barcode" t-else=""
|
||||
t-att-src="'/report/barcode/?type=%s&value=%s&width=%s&height=%s&humanreadable=%s' % ('Code128', label.product_id.barcode, 600, 100, show_code)"
|
||||
style="overflow: hidden; width: 100%; height: 1.4rem;"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</template>
|
||||
|
||||
<template id="report_product_label_57x35_template">
|
||||
<t t-call="web.html_container">
|
||||
<t t-call="web.basic_layout">
|
||||
<t t-set="count" t-value="0" />
|
||||
<div class="page">
|
||||
<div class="oe_structure"/>
|
||||
<t t-foreach="docs" t-as="label">
|
||||
<t t-set="qty" t-value="1" />
|
||||
<t t-if="label.qty">
|
||||
<t t-set="qty" t-value="label.qty" />
|
||||
</t>
|
||||
<t t-foreach="list(range(qty))" t-as="index_qty">
|
||||
<div t-if="count % 21 == 0" style="page-break-after:always;"/>
|
||||
<div t-if="count % 3 == 0" style="clear:both;"/>
|
||||
<div t-att-style="'width: 233px; float: left; height: 145px; margin: 0 4px 4px; border: {};'.format('%dpx solid #777;' % label.wizard_id.border_width if label.wizard_id.border_width else '0')">
|
||||
<t t-call="garazd_product_label.label_57x35"/>
|
||||
</div>
|
||||
<t t-set="count" t-value="count+1" />
|
||||
</t>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="report_product_label_50x38_template">
|
||||
<t t-call="web.html_container">
|
||||
<t t-call="web.basic_layout">
|
||||
<t t-foreach="docs" t-as="label">
|
||||
<t t-set="qty" t-value="1"/>
|
||||
<t t-if="label.qty" t-set="qty" t-value="label.qty" />
|
||||
<t t-foreach="list(range(qty))" t-as="index_qty">
|
||||
<div class="page" style="page-break-after: always;">
|
||||
<div style="height: 136px !important; width: 165px !important;">
|
||||
<table class="table" t-att-style="'height: 100%; border: {};'.format('%dpx solid #777;' % label.wizard_id.border_width if label.wizard_id.border_width else '0')">
|
||||
<tr style="border: 0;">
|
||||
<td class="text-center" style="padding: 0; margin: 0; border: 0;">
|
||||
<div style="overflow: hidden; height: 64px !important; font-size: 13px; line-height: 1.2; margin-bottom: 2px;">
|
||||
<span t-field="label.product_id.name" />
|
||||
<span t-if="label.product_id.product_template_attribute_value_ids"
|
||||
t-esc="u', '.join(map(lambda x: x.attribute_line_id.attribute_id.name + u': ' + x.name, label.product_id.product_template_attribute_value_ids))"
|
||||
class="badge"/>
|
||||
</div>
|
||||
<div style="width: 100%; overflow: hidden; height: 26px !important;">
|
||||
<div style="float: right; width: 60%; font-size: 20px; font-weight: bold; line-height: 1.0; text-align: right; margin-bottom: 0px;">
|
||||
<span t-if="label.product_id.currency_id.position == 'before'" t-field="label.product_id.currency_id.symbol"/>
|
||||
<span t-field="label.product_id.lst_price"/>
|
||||
<span t-if="label.product_id.currency_id.position == 'after'" t-field="label.product_id.currency_id.symbol"/>
|
||||
</div>
|
||||
<div style="float: left; width: 40%; font-size: 10px; font-weight: 900; line-height: 1.0; text-align: left; margin-bottom: 0px; padding-top: 6px;">
|
||||
<span t-if="label.product_id.default_code"><span t-field="label.product_id.default_code"/> </span>
|
||||
</div>
|
||||
</div>
|
||||
<div t-if="label.product_id.barcode" class="text-center align-middle" style="margin: 2px; height: 32px; clear: both;">
|
||||
<t t-if="label.wizard_id.humanreadable" t-set="show_code" t-value="1"/>
|
||||
<t t-else="" t-set="show_code" t-value="0" />
|
||||
<img alt="Barcode" t-if="len(label.product_id.barcode) == 13"
|
||||
t-att-src="'/report/barcode/?type=%s&value=%s&width=%s&height=%s&humanreadable=%s' % ('EAN13', label.product_id.barcode, 600, 100, show_code)"
|
||||
style="overflow: hidden; width: 100%; height: 2rem;"/>
|
||||
<img alt="Barcode" t-elif="len(label.product_id.barcode) == 8"
|
||||
t-att-src="'/report/barcode/?type=%s&value=%s&width=%s&height=%s&humanreadable=%s' % ('EAN8', label.product_id.barcode, 600, 100, show_code)"
|
||||
style="overflow: hidden; width: 100%; height: 2rem;"/>
|
||||
<img alt="Barcode" t-else=""
|
||||
t-att-src="'/report/barcode/?type=%s&value=%s&width=%s&height=%s&humanreadable=%s' % ('Code128', label.product_id.barcode, 600, 100, show_code)"
|
||||
style="overflow: hidden; width: 100%; height: 2rem;"/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<template id="report_product_label_from_template">
|
||||
<t t-call="web.basic_layout"/>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
@@ -0,0 +1,3 @@
|
||||
id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_print_product_label_line_user,access_print_product_label_line_user,model_print_product_label_line,base.group_user,1,1,1,1
|
||||
access_print_product_label_user,access_print_product_label_user,model_print_product_label,base.group_user,1,1,1,0
|
||||
|
|
After Width: | Height: | Size: 73 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 75 KiB |
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 9.2 KiB |
@@ -0,0 +1,594 @@
|
||||
<section class="oe_container" style="font-family: 'Montserrat', 'Odoo Unicode Support Noto', sans-serif;">
|
||||
<div class="row mt-3">
|
||||
|
||||
<ul class="offset-3 col-6 text-left d-md-none list-unstyled pt-5">
|
||||
<li class="border-top border-bottom"><div class="my-2 mx-sm-2" style="color: #6F649A;"><i class="fa fa-check-circle"></i> Community</div></li>
|
||||
<li class="border-bottom"><div class="my-2 mx-sm-2" style="color: #694D65;"><i class="fa fa-check-circle"></i> Enterprise</div></li>
|
||||
</ul>
|
||||
|
||||
<div class="col-12 text-right d-none d-md-block">
|
||||
<span class="m-2" style="float: right; background-color: #694D65; border-color: #694D65; color: #FFFFFF; padding: 5px 18px; border-radius: 15px 0 15px 0; opacity: 1;"><i class="fa fa-check"></i> Enterprise</span>
|
||||
<span class="m-2" style="float: right; background-color: #6F649A; border-color: #6F649A; color: #FFFFFF; padding: 5px 18px; border-radius: 15px 0 15px 0; opacity: 1;"><i class="fa fa-check"></i> Community</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="oe_container" style="font-family: 'Montserrat', 'Odoo Unicode Support Noto', sans-serif;">
|
||||
<div class="row oe_spaced">
|
||||
<div class="offset-2 col-8 offset-md-3 col-md-6 offset-lg-0 col-lg-2">
|
||||
<div class="text-center shadow ml8">
|
||||
<div class="s_panel_video" data-video-id="0Sem8pMbUyU?rel=0&start=0" style="cursor: pointer; width: 100%;" data-container="body" data-toggle="popover" data-placement="top" data-content="Click on the image to play the video.">
|
||||
<img class="s_tooltip_tabs_tooltip_image s_figure_link img-fluid rounded-top pb-0" src="banner_youtube.png" alt="Custom Product Labels youtube video tutorial">
|
||||
</div>
|
||||
<a href="https://youtu.be/0Sem8pMbUyU" target="_blank" class="btn btn-danger rounded-bottom p-1" role="button" style="width: 100%; font-size: 0.7rem;">Watch on Youtube <i class="fa fa-external-link"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="offset-xl-1 col-lg-9 d-flex d-column mt-5 mt-lg-0">
|
||||
<h2 class="h1 align-self-center text-center" style="color: #154577; font-weight: 900; font-family: 'Montserrat', 'Odoo Unicode Support Noto', sans-serif;">Product label printing easily in Odoo</h2>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="oe_container" style="font-family: 'Montserrat', 'Odoo Unicode Support Noto', sans-serif;">
|
||||
<div class="row oe_spaced">
|
||||
<div class="col-12">
|
||||
<div class="h2 text-left ml8" style="color: #FEA621;"><i class="fa fa-newspaper-o mr8"></i>Description</div>
|
||||
<div class="media p-2 pt-4 overflow-hidden" style="border-color: #FEA621 !important; border-radius: 0 15px 0 0; border-top-style: solid; border-right-style: solid;">
|
||||
<div class="py-2 px-md-5 lead w-100" style="line-height: 2.5rem;"><p>There are a lot of cases when company business processes require having the ability to print product barcode labels. However, different printers and label makers use varied paper formats and label designs can be individual for each company.</p>
|
||||
|
||||
<p>The <a href="https://apps.odoo.com/apps/modules/browse?search=product+label&repo_maintainer_id=119796">Odoo Product Labels</a> app family by <b>Garazd Creation</b> solves this business need and gives a usable tool to generate and print product labels with required sizes.</p>
|
||||
|
||||
<p class="pt-3">This module allows printing custom product labels with barcode on various paper formats. It includes two label templates:</p>
|
||||
<ul>
|
||||
<li><b>57x35mm</b> (21 pcs on the A4 paper format, 3 pcs x 7 rows)</li>
|
||||
<li><b>50x38mm</b> (the Dymo label, 2" x 1.5")</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="oe_container" style="font-family: 'Montserrat', 'Odoo Unicode Support Noto', sans-serif;">
|
||||
<div class="row oe_spaced">
|
||||
<div class="col-12">
|
||||
<div class="h2 text-left ml8" style="color: #FEA621;"><i class="fa fa-check-square-o mr8"></i>Benefits</div>
|
||||
<div class="s_features_grid p-2 pt-4 o_colored_level" data-snippet="s_features_grid" data-name="Features Grid" style="border-color: #FEA621 !important; border-radius: 0 15px 0 0; border-top-style: solid; border-right-style: solid; background-color: #ffa81f14;">
|
||||
<div class="container p-0">
|
||||
<div class="row px-md-5">
|
||||
<div class="col-lg-6 s_col_no_bgcolor pb24">
|
||||
<div class="row">
|
||||
<div class="col-lg-12 o_colored_level" data-name="Box">
|
||||
<i class="s_features_grid_icon fa fa-2x float-left mr32 mr-3 bg-warning fa-youtube-play rounded-circle" style="line-height:5rem; height:5rem; width:5rem; text-align:center; float:left;"></i>
|
||||
<div class="s_features_grid_content">
|
||||
<div class="h4 pt-2">Watch Demo</div>
|
||||
<p>Watch the video tutorial</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6 s_col_no_bgcolor pb24">
|
||||
<div class="row">
|
||||
<div class="col-lg-12 o_colored_level" data-name="Box">
|
||||
<i class="s_features_grid_icon fa fa-2x float-left mr32 mr-3 bg-warning fa-check-square-o rounded-circle" style="line-height:5rem; height:5rem; width:5rem; text-align:center; float:left;"></i>
|
||||
<div class="s_features_grid_content">
|
||||
<div class="h4 pt-2">Tested</div>
|
||||
<p>Include unit tests</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6 s_col_no_bgcolor pb24">
|
||||
<div class="row">
|
||||
<div class="col-lg-12 o_colored_level" data-name="Box">
|
||||
<i class="s_features_grid_icon fa fa-2x float-left mr32 mr-3 bg-warning fa-edit rounded-circle" style="line-height:5rem; height:5rem; width:5rem; text-align:center; float:left;"></i>
|
||||
<div class="s_features_grid_content">
|
||||
<div class="h4 pt-2">Customize</div>
|
||||
<p>Contact us for improvements and changes</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6 s_col_no_bgcolor pb24">
|
||||
<div class="row">
|
||||
<div class="col-lg-12 o_colored_level" data-name="Box">
|
||||
<i class="s_features_grid_icon fa fa-2x float-left mr32 mr-3 bg-dark fa-search rounded-circle" style="line-height:5rem; height:5rem; width:5rem; text-align:center; float:left;"></i>
|
||||
<div class="s_features_grid_content">
|
||||
<div class="h4 pt-2">Try me</div>
|
||||
<p>Demo & Test. Click on the "Live Preview" button</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="oe_container" style="font-family: 'Montserrat', 'Odoo Unicode Support Noto', sans-serif;">
|
||||
<div class="row oe_spaced">
|
||||
<div class="col-12">
|
||||
<section class="oe_container" style="font-family: 'Montserrat','Odoo Unicode Support Noto',sans-serif; line-height: 2rem;">
|
||||
<div class="h2 text-left ml8" style="color: #FEA621;"><i class="fa fa-mouse-pointer mr8"></i>Product Selection</div>
|
||||
<div class="media p-2 pt-4 border-top border-right" style="border-color: #FEA621 !important; border-radius: 0 15px 0 0;">
|
||||
<div class="media-body">
|
||||
|
||||
<div class="py-2 px-md-5" style="line-height: 2rem;">
|
||||
To print labels by the wizard, go to the "<b>Products</b>" or "<b>Product Variants</b>" menu and select one or several products.
|
||||
Then click on the "<b>Custom Product Labels</b>" in the "<b>Print</b>" menu.
|
||||
</div>
|
||||
<div class="text-center my-5 mx-md-5">
|
||||
<img src="print_product_label_select_products.png" class="w-100 img-fluid rounded shadow-lg border" alt="Odoo 14.0 select products to print">
|
||||
</div>
|
||||
<blockquote class="py-2 my-3 ml-md-5">By using our additional modules, you will also be able to select products from:
|
||||
<a href="https://apps.odoo.com/apps/modules/14.0/garazd_product_label_picking/">Stock Pickings</a>,
|
||||
<a href="https://apps.odoo.com/apps/modules/14.0/garazd_product_label_packaging/">Product Packaging</a>,
|
||||
<a href="https://apps.odoo.com/apps/modules/14.0/garazd_product_label_purchase/">Purchase Orders</a>,
|
||||
<a href="https://apps.odoo.com/apps/modules/14.0/garazd_product_label_mrp/">Manufacturing Orders</a>.
|
||||
</blockquote>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="oe_container" style="font-family: 'Montserrat', 'Odoo Unicode Support Noto', sans-serif;">
|
||||
<div class="row oe_spaced">
|
||||
<div class="col-12">
|
||||
<section class="oe_container" style="font-family: 'Montserrat','Odoo Unicode Support Noto',sans-serif; line-height: 2rem;">
|
||||
<div class="h2 text-left ml8" style="color: #FEA621;"><i class="fa fa-gears mr8"></i>Label Settings</div>
|
||||
<div class="media p-2 pt-4 border-top border-right bg-light" style="border-color: #FEA621 !important; border-radius: 0 15px 0 0;">
|
||||
<div class="media-body">
|
||||
|
||||
<div class="h3 mt-4 p-2 pl-md-5">Label Settings</div>
|
||||
<div class="py-2 px-md-5" style="line-height: 2rem;">
|
||||
In the print wizard form:
|
||||
</div>
|
||||
<ol class="py-2 mx-md-3">
|
||||
<li>Select a <b>Label Template</b>.</li>
|
||||
<blockquote>
|
||||
Templates can be in a variety of designs, sizes, and paper formats. Look at our <a href="https://apps.odoo.com/apps/modules/browse?search=garazd_product_label&repo_maintainer_id=119796">other related modules</a>.
|
||||
</blockquote>
|
||||
<li>Specify the number of labels you want to print</li>
|
||||
<blockquote> You can enter a quantity value or use <i class="fa fa-minus"></i> / <i class="fa fa-plus"></i> buttons.</blockquote>
|
||||
<li>If you need to set a specific quantity for each label, enter the value and click on <b>Set quantity</b>.</li>
|
||||
<li>After changing the label quantities, you can restore the initial values by clicking the button <i class="fa fa-undo"></i>.</li>
|
||||
<li>To sort labels by product, click on this button.</li>
|
||||
<li>You can reorder the labels manually or deactivate some labels to avoid printing them.</li>
|
||||
</ol>
|
||||
<div class="text-center my-5 mx-md-5">
|
||||
<img src="print_product_label_settings.png" class="w-100 img-fluid rounded shadow-lg border" alt="Odoo 14.0 product label settings">
|
||||
</div>
|
||||
|
||||
<div class="h3 mt-4 p-2 pl-md-5">Label Options</div>
|
||||
<div class="py-2 px-md-5" style="line-height: 2rem;">
|
||||
You can also set some label options on the tab <b>Options</b>:
|
||||
</div>
|
||||
<ul class="py-2 mx-md-5">
|
||||
<li><b>Language</b> - to specify the language to translate label fields.</li>
|
||||
<li><b>Human readable barcode</b> - to print a barcode digit code on the labels.</li>
|
||||
<li><b>Border</b> - to set the label border width.</li>
|
||||
<blockquote>Set to <b>0</b> to print labels without border.</blockquote>
|
||||
<li><b>Company</b> - select a company if your label's data is related from the company.</li>
|
||||
</ul>
|
||||
<div class="text-center my-5 mx-md-5">
|
||||
<img src="print_product_label_options.png" class="w-100 img-fluid rounded shadow-lg border" alt="Odoo 14.0 product label options">
|
||||
</div>
|
||||
|
||||
<div class="h3 mt-4 p-2 pl-md-5">Label Printing</div>
|
||||
<div class="py-2 px-md-5 mb-4" style="line-height: 2rem;">
|
||||
Finally, you can preview the labels before printing, by clicking on the <span class="btn btn-sm btn-secondary"><i class="fa fa-search"/> PREVIEW</span> button, or print them with the <span class="btn btn-sm btn-primary"><i class="fa fa-print"/> PRINT</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="oe_container" style="font-family: 'Montserrat', 'Odoo Unicode Support Noto', sans-serif;">
|
||||
<div class="row oe_spaced">
|
||||
<div class="col-12">
|
||||
<section class="oe_container" style="font-family: 'Montserrat','Odoo Unicode Support Noto',sans-serif; line-height: 2rem;">
|
||||
<div class="h2 text-left pl-2" style="color: #FEA621;"><i class="fa fa-paint-brush mr8"></i>Design your own label</div>
|
||||
<div class="mb-3 border-top border-right" style="background-color: #FEA621; border-color: #FEA621 !important; border-radius: 0 15px 0 0;">
|
||||
<div class="container p-0">
|
||||
<div class="py-2 px-md-5 text-white d-flex justify-content-center" style="line-height: 2rem; font-size: 1.2rem;">
|
||||
<span class="my-auto">Create a variety of labels with awesome designs using the </span>
|
||||
<i class="fa fa-angle-double-right fa-2x px-3 my-auto"></i>
|
||||
<a href="https://apps.odoo.com/apps/modules/14.0/garazd_product_label_pro/" class="btn btn-light text-primary my-auto">Product Label Builder</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="oe_container" style="font-family: 'Montserrat', 'Odoo Unicode Support Noto', sans-serif;">
|
||||
<div class="row oe_spaced">
|
||||
<div class="col-12">
|
||||
<section class="oe_container" style="font-family: 'Montserrat','Odoo Unicode Support Noto',sans-serif; line-height: 2rem;">
|
||||
<div class="h2 text-left ml8" style="color: #FEA621;"><i class="fa fa-barcode mr8"></i>Label Samples</div>
|
||||
<div class="media p-2 pt-4 border-top border-right" style="border-color: #FEA621 !important; border-radius: 0 15px 0 0;">
|
||||
<div class="media-body">
|
||||
|
||||
<div class="py-2 px-md-5" style="line-height: 2rem;">
|
||||
Labels will be generated in the PDF format:
|
||||
</div>
|
||||
<div class="text-center my-5 mx-md-5">
|
||||
<img src="product_barcode_label_50x38mm.png" class="w-100 w-lg-25 img-fluid rounded shadow-lg border" alt="Odoo 14.0 Custom Product Labels">
|
||||
</div>
|
||||
<div class="text-center my-5 mx-md-5">
|
||||
<img src="product_barcode_label_A4_57x35mm.png" class="w-100 w-lg-50 img-fluid rounded shadow-lg border" alt="Odoo 14.0 Custom Product Labels">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="oe_container" style="font-family: 'Montserrat','Odoo Unicode Support Noto',sans-serif;">
|
||||
<div class="row oe_spaced">
|
||||
<div class="col-12">
|
||||
<div class="h2 text-left pl-2 pt-3" style="color: #FEA621; font-family: 'Montserrat', 'Odoo Unicode Support Noto', sans-serif;">Related Modules</div>
|
||||
<div class="mb-3 bg-light" style="border-color:#FEA621 !important; border-radius: 0 15px 0 0; border-top-style: solid; border-right-style: solid;">
|
||||
<div id="related_modules" class="carousel slide mt-2 mx-3" data-ride="carousel" data-interval="15000" data-pause="hover">
|
||||
<div class="carousel-inner">
|
||||
<div class="carousel-item row active" style="min-height: 0px;">
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 my-4 px-3" style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/14.0/garazd_product_label_pro/" target="_blank">
|
||||
<div class="card shadow-sm border rounded deep-1 deep_hover">
|
||||
<img class="img img-responsive center-block border-bottom w-100" src="banner_garazd_product_label_pro.png" alt="Odoo App Product Label Builder" title="Product Label Builder | Product Barcode Label Building and Printing | Professional Tool to Print Labels | Barcode Product Label Builder | Product Label Designer | Sticker Label Maker | Dymo Label Maker | Barcode Label Generator | Direct Print">
|
||||
<div class="card-body">
|
||||
<div class="card-title h5 text-nowrap text-truncate" title="Product Label Builder">Product Label Builder</div>
|
||||
<p class="card-text small text-nowrap text-truncate" title="Product Barcode Label Building and Printing | Professional Tool to Print Labels | Barcode Product Label Builder | Product Label Designer | Sticker Label Maker | Dymo Label Maker | Barcode Label Generator | Direct Print">Product Barcode Label Building and Printing | Professional Tool to Print Labels | Barcode Product Label Builder | Product Label Designer | Sticker Label Maker | Dymo Label Maker | Barcode Label Generator | Direct Print</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 my-4 px-3" style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/14.0/garazd_product_label_picking/" target="_blank">
|
||||
<div class="card shadow-sm border rounded deep-1 deep_hover">
|
||||
<img class="img img-responsive center-block border-bottom w-100" src="banner_garazd_product_label_picking.png" alt="Odoo App Stock Product Labels" title="Stock Product Labels | Print custom product barcode labels for stock transfers | Product Barcode Labels Printing | Print Product Labels | Barcode Product Labels Printinf from Stock | Barcode labels for inventory | Label Inventory Tag">
|
||||
<div class="card-body">
|
||||
<div class="card-title h5 text-nowrap text-truncate" title="Stock Product Labels">Stock Product Labels</div>
|
||||
<p class="card-text small text-nowrap text-truncate" title="Print custom product barcode labels for stock transfers | Product Barcode Labels Printing | Print Product Labels | Barcode Product Labels Printinf from Stock | Barcode labels for inventory | Label Inventory Tag">Print custom product barcode labels for stock transfers | Product Barcode Labels Printing | Print Product Labels | Barcode Product Labels Printinf from Stock | Barcode labels for inventory | Label Inventory Tag</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 my-4 px-3" style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/14.0/garazd_product_label_purchase/" target="_blank">
|
||||
<div class="card shadow-sm border rounded deep-1 deep_hover">
|
||||
<img class="img img-responsive center-block border-bottom w-100" src="banner_garazd_product_label_purchase.png" alt="Odoo App Purchase Product Labels" title="Purchase Product Labels | Print custom product barcode labels for purchase orders | Barcode product label printing from purchase order">
|
||||
<div class="card-body">
|
||||
<div class="card-title h5 text-nowrap text-truncate" title="Purchase Product Labels">Purchase Product Labels</div>
|
||||
<p class="card-text small text-nowrap text-truncate" title="Print custom product barcode labels for purchase orders | Barcode product label printing from purchase order">Print custom product barcode labels for purchase orders | Barcode product label printing from purchase order</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="carousel-item row" style="min-height: 0px;">
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 my-4 px-3" style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/14.0/garazd_product_label_packaging/" target="_blank">
|
||||
<div class="card shadow-sm border rounded deep-1 deep_hover">
|
||||
<img class="img img-responsive center-block border-bottom w-100" src="banner_garazd_product_label_packaging.png" alt="Odoo App Product Packaging Labels" title="Product Packaging Labels | Custom Product Packagings Labels | Product Barcode Labels Printing | Print Product Labels">
|
||||
<div class="card-body">
|
||||
<div class="card-title h5 text-nowrap text-truncate" title="Product Packaging Labels">Product Packaging Labels</div>
|
||||
<p class="card-text small text-nowrap text-truncate" title="Custom Product Packagings Labels | Product Barcode Labels Printing | Print Product Labels">Custom Product Packagings Labels | Product Barcode Labels Printing | Print Product Labels</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 my-4 px-3" style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/14.0/garazd_product_label_mrp/" target="_blank">
|
||||
<div class="card shadow-sm border rounded deep-1 deep_hover">
|
||||
<img class="img img-responsive center-block border-bottom w-100" src="banner_garazd_product_label_mrp.png" alt="Odoo App MRP Product Labels" title="MRP Product Labels | Custom Product Labels in Manufacturing | Barcode Product Labels Printinf from Manufacturing">
|
||||
<div class="card-body">
|
||||
<div class="card-title h5 text-nowrap text-truncate" title="MRP Product Labels">MRP Product Labels</div>
|
||||
<p class="card-text small text-nowrap text-truncate" title="Custom Product Labels in Manufacturing | Barcode Product Labels Printinf from Manufacturing">Custom Product Labels in Manufacturing | Barcode Product Labels Printinf from Manufacturing</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-4 col-md-4 my-4 px-3" style="float:left">
|
||||
<a href="https://apps.odoo.com/apps/modules/17.0/garazd_product_label_account/" target="_blank">
|
||||
<div class="card shadow-sm border rounded deep-1 deep_hover">
|
||||
<img class="img img-responsive center-block border-bottom w-100" src="banner_garazd_product_label_account.png" alt="Odoo App Account Product Labels" title="Account Product Labels | Product Labels with Accounting Features | Barcode Labels with VAT | Product Labels with Tax-included prices">
|
||||
<div class="card-body">
|
||||
<div class="card-title h5 text-nowrap text-truncate" title="Account Product Labels">Account Product Labels</div>
|
||||
<p class="card-text small text-nowrap text-truncate" title="Product Labels with Accounting Features | Barcode Labels with VAT | Product Labels with Tax-included prices">Product Labels with Accounting Features | Barcode Labels with VAT | Product Labels with Tax-included prices</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- Control arrows -->
|
||||
<a class="carousel-control-prev w-0" href="#related_modules" data-slide="prev" style="color: #FEA621;">
|
||||
<span class="carousel-control-prev-icon"><i class="fa fa-chevron-left fa-2x"></i></span>
|
||||
</a>
|
||||
<a class="carousel-control-next w-0" href="#related_modules" data-slide="next" style="color: #FEA621;">
|
||||
<span class="carousel-control-next-icon"><i class="fa fa-chevron-right fa-2x"></i></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="oe_container" style="font-family: 'Montserrat', 'Odoo Unicode Support Noto', sans-serif; background-color: #FEA621; border-color: #fea621; padding: 12px 28px; border-radius: 15px 0 15px 0;">
|
||||
<div class="row my-2">
|
||||
|
||||
<div class="col-lg-4 text-center mb-5 mb-lg-0">
|
||||
<div class="h3 p-2 mb-2 font-weight-bold">Contact Us</div>
|
||||
<div class="lead text-white pb-2">Support, customizations, and development</div>
|
||||
<div class="w-100 w-md-75 w-lg-100 my-1 pl-3 text-nowrap text-truncate btn btn-dark rounded">
|
||||
<i class="fa fa-envelope fa-fw" style="font-size:1.2rem;"></i>
|
||||
<a href="mailto:support@garazd.biz" target="_blank">support@garazd.biz</a>
|
||||
</div>
|
||||
<div class="w-100 w-md-75 w-lg-100 my-1 pl-3 text-nowrap text-truncate btn btn-dark rounded">
|
||||
<i class="fa fa-skype fa-fw" style="font-size:1.2rem;"></i>
|
||||
<span>Skype: </span>
|
||||
<a href="skype:live:7f0648d653072c5f?chat" target="_blank">GarazdCreation</a>
|
||||
</div>
|
||||
<div class="w-100 w-md-75 w-lg-100 m-auto my-1 pl-3 text-nowrap text-truncate btn-light border border-dark rounded" style="line-height: 2.4rem;">
|
||||
<a href="https://garazd.biz/contactus" target="_blank">https://garazd.biz/contactus</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-4 border-left border-right">
|
||||
<div class="h3 p-2 mb-3 text-center font-weight-bold">Our expertise</div>
|
||||
<div class="text-left">
|
||||
<div class="my-3 pl-3 text-nowrap text-truncate lead text-white" data-container="body" data-toggle="popover" data-placement="top" data-content="Garazd Creation is official Odoo Partner with the status 'Learning Partner'.">
|
||||
<i class="fa fa-handshake-o fa-fw"></i> Odoo Learning Partner
|
||||
</div>
|
||||
<div class="my-3 pl-3 text-nowrap text-truncate lead text-white" data-container="body" data-toggle="popover" data-placement="top" data-content="Odoo Community Association member.">
|
||||
<i class="fa fa-group fa-fw"></i> OCA Member
|
||||
</div>
|
||||
<div class="my-3 pl-3 text-nowrap text-truncate lead text-white" data-container="body" data-toggle="popover" data-placement="top" data-content="Garazd Creation with Odoo since 2014.">
|
||||
<i class="fa fa-calendar-check-o fa-fw"></i> With Odoo since 2014
|
||||
</div>
|
||||
<div class="my-3 pl-3 lead text-white" data-container="body" data-toggle="popover" data-placement="top" data-content="Over 20,000 app downloads and purchases in Odoo Apps Store.">
|
||||
<i class="fa fa-download fa-fw"></i> Over 20,000 app downloads and purchases
|
||||
</div>
|
||||
<div class="my-3 pl-3 lead text-white" data-container="body" data-toggle="popover" data-placement="top" data-content="Our apps in the TOP 10 on Odoo Apps.">
|
||||
<i class="fa fa-trophy fa-fw"></i> Our apps in the TOP 10 on Odoo Apps
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-4 mt-5 mt-lg-0">
|
||||
<div class="h3 p-2 text-center font-weight-bold">Explore our apps</div>
|
||||
<div class="text-center mb-3">
|
||||
<a href="https://apps.odoo.com/apps/browse?repo_maintainer_id=119796" target="_blank">
|
||||
<div class="text-black bg-warning shadow-sm rounded">
|
||||
<i class="fa fa-compass fa-4x py-0"></i>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="h4 p-2 text-center font-weight-bold">Watch and subscribe</div>
|
||||
<div class="text-center">
|
||||
<a href="https://www.youtube.com/channel/UCjHB3t-qc6SQmbgnS8bSPOA?sub_confirmation=1" target="_blank">
|
||||
<div class="text-black bg-warning shadow-sm rounded">
|
||||
<i class="fa fa-youtube-play fa-4x py-0"></i>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
<section class="oe_container" style="font-family: 'Montserrat', 'Odoo Unicode Support Noto', sans-serif;">
|
||||
<div class="row mt-5 mb-4 align-items-center">
|
||||
|
||||
<div class="col-6 text-left">Version: 14.0.2.3.2</div>
|
||||
<div class="col-6 text-right" style="text-align: right;"><small>Module design is reserved</small> | Copyright © <a href="https://garazd.biz/" target="_blank">Garazd Creation</a></div>
|
||||
|
||||
|
||||
<section class="oe_container col-12 mt-5" style="font-family: 'Montserrat','Odoo Unicode Support Noto',sans-serif; line-height: 1.75rem;">
|
||||
<div class="h2 text-left ml8 mr32" style="color: #FEA621;"><i class="fa fa-code-fork mr8"></i>Changelog</div>
|
||||
<div class="media p-2 pt-4" style="border-color:#FEA621 !important; border-radius: 15px; border: solid;">
|
||||
<small class="media-body">
|
||||
|
||||
<ul class="list-unstyled">
|
||||
<li class="media">
|
||||
|
||||
<div class="media-body mb-4">
|
||||
<div class="h5 ml32 my-1" style="font-size: 1.0rem;">
|
||||
<span class="font-weight-bold bg-dark text-white rounded py-1 px-3">14.0.2.3.2</span>
|
||||
<span class="text-muted ml16">2024-10-26</span>
|
||||
</div>
|
||||
<ul class="mt-2">
|
||||
<li class="mx-3"><small>Add method to get PDF.</small></li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
<li class="media">
|
||||
|
||||
<div class="media-body mb-4">
|
||||
<div class="h5 ml32 my-1" style="font-size: 1.0rem;">
|
||||
<span class="font-weight-bold bg-dark text-white rounded py-1 px-3">14.0.2.3.1</span>
|
||||
<span class="text-muted ml16">2024-08-17</span>
|
||||
</div>
|
||||
<ul class="mt-2">
|
||||
<li class="mx-3"><small>Add UA translations.</small></li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
<li class="media">
|
||||
|
||||
<div class="media-body mb-4">
|
||||
<div class="h5 ml32 my-1" style="font-size: 1.0rem;">
|
||||
<span class="font-weight-bold bg-dark text-white rounded py-1 px-3">14.0.2.3.0</span>
|
||||
<span class="text-muted ml16">2023-11-18</span>
|
||||
</div>
|
||||
<ul class="mt-2">
|
||||
<li class="mx-3"><small>Improve getting of labels to print, add excluding of lines with qty=0.</small></li>
|
||||
<li class="mx-3"><small>Add the "mode" option for technical purposes.</small></li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
<li class="media">
|
||||
|
||||
<div class="media-body mb-4">
|
||||
<div class="h5 ml32 my-1" style="font-size: 1.0rem;">
|
||||
<span class="font-weight-bold bg-dark text-white rounded py-1 px-3">14.0.2.2.0</span>
|
||||
<span class="text-muted ml16">2023-11-16</span>
|
||||
</div>
|
||||
<ul class="mt-2">
|
||||
<li class="mx-3"><small>Implement sorting of label lines by a product.</small></li>
|
||||
<li class="mx-3"><small>Add the sequence for the label lines.</small></li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
<li class="media">
|
||||
|
||||
<div class="media-body mb-4">
|
||||
<div class="h5 ml32 my-1" style="font-size: 1.0rem;">
|
||||
<span class="font-weight-bold bg-dark text-white rounded py-1 px-3">14.0.2.1.0</span>
|
||||
<span class="text-muted ml16">2023-09-19</span>
|
||||
</div>
|
||||
<ul class="mt-2">
|
||||
<li class="mx-3"><small>Add the settings section "Product Labels".</small></li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
<li class="media">
|
||||
|
||||
<div class="media-body mb-4">
|
||||
<div class="h5 ml32 my-1" style="font-size: 1.0rem;">
|
||||
<span class="font-weight-bold bg-dark text-white rounded py-1 px-3">14.0.2.0.0</span>
|
||||
<span class="text-muted ml16">2023-04-06</span>
|
||||
</div>
|
||||
<ul class="mt-2">
|
||||
<li class="mx-3"><small>Add a product label template 50x38 mm.</small></li>
|
||||
<li class="mx-3"><small>Improve product demo data.</small></li>
|
||||
<li class="mx-3"><small>Implement a new logic for print wizard.</small></li>
|
||||
<li class="mx-3"><small>Add a company selection to the wizard.</small></li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
<li class="media">
|
||||
|
||||
<div class="media-body mb-4">
|
||||
<div class="h5 ml32 my-1" style="font-size: 1.0rem;">
|
||||
<span class="font-weight-bold bg-dark text-white rounded py-1 px-3">14.0.1.2.0</span>
|
||||
<span class="text-muted ml16">2022-12-19</span>
|
||||
</div>
|
||||
<ul class="mt-2">
|
||||
<li class="mx-3"><small>Add the option "Language" to translate product names.</small></li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
<li class="media">
|
||||
|
||||
<div class="media-body mb-4">
|
||||
<div class="h5 ml32 my-1" style="font-size: 1.0rem;">
|
||||
<span class="font-weight-bold bg-dark text-white rounded py-1 px-3">14.0.1.1.1</span>
|
||||
<span class="text-muted ml16">2022-06-22</span>
|
||||
</div>
|
||||
<ul class="mt-2">
|
||||
<li class="mx-3"><small>Add method "_get_label_to_print" to define actual product lines.</small></li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
<li class="media">
|
||||
|
||||
<div class="media-body mb-4">
|
||||
<div class="h5 ml32 my-1" style="font-size: 1.0rem;">
|
||||
<span class="font-weight-bold bg-dark text-white rounded py-1 px-3">14.0.1.1.0</span>
|
||||
<span class="text-muted ml16">2022-06-20</span>
|
||||
</div>
|
||||
<ul class="mt-2">
|
||||
<li class="mx-3"><small>Add the option "Border" to define a border width on multi labels on A4, US letter paper formats.</small></li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
<li class="media">
|
||||
|
||||
<div class="media-body mb-4">
|
||||
<div class="h5 ml32 my-1" style="font-size: 1.0rem;">
|
||||
<span class="font-weight-bold bg-dark text-white rounded py-1 px-3">14.0.1.0.3</span>
|
||||
<span class="text-muted ml16">2021-12-18</span>
|
||||
</div>
|
||||
<ul class="mt-2">
|
||||
<li class="mx-3"><small>Add barcode types in the 57x35 label template</small></li>
|
||||
<li class="mx-3"><small>Add currency symbol position before/after in the 57x35 label template</small></li>
|
||||
<li class="mx-3"><small>Add option Humanreadable barcode to the wizard</small></li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
<li class="media">
|
||||
|
||||
<div class="media-body mb-4">
|
||||
<div class="h5 ml32 my-1" style="font-size: 1.0rem;">
|
||||
<span class="font-weight-bold bg-dark text-white rounded py-1 px-3">14.0.1.0.2</span>
|
||||
<span class="text-muted ml16">2021-05-31</span>
|
||||
</div>
|
||||
<ul class="mt-2">
|
||||
<li class="mx-3"><small>Fix save_eval error: NameError: name Product_labels_57x35mm is not defined</small></li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
<li class="media">
|
||||
|
||||
<div class="media-body mb-4">
|
||||
<div class="h5 ml32 my-1" style="font-size: 1.0rem;">
|
||||
<span class="font-weight-bold bg-dark text-white rounded py-1 px-3">14.0.1.0.1</span>
|
||||
<span class="text-muted ml16">2021-03-28</span>
|
||||
</div>
|
||||
<ul class="mt-2">
|
||||
<li class="mx-3"><small>change print_report_name (spaces removed)</small></li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
<li class="media">
|
||||
|
||||
<div class="media-body mb-4">
|
||||
<div class="h5 ml32 my-1" style="font-size: 1.0rem;">
|
||||
<span class="font-weight-bold bg-dark text-white rounded py-1 px-3">14.0.1.0.0</span>
|
||||
<span class="text-muted ml16">2021-02-18</span>
|
||||
</div>
|
||||
<ul class="mt-2">
|
||||
<li class="mx-3"><small>Migrate to 14.0</small></li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
</small>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="oe_container" style="font-family: 'Montserrat','Odoo Unicode Support Noto',sans-serif;">
|
||||
<div class="container" id="odoo-app-rating">
|
||||
<div class="row my-4 py-3 bg-light" style="padding: 12px 28px; border-radius: 0 0 15px 15px;">
|
||||
<div class="col d-flex justify-content-center text-center" style="color: #FEA621;">
|
||||
<i class="fa fa-fw fa-thumbs-o-up fa-4x"></i>
|
||||
<span class="my-auto mx-5 display-4">
|
||||
<a href="https://apps.odoo.com/apps/modules/14.0/garazd_product_label/#odoo-app-rating" class="btn btn-lg btn-warning text-white rounded">Rate the app</a>
|
||||
- support us to do more!
|
||||
</span>
|
||||
<i class="fa fa-fw fa-angle-double-down fa-4x"></i>
|
||||
</div>
|
||||
<div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
After Width: | Height: | Size: 75 KiB |
|
After Width: | Height: | Size: 8.7 KiB |
|
After Width: | Height: | Size: 120 KiB |
|
After Width: | Height: | Size: 124 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 223 KiB |
|
After Width: | Height: | Size: 161 KiB |
|
After Width: | Height: | Size: 111 KiB |
|
After Width: | Height: | Size: 111 KiB |
|
After Width: | Height: | Size: 111 KiB |
|
After Width: | Height: | Size: 68 KiB |
|
After Width: | Height: | Size: 191 KiB |
|
After Width: | Height: | Size: 86 KiB |
@@ -0,0 +1 @@
|
||||
from . import test_print_product_label
|
||||
@@ -0,0 +1,67 @@
|
||||
from odoo.tests.common import TransactionCase
|
||||
from odoo.tools import test_reports
|
||||
|
||||
|
||||
class TestPrintProductLabel(TransactionCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestPrintProductLabel, self).setUp()
|
||||
self.product_chair = self.env.ref('product.product_product_12')
|
||||
self.product_drawer = self.env.ref('product.product_product_27')
|
||||
|
||||
def test_print_wizard(self):
|
||||
ctx = {
|
||||
'active_model': 'product.product',
|
||||
'default_product_ids': [
|
||||
self.product_chair.id,
|
||||
self.product_drawer.id,
|
||||
],
|
||||
}
|
||||
wizard = self.env['print.product.label'].with_context(**ctx).create({})
|
||||
self.assertEqual(len(wizard.label_ids), 2)
|
||||
|
||||
test_reports.try_report(
|
||||
self.env.cr,
|
||||
self.env.uid,
|
||||
'garazd_product_label.report_product_label_57x35_template',
|
||||
ids=wizard.label_ids.ids,
|
||||
our_module='garazd_product_label'
|
||||
)
|
||||
|
||||
def test_action_product_product_label_print(self):
|
||||
ctx = {
|
||||
'active_model': 'product.product',
|
||||
'active_ids': [
|
||||
self.product_chair.id,
|
||||
self.product_drawer.id,
|
||||
],
|
||||
}
|
||||
data_dict = {}
|
||||
test_reports.try_report_action(
|
||||
self.env.cr,
|
||||
self.env.uid,
|
||||
'action_print_label_from_product',
|
||||
context=ctx,
|
||||
wiz_data=data_dict,
|
||||
wiz_buttons=['action_print'],
|
||||
our_module='garazd_product_label'
|
||||
)
|
||||
|
||||
def test_action_product_template_label_print(self):
|
||||
ctx = {
|
||||
'active_model': 'product.template',
|
||||
'active_ids': [
|
||||
self.product_chair.product_tmpl_id.id,
|
||||
self.product_drawer.product_tmpl_id.id,
|
||||
],
|
||||
}
|
||||
data_dict = {}
|
||||
test_reports.try_report_action(
|
||||
self.env.cr,
|
||||
self.env.uid,
|
||||
'action_print_label_from_template',
|
||||
context=ctx,
|
||||
wiz_data=data_dict,
|
||||
wiz_buttons=['action_print'],
|
||||
our_module='garazd_product_label'
|
||||
)
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="res_config_settings_view_form" model="ir.ui.view">
|
||||
<field name="name">res.config.settings.view.form.inherit.garazd_product_label</field>
|
||||
<field name="model">res.config.settings</field>
|
||||
<field name="inherit_id" ref="product.res_config_settings_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[@id='product_general_settings']" position="after">
|
||||
<h2>Product Labels</h2>
|
||||
<div class="row mt16 o_settings_container" id="garazd_product_label_setting"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -0,0 +1,2 @@
|
||||
from . import print_product_label_line
|
||||
from . import print_product_label
|
||||
@@ -0,0 +1,165 @@
|
||||
# Copyright © 2018 Garazd Creation (<https://garazd.biz>)
|
||||
# @author: Yurii Razumovskyi (<support@garazd.biz>)
|
||||
# @author: Iryna Razumovska (<support@garazd.biz>)
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.html).
|
||||
|
||||
import base64
|
||||
from typing import List
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.addons.base.models.res_partner import _lang_get
|
||||
|
||||
|
||||
class PrintProductLabel(models.TransientModel):
|
||||
_name = "print.product.label"
|
||||
_description = 'Wizard to print Product Labels'
|
||||
|
||||
@api.model
|
||||
def _complete_label_fields(self, label_ids: List[int]) -> List[int]:
|
||||
"""Set additional fields for product labels. Method to override."""
|
||||
# Increase a label sequence
|
||||
labels = self.env['print.product.label.line'].browse(label_ids)
|
||||
for seq, label in enumerate(labels):
|
||||
label.sequence = 1000 + seq
|
||||
return label_ids
|
||||
|
||||
@api.model
|
||||
def _get_product_label_ids(self):
|
||||
res = []
|
||||
# flake8: noqa: E501
|
||||
if self._context.get('active_model') == 'product.template':
|
||||
products = self.env[self._context.get('active_model')].browse(self._context.get('default_product_ids'))
|
||||
for product in products:
|
||||
label = self.env['print.product.label.line'].create({
|
||||
'product_id': product.product_variant_id.id,
|
||||
})
|
||||
res.append(label.id)
|
||||
elif self._context.get('active_model') == 'product.product':
|
||||
products = self.env[self._context.get('active_model')].browse(self._context.get('default_product_ids'))
|
||||
for product in products:
|
||||
label = self.env['print.product.label.line'].create({
|
||||
'product_id': product.id,
|
||||
})
|
||||
res.append(label.id)
|
||||
res = self._complete_label_fields(res)
|
||||
return res
|
||||
|
||||
name = fields.Char(default=_('Print Product Labels'))
|
||||
message = fields.Char(readonly=True)
|
||||
output = fields.Selection(
|
||||
selection=[('pdf', 'PDF')],
|
||||
string='Print to',
|
||||
default='pdf',
|
||||
)
|
||||
mode = fields.Selection(selection=[], help='Technical field')
|
||||
label_ids = fields.One2many(
|
||||
comodel_name='print.product.label.line',
|
||||
inverse_name='wizard_id',
|
||||
string='Labels for Products',
|
||||
default=_get_product_label_ids,
|
||||
)
|
||||
report_id = fields.Many2one(
|
||||
comodel_name='ir.actions.report',
|
||||
string='Label',
|
||||
domain=[('model', '=', 'print.product.label.line')],
|
||||
)
|
||||
is_template_report = fields.Boolean(compute='_compute_is_template_report')
|
||||
qty_per_product = fields.Integer(
|
||||
string='Label quantity per product',
|
||||
default=1,
|
||||
)
|
||||
# Options
|
||||
humanreadable = fields.Boolean(
|
||||
string='Human readable barcode',
|
||||
help='Print digital code of barcode.',
|
||||
default=False,
|
||||
)
|
||||
border_width = fields.Integer(
|
||||
string='Border',
|
||||
help='Border width for labels (in pixels). Set "0" for no border.'
|
||||
)
|
||||
lang = fields.Selection(
|
||||
selection=_lang_get,
|
||||
string='Language',
|
||||
help="The language that will be used to translate label names.",
|
||||
)
|
||||
company_id = fields.Many2one(
|
||||
comodel_name='res.company',
|
||||
help='Specify a company for product labels.'
|
||||
)
|
||||
|
||||
@api.depends('report_id')
|
||||
def _compute_is_template_report(self):
|
||||
for wizard in self:
|
||||
# flake8: noqa: E501
|
||||
wizard.is_template_report = self.report_id == self.env.ref('garazd_product_label.action_report_product_label_from_template')
|
||||
|
||||
def get_labels_to_print(self):
|
||||
self.ensure_one()
|
||||
labels = self.label_ids.filtered(lambda l: l.selected and l.qty)
|
||||
if not labels:
|
||||
raise UserError(
|
||||
_('Nothing to print, set the quantity of labels in the table.'))
|
||||
return labels
|
||||
|
||||
def _get_report_action_params(self):
|
||||
"""Return two params for a report action: record "ids" and "data"."""
|
||||
self.ensure_one()
|
||||
return self.get_labels_to_print().ids, None
|
||||
|
||||
def _prepare_report(self):
|
||||
self.ensure_one()
|
||||
mode = self._context.get('print_mode', 'pdf')
|
||||
if not self.report_id:
|
||||
raise UserError(_('Please select a label type.'))
|
||||
report = self.report_id.with_context(discard_logo_check=True, lang=self.lang)
|
||||
report.sudo().write({'report_type': f'qweb-{mode}'})
|
||||
return report
|
||||
|
||||
def action_print(self):
|
||||
"""Print labels."""
|
||||
self.ensure_one()
|
||||
report = self._prepare_report()
|
||||
return report.report_action(*self._get_report_action_params())
|
||||
|
||||
def action_set_qty(self):
|
||||
"""Set a specific number of labels for all lines."""
|
||||
self.ensure_one()
|
||||
self.label_ids.write({'qty': self.qty_per_product})
|
||||
|
||||
def action_restore_initial_qty(self):
|
||||
"""Restore the initial number of labels for all lines."""
|
||||
self.ensure_one()
|
||||
for label in self.label_ids:
|
||||
if label.qty_initial:
|
||||
label.update({'qty': label.qty_initial})
|
||||
|
||||
@api.model
|
||||
def _set_sequence(self, lbl, seq, processed):
|
||||
if lbl in processed:
|
||||
return seq, processed
|
||||
lbl.sequence = seq
|
||||
seq += 1
|
||||
processed += lbl
|
||||
return seq, processed
|
||||
|
||||
def action_sort_by_product(self):
|
||||
self.ensure_one()
|
||||
sequence = 1000
|
||||
processed_labels = self.env['print.product.label.line'].browse()
|
||||
# flake8: noqa: E501
|
||||
for label in self.label_ids:
|
||||
sequence, processed_labels = self._set_sequence(label, sequence, processed_labels)
|
||||
tmpl_labels = self.label_ids.filtered(lambda l: l.product_id.product_tmpl_id == label.product_id.product_tmpl_id).sorted(lambda l: l.product_id.id, reverse=True) - label
|
||||
for tmpl_label in tmpl_labels:
|
||||
sequence, processed_labels = self._set_sequence(tmpl_label, sequence, processed_labels)
|
||||
product_labels = tmpl_labels.filtered(lambda l: l.product_id == label.product_id) - tmpl_label
|
||||
for product_label in product_labels:
|
||||
sequence, processed_labels = self._set_sequence(product_label, sequence, processed_labels)
|
||||
|
||||
def get_pdf(self):
|
||||
self.ensure_one()
|
||||
report = self.with_context(print_mode='pdf')._prepare_report()
|
||||
pdf_data = report._render_qweb_pdf(*self._get_report_action_params())
|
||||
return base64.b64encode(pdf_data[0])
|
||||
@@ -0,0 +1,49 @@
|
||||
# Copyright © 2018 Garazd Creation (<https://garazd.biz>)
|
||||
# @author: Yurii Razumovskyi (<support@garazd.biz>)
|
||||
# @author: Iryna Razumovska (<support@garazd.biz>)
|
||||
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.html).
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class PrintProductLabelLine(models.TransientModel):
|
||||
_name = "print.product.label.line"
|
||||
_description = 'Line with a Product Label Data'
|
||||
_order = 'sequence'
|
||||
|
||||
sequence = fields.Integer(default=900)
|
||||
selected = fields.Boolean(string='Print', default=True)
|
||||
wizard_id = fields.Many2one(comodel_name='print.product.label') # Not make required
|
||||
product_id = fields.Many2one(comodel_name='product.product', required=True)
|
||||
barcode = fields.Char(compute='_compute_barcode')
|
||||
qty_initial = fields.Integer(string='Initial Qty', default=1)
|
||||
qty = fields.Integer(string='Label Qty', default=1)
|
||||
company_id = fields.Many2one(
|
||||
comodel_name='res.company',
|
||||
compute='_compute_company_id',
|
||||
)
|
||||
|
||||
@api.depends('wizard_id.company_id')
|
||||
def _compute_company_id(self):
|
||||
for label in self:
|
||||
label.company_id = \
|
||||
label.wizard_id.company_id and label.wizard_id.company_id.id \
|
||||
or self.env.user.company_id.id
|
||||
|
||||
@api.depends('product_id')
|
||||
def _compute_barcode(self):
|
||||
for label in self:
|
||||
label.barcode = label.product_id.barcode
|
||||
|
||||
def action_plus_qty(self):
|
||||
self.ensure_one()
|
||||
if not self.qty:
|
||||
self.update({'selected': True})
|
||||
self.update({'qty': self.qty + 1})
|
||||
|
||||
def action_minus_qty(self):
|
||||
self.ensure_one()
|
||||
if self.qty > 0:
|
||||
self.update({'qty': self.qty - 1})
|
||||
if not self.qty:
|
||||
self.update({'selected': False})
|
||||
@@ -0,0 +1,104 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="print_product_label_view_form" model="ir.ui.view">
|
||||
<field name="name">print.product.label.view.form</field>
|
||||
<field name="model">print.product.label</field>
|
||||
<field name="arch" type="xml">
|
||||
<form create="false" string="Print Product Labels">
|
||||
<header>
|
||||
<button name="action_print"
|
||||
string="Print"
|
||||
help="Print product labels"
|
||||
type="object"
|
||||
icon="fa-print"
|
||||
class="btn-primary mr8"/>
|
||||
<button name="action_print"
|
||||
string="Preview"
|
||||
context="{'print_mode': 'html'}"
|
||||
help="Preview product labels"
|
||||
type="object"
|
||||
icon="fa-search"
|
||||
class="btn-secondary mr8"/>
|
||||
</header>
|
||||
<div class="oe_button_box mb-0" name="button_box"/>
|
||||
<field name="mode" invisible="1"/>
|
||||
<field name="is_template_report" invisible="1"/>
|
||||
<div class="alert alert-info text-center mb-3"
|
||||
attrs="{'invisible':[('message', '=', False)]}"
|
||||
role="alert">
|
||||
<field name="message"/>
|
||||
</div>
|
||||
<group col="6" colspan="2">
|
||||
<group string="Output" name="output_format" col="1" colspan="1">
|
||||
<field name="output" widget="badge"/>
|
||||
</group>
|
||||
<group string="Label" name="label_report" col="2" colspan="2">
|
||||
<field name="report_id" string="Label" widget="radio" nolabel="1"/>
|
||||
</group>
|
||||
<group string="Template" name="label_template" col="2" colspan="3" attrs="{'invisible': [('is_template_report', '=', False)]}">
|
||||
<a name="label_builder_link" attrs="{'invisible': [('is_template_report', '=', False)]}" href="https://garazd.biz/r/LfW" title="How to get Product Label Builder" target="_blank" rel="noopener noreferrer">
|
||||
<span>Get the Label Builder to create your own labels</span>
|
||||
</a>
|
||||
</group>
|
||||
</group>
|
||||
<div name="extra_action" class="oe_row">
|
||||
<button name="action_sort_by_product" title="Sort labels by a product" icon="fa-sort-amount-desc" type="object" class="btn-xs btn-light"/>
|
||||
<span class="text-muted px-3">|</span>
|
||||
<field name="qty_per_product" class="mr-2 mt-1 text-right" help="Label quantity per product" style="width: 40px !important;"/>
|
||||
<button name="action_set_qty" string="Set quantity" help="Set a certain quantity for each line." type="object" class="btn-xs btn-light mr-2"/>
|
||||
<button name="action_restore_initial_qty" title="Restore initial quantity" help="Restore initial quantity" icon="fa-undo" type="object" class="btn-xs btn-light"/>
|
||||
</div>
|
||||
<notebook>
|
||||
<page string="Labels" name="labels">
|
||||
<field name="label_ids" mode="tree">
|
||||
<tree editable="top" decoration-muted="qty==0">
|
||||
<field name="sequence" widget="handle" width="0.5"/>
|
||||
<field name="selected" widget="boolean_toggle"/>
|
||||
<field name="product_id"/>
|
||||
<field name="barcode" optional="show"/>
|
||||
<field name="company_id" groups="base.group_multi_company" optional="hide"/>
|
||||
<button name="action_minus_qty" type="object" title="Decrease Qty" icon="fa-minus" class="btn-light"/>
|
||||
<field name="qty" sum="Total" width="0.6" class="text-center font-weight-bold"/>
|
||||
<button name="action_plus_qty" type="object" title="Increase Qty" icon="fa-plus" class="btn-light"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
<page string="Options" name="options">
|
||||
<group name="general_options" class="o_label_nowrap">
|
||||
<group>
|
||||
<field name="lang" widget="radio" options="{'horizontal': true}"/>
|
||||
<field name="humanreadable" widget="boolean_toggle" />
|
||||
<field name="border_width" />
|
||||
</group>
|
||||
<group>
|
||||
<field name="company_id" widget="radio" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_print_label_from_template" model="ir.actions.act_window">
|
||||
<field name="name">Custom Product Labels</field>
|
||||
<field name="res_model">print.product.label</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">current</field>
|
||||
<field name="context">{'default_product_ids': active_ids}</field>
|
||||
<field name="binding_model_id" ref="product.model_product_template"/>
|
||||
<field name="binding_type">report</field>
|
||||
</record>
|
||||
|
||||
<record id="action_print_label_from_product" model="ir.actions.act_window">
|
||||
<field name="name">Custom Product Labels</field>
|
||||
<field name="res_model">print.product.label</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">current</field>
|
||||
<field name="context">{'default_product_ids': active_ids}</field>
|
||||
<field name="binding_model_id" ref="product.model_product_product"/>
|
||||
<field name="binding_type">report</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
'name': 'SCADA for Odoo - Manufacturing Integration',
|
||||
'version': '3.0.30',
|
||||
'version': '4.0.31',
|
||||
'category': 'manufacturing',
|
||||
'license': 'LGPL-3',
|
||||
'author': 'PT. Gagak Rimang Teknologi',
|
||||
@@ -30,9 +30,13 @@
|
||||
'views/scada_mrp_views.xml',
|
||||
'views/scada_sensor_reading_view.xml',
|
||||
'views/scada_api_log_view.xml',
|
||||
'views/scada_quality_control_view.xml',
|
||||
'views/scada_equipment_oee_view.xml',
|
||||
'views/menu.xml',
|
||||
'data/demo_data.xml',
|
||||
'data/ir_cron.xml',
|
||||
'reports/scada_quality_control_report.xml',
|
||||
'reports/scada_equipment_oee_report.xml',
|
||||
],
|
||||
'demo': [
|
||||
'data/demo_data.xml',
|
||||
|
||||
@@ -3,10 +3,12 @@ from . import scada_equipment
|
||||
from . import scada_material_consumption
|
||||
from . import scada_mo_weight
|
||||
from . import scada_equipment_material
|
||||
from . import scada_equipment_oee
|
||||
from . import scada_sensor_reading
|
||||
from . import scada_api_log
|
||||
from . import scada_health
|
||||
from . import scada_module
|
||||
from . import scada_quality_control
|
||||
from . import mrp_bom
|
||||
from . import mrp_production
|
||||
from . import mrp_bom_line
|
||||
|
||||
@@ -31,3 +31,20 @@ class MrpProduction(models.Model):
|
||||
if bom and bom.scada_equipment_id:
|
||||
vals['scada_equipment_id'] = bom.scada_equipment_id.id
|
||||
return super().create(vals_list)
|
||||
|
||||
def button_mark_done(self):
|
||||
res = super().button_mark_done()
|
||||
oee_model = self.env['scada.equipment.oee']
|
||||
|
||||
for mo in self:
|
||||
if mo.state != 'done':
|
||||
continue
|
||||
equipment = mo.scada_equipment_id or (mo.bom_id.scada_equipment_id if mo.bom_id else False)
|
||||
if not equipment:
|
||||
continue
|
||||
if oee_model.search([('manufacturing_order_id', '=', mo.id)], limit=1):
|
||||
continue
|
||||
vals = oee_model.prepare_from_mo(mo, equipment)
|
||||
oee_model.create(vals)
|
||||
|
||||
return res
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from odoo import models, fields
|
||||
|
||||
|
||||
class ScadaEquipmentOee(models.Model):
|
||||
_name = 'scada.equipment.oee'
|
||||
_description = 'SCADA Equipment OEE Summary'
|
||||
_order = 'date_done desc, id desc'
|
||||
_rec_name = 'mo_name'
|
||||
|
||||
manufacturing_order_id = fields.Many2one(
|
||||
'mrp.production',
|
||||
string='Manufacturing Order',
|
||||
required=True,
|
||||
ondelete='restrict'
|
||||
)
|
||||
mo_name = fields.Char(
|
||||
string='MO Name',
|
||||
related='manufacturing_order_id.name',
|
||||
store=True,
|
||||
readonly=True
|
||||
)
|
||||
equipment_id = fields.Many2one(
|
||||
'scada.equipment',
|
||||
string='Equipment',
|
||||
required=True,
|
||||
ondelete='restrict'
|
||||
)
|
||||
product_id = fields.Many2one(
|
||||
'product.product',
|
||||
string='Product',
|
||||
related='manufacturing_order_id.product_id',
|
||||
store=True,
|
||||
readonly=True
|
||||
)
|
||||
date_done = fields.Datetime(
|
||||
string='Done Date',
|
||||
default=fields.Datetime.now,
|
||||
required=True
|
||||
)
|
||||
|
||||
qty_planned = fields.Float(
|
||||
string='Planned Qty (BoM)',
|
||||
digits=(12, 3)
|
||||
)
|
||||
qty_finished = fields.Float(
|
||||
string='Actual Finished Qty',
|
||||
digits=(12, 3)
|
||||
)
|
||||
qty_bom_consumption = fields.Float(
|
||||
string='BoM Consumption (Total)',
|
||||
digits=(12, 3)
|
||||
)
|
||||
qty_actual_consumption = fields.Float(
|
||||
string='Actual Consumption (Total)',
|
||||
digits=(12, 3)
|
||||
)
|
||||
|
||||
variance_finished = fields.Float(
|
||||
string='Finished Variance',
|
||||
digits=(12, 3)
|
||||
)
|
||||
variance_consumption = fields.Float(
|
||||
string='Consumption Variance',
|
||||
digits=(12, 3)
|
||||
)
|
||||
|
||||
yield_percent = fields.Float(
|
||||
string='Yield %',
|
||||
digits=(16, 3)
|
||||
)
|
||||
consumption_ratio = fields.Float(
|
||||
string='Consumption Ratio %',
|
||||
digits=(16, 3)
|
||||
)
|
||||
|
||||
notes = fields.Text(string='Notes')
|
||||
|
||||
company_id = fields.Many2one(
|
||||
'res.company',
|
||||
string='Company',
|
||||
default=lambda self: self.env.company
|
||||
)
|
||||
|
||||
_sql_constraints = [
|
||||
('mo_unique', 'unique(manufacturing_order_id)',
|
||||
'OEE summary already exists for this manufacturing order.')
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
def _safe_ratio(numerator, denominator):
|
||||
return (numerator / denominator * 100.0) if denominator else 0.0
|
||||
|
||||
@classmethod
|
||||
def prepare_from_mo(cls, mo, equipment):
|
||||
finished_qty = sum(
|
||||
move.quantity_done for move in mo.move_finished_ids
|
||||
if move.state != 'cancel'
|
||||
)
|
||||
actual_consumed = sum(
|
||||
move.quantity_done for move in mo.move_raw_ids
|
||||
if move.state != 'cancel'
|
||||
)
|
||||
|
||||
bom_consumption = 0.0
|
||||
if mo.bom_id and mo.bom_id.product_qty:
|
||||
for line in mo.bom_id.bom_line_ids:
|
||||
bom_consumption += (
|
||||
(line.product_qty / mo.bom_id.product_qty) * mo.product_qty
|
||||
)
|
||||
|
||||
planned_qty = mo.product_qty or 0.0
|
||||
variance_finished = finished_qty - planned_qty
|
||||
variance_consumption = actual_consumed - bom_consumption
|
||||
|
||||
return {
|
||||
'manufacturing_order_id': mo.id,
|
||||
'equipment_id': equipment.id,
|
||||
'date_done': mo.date_finished or mo.date_planned_finished or fields.Datetime.now(),
|
||||
'qty_planned': planned_qty,
|
||||
'qty_finished': finished_qty,
|
||||
'qty_bom_consumption': bom_consumption,
|
||||
'qty_actual_consumption': actual_consumed,
|
||||
'variance_finished': variance_finished,
|
||||
'variance_consumption': variance_consumption,
|
||||
'yield_percent': cls._safe_ratio(finished_qty, planned_qty),
|
||||
'consumption_ratio': cls._safe_ratio(actual_consumed, bom_consumption),
|
||||
'company_id': mo.company_id.id,
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from odoo import models, fields
|
||||
|
||||
|
||||
class ScadaQualityControl(models.Model):
|
||||
_name = 'scada.quality.control'
|
||||
_description = 'SCADA Quality Control'
|
||||
_order = 'tanggal_uji desc, id desc'
|
||||
_rec_name = 'kode'
|
||||
|
||||
product_id = fields.Many2one(
|
||||
'product.product',
|
||||
string='Product',
|
||||
required=True,
|
||||
ondelete='restrict'
|
||||
)
|
||||
product_name = fields.Char(
|
||||
string='Product Name',
|
||||
related='product_id.name',
|
||||
store=True,
|
||||
readonly=True
|
||||
)
|
||||
kode = fields.Char(string='Kode', required=True, index=True)
|
||||
|
||||
quantity = fields.Float(
|
||||
string='Quantity',
|
||||
digits='Product Unit of Measure',
|
||||
required=True
|
||||
)
|
||||
uom_id = fields.Many2one(
|
||||
'uom.uom',
|
||||
string='Unit of Measure',
|
||||
related='product_id.uom_id',
|
||||
store=True,
|
||||
readonly=True
|
||||
)
|
||||
|
||||
qc_type = fields.Selection([
|
||||
('raw', 'Raw Material'),
|
||||
('finished', 'Finished Goods')
|
||||
], string='QC Type', required=True, default='finished')
|
||||
|
||||
lot_id = fields.Many2one(
|
||||
'stock.production.lot',
|
||||
string='Lot/Serial Number'
|
||||
)
|
||||
|
||||
warna = fields.Boolean(string='Warna', default=False)
|
||||
aroma = fields.Boolean(string='Aroma', default=False)
|
||||
tekstur = fields.Boolean(string='Tekstur', default=False)
|
||||
pest = fields.Boolean(string='Pest', default=False)
|
||||
kemasan = fields.Boolean(string='Kemasan', default=False)
|
||||
jahitan = fields.Boolean(string='Jahitan', default=False)
|
||||
label = fields.Boolean(string='Label', default=False)
|
||||
|
||||
density = fields.Float(string='Density', digits=(16, 3))
|
||||
ka_output = fields.Float(string='KA Output', digits=(16, 3))
|
||||
ka_output_max = fields.Float(string='KA Output Max', digits=(16, 3))
|
||||
|
||||
suhu_ruang = fields.Float(string='Suhu Ruang')
|
||||
suhu_produk = fields.Float(string='Suhu Produk')
|
||||
|
||||
umur_barang = fields.Float(string='Umur Barang')
|
||||
umur_simpan = fields.Float(string='Umur Simpan')
|
||||
|
||||
ka_supply = fields.Float(string='KA Supply', digits=(16, 3))
|
||||
ka_supply_max = fields.Float(string='KA Supply Max', digits=(16, 3))
|
||||
|
||||
kadar_air = fields.Float(string='Kadar Air', digits=(16, 3))
|
||||
ka_process_max = fields.Float(string='KA Process Max', digits=(16, 3))
|
||||
|
||||
tanggal_uji = fields.Date(
|
||||
string='Tanggal Uji',
|
||||
default=fields.Date.context_today,
|
||||
required=True
|
||||
)
|
||||
|
||||
company_id = fields.Many2one(
|
||||
'res.company',
|
||||
string='Company',
|
||||
default=lambda self: self.env.company
|
||||
)
|
||||
@@ -0,0 +1,72 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<report
|
||||
id="report_scada_equipment_oee"
|
||||
model="scada.equipment.oee"
|
||||
string="OEE Summary"
|
||||
report_type="qweb-pdf"
|
||||
name="grt_scada.report_scada_equipment_oee"
|
||||
file="grt_scada.report_scada_equipment_oee"
|
||||
print_report_name="'OEE - %s' % (object.manufacturing_order_id.name or '')"
|
||||
/>
|
||||
|
||||
<template id="report_scada_equipment_oee_document">
|
||||
<t t-call="web.external_layout">
|
||||
<t t-foreach="docs" t-as="o">
|
||||
<div class="page">
|
||||
<h2>Equipment OEE Summary</h2>
|
||||
<table class="table table-sm">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Date Done</th>
|
||||
<td><span t-esc="o.date_done"/></td>
|
||||
<th>Equipment</th>
|
||||
<td><span t-esc="o.equipment_id.name"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>MO</th>
|
||||
<td><span t-esc="o.manufacturing_order_id.name"/></td>
|
||||
<th>Product</th>
|
||||
<td><span t-esc="o.product_id.display_name"/></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h3>Finished Quantity</h3>
|
||||
<table class="table table-sm">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Planned</th><td><span t-esc="o.qty_planned"/></td>
|
||||
<th>Actual</th><td><span t-esc="o.qty_finished"/></td>
|
||||
<th>Variance</th><td><span t-esc="o.variance_finished"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Yield %</th><td><span t-esc="o.yield_percent"/></td>
|
||||
<th></th><td></td>
|
||||
<th></th><td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h3>Consumption</h3>
|
||||
<table class="table table-sm">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>BoM Total</th><td><span t-esc="o.qty_bom_consumption"/></td>
|
||||
<th>Actual Total</th><td><span t-esc="o.qty_actual_consumption"/></td>
|
||||
<th>Variance</th><td><span t-esc="o.variance_consumption"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Ratio %</th><td><span t-esc="o.consumption_ratio"/></td>
|
||||
<th></th><td></td>
|
||||
<th></th><td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
</data>
|
||||
</odoo>
|
||||
@@ -0,0 +1,93 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<report
|
||||
id="report_scada_quality_control"
|
||||
model="scada.quality.control"
|
||||
string="QC Report"
|
||||
report_type="qweb-pdf"
|
||||
name="grt_scada.report_scada_quality_control"
|
||||
file="grt_scada.report_scada_quality_control"
|
||||
print_report_name="'QC - %s' % (object.kode or '')"
|
||||
/>
|
||||
|
||||
<template id="report_scada_quality_control_document">
|
||||
<t t-call="web.external_layout">
|
||||
<t t-foreach="docs" t-as="o">
|
||||
<div class="page">
|
||||
<h2>Quality Control Report</h2>
|
||||
<table class="table table-sm">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<td><span t-esc="o.tanggal_uji"/></td>
|
||||
<th>QC Type</th>
|
||||
<td><span t-esc="o.qc_type"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Product</th>
|
||||
<td><span t-esc="o.product_id.display_name"/></td>
|
||||
<th>Code</th>
|
||||
<td><span t-esc="o.kode"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Quantity</th>
|
||||
<td><span t-esc="o.quantity"/> <span t-esc="o.uom_id.name"/></td>
|
||||
<th>Lot/Serial</th>
|
||||
<td><span t-esc="o.lot_id.name"/></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h3>Visual</h3>
|
||||
<table class="table table-sm">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Warna</th><td><span t-esc="'OK' if o.warna else 'NG'"/></td>
|
||||
<th>Aroma</th><td><span t-esc="'OK' if o.aroma else 'NG'"/></td>
|
||||
<th>Tekstur</th><td><span t-esc="'OK' if o.tekstur else 'NG'"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Pest</th><td><span t-esc="'OK' if o.pest else 'NG'"/></td>
|
||||
<th>Kemasan</th><td><span t-esc="'OK' if o.kemasan else 'NG'"/></td>
|
||||
<th>Jahitan</th><td><span t-esc="'OK' if o.jahitan else 'NG'"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Label</th><td><span t-esc="'OK' if o.label else 'NG'"/></td>
|
||||
<th></th><td></td>
|
||||
<th></th><td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h3>Kualitas</h3>
|
||||
<table class="table table-sm">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Density</th><td><span t-esc="o.density"/></td>
|
||||
<th>KA Output</th><td><span t-esc="o.ka_output"/></td>
|
||||
<th>KA Output Max</th><td><span t-esc="o.ka_output_max"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>KA Supply</th><td><span t-esc="o.ka_supply"/></td>
|
||||
<th>KA Supply Max</th><td><span t-esc="o.ka_supply_max"/></td>
|
||||
<th>Kadar Air</th><td><span t-esc="o.kadar_air"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>KA Process Max</th><td><span t-esc="o.ka_process_max"/></td>
|
||||
<th>Suhu Ruang</th><td><span t-esc="o.suhu_ruang"/></td>
|
||||
<th>Suhu Produk</th><td><span t-esc="o.suhu_produk"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Umur Barang</th><td><span t-esc="o.umur_barang"/></td>
|
||||
<th>Umur Simpan</th><td><span t-esc="o.umur_simpan"/></td>
|
||||
<th></th><td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
</data>
|
||||
</odoo>
|
||||
@@ -13,3 +13,9 @@ access_scada_equipment_material_technician,scada.equipment.material Technician,m
|
||||
access_scada_mo_weight_manager,scada.mo.weight Manager,model_scada_mo_weight,group_scada_manager,1,1,1,1
|
||||
access_scada_mo_weight_operator,scada.mo.weight Operator,model_scada_mo_weight,group_scada_operator,1,0,0,0
|
||||
access_scada_mo_weight_technician,scada.mo.weight Technician,model_scada_mo_weight,group_scada_technician,1,1,0,0
|
||||
access_scada_quality_control_manager,scada.quality.control Manager,model_scada_quality_control,group_scada_manager,1,1,1,1
|
||||
access_scada_quality_control_operator,scada.quality.control Operator,model_scada_quality_control,group_scada_operator,1,1,1,0
|
||||
access_scada_quality_control_technician,scada.quality.control Technician,model_scada_quality_control,group_scada_technician,1,1,1,0
|
||||
access_scada_equipment_oee_manager,scada.equipment.oee Manager,model_scada_equipment_oee,group_scada_manager,1,1,1,1
|
||||
access_scada_equipment_oee_operator,scada.equipment.oee Operator,model_scada_equipment_oee,group_scada_operator,1,1,1,0
|
||||
access_scada_equipment_oee_technician,scada.equipment.oee Technician,model_scada_equipment_oee,group_scada_technician,1,1,1,0
|
||||
|
||||
|
@@ -36,6 +36,34 @@
|
||||
name="Sensor Readings"
|
||||
sequence="1"/>
|
||||
|
||||
<!-- Quality Control Menu -->
|
||||
<menuitem
|
||||
id="menu_scada_quality_control"
|
||||
parent="menu_scada_root"
|
||||
name="Quality Control"
|
||||
sequence="30"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_scada_quality_control_list"
|
||||
parent="menu_scada_quality_control"
|
||||
action="action_scada_quality_control"
|
||||
name="QC Records"
|
||||
sequence="1"/>
|
||||
|
||||
<!-- OEE Summary Menu -->
|
||||
<menuitem
|
||||
id="menu_scada_oee"
|
||||
parent="menu_scada_root"
|
||||
name="OEE Summary"
|
||||
sequence="35"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_scada_oee_list"
|
||||
parent="menu_scada_oee"
|
||||
action="action_scada_equipment_oee"
|
||||
name="OEE Results"
|
||||
sequence="1"/>
|
||||
|
||||
<!-- API Logs Menu -->
|
||||
<menuitem
|
||||
id="menu_scada_logs"
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<!-- OEE Tree View -->
|
||||
<record id="view_scada_equipment_oee_tree" model="ir.ui.view">
|
||||
<field name="name">scada.equipment.oee.tree</field>
|
||||
<field name="model">scada.equipment.oee</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Equipment OEE Summary" default_order="date_done desc">
|
||||
<field name="date_done"/>
|
||||
<field name="equipment_id"/>
|
||||
<field name="manufacturing_order_id"/>
|
||||
<field name="product_id"/>
|
||||
<field name="qty_planned"/>
|
||||
<field name="qty_finished"/>
|
||||
<field name="variance_finished"/>
|
||||
<field name="qty_bom_consumption"/>
|
||||
<field name="qty_actual_consumption"/>
|
||||
<field name="variance_consumption"/>
|
||||
<field name="yield_percent"/>
|
||||
<field name="consumption_ratio"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- OEE Form View -->
|
||||
<record id="view_scada_equipment_oee_form" model="ir.ui.view">
|
||||
<field name="name">scada.equipment.oee.form</field>
|
||||
<field name="model">scada.equipment.oee</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Equipment OEE Summary">
|
||||
<sheet>
|
||||
<group>
|
||||
<group>
|
||||
<field name="date_done"/>
|
||||
<field name="equipment_id"/>
|
||||
<field name="manufacturing_order_id"/>
|
||||
<field name="product_id"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="qty_planned"/>
|
||||
<field name="qty_finished"/>
|
||||
<field name="variance_finished"/>
|
||||
<field name="yield_percent"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Consumption">
|
||||
<group>
|
||||
<group>
|
||||
<field name="qty_bom_consumption"/>
|
||||
<field name="qty_actual_consumption"/>
|
||||
<field name="variance_consumption"/>
|
||||
<field name="consumption_ratio"/>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Notes">
|
||||
<field name="notes" placeholder="Notes..."/>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- OEE Search View -->
|
||||
<record id="view_scada_equipment_oee_search" model="ir.ui.view">
|
||||
<field name="name">scada.equipment.oee.search</field>
|
||||
<field name="model">scada.equipment.oee</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search OEE Summary">
|
||||
<field name="equipment_id"/>
|
||||
<field name="manufacturing_order_id"/>
|
||||
<field name="product_id"/>
|
||||
<field name="date_done"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter string="Equipment" name="group_equipment" context="{'group_by':'equipment_id'}"/>
|
||||
<filter string="Product" name="group_product" context="{'group_by':'product_id'}"/>
|
||||
<filter string="Date" name="group_date" context="{'group_by':'date_done'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- OEE Action -->
|
||||
<record id="action_scada_equipment_oee" model="ir.actions.act_window">
|
||||
<field name="name">Equipment OEE Summary</field>
|
||||
<field name="res_model">scada.equipment.oee</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="search_view_id" ref="view_scada_equipment_oee_search"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
OEE summary will be generated when MO is marked done.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
@@ -0,0 +1,118 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<!-- QC Tree View -->
|
||||
<record id="view_scada_quality_control_tree" model="ir.ui.view">
|
||||
<field name="name">scada.quality.control.tree</field>
|
||||
<field name="model">scada.quality.control</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Quality Control" default_order="tanggal_uji desc">
|
||||
<field name="tanggal_uji"/>
|
||||
<field name="qc_type"/>
|
||||
<field name="product_id"/>
|
||||
<field name="kode"/>
|
||||
<field name="quantity"/>
|
||||
<field name="uom_id"/>
|
||||
<field name="lot_id"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- QC Form View -->
|
||||
<record id="view_scada_quality_control_form" model="ir.ui.view">
|
||||
<field name="name">scada.quality.control.form</field>
|
||||
<field name="model">scada.quality.control</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Quality Control">
|
||||
<sheet>
|
||||
<group>
|
||||
<group>
|
||||
<field name="tanggal_uji"/>
|
||||
<field name="qc_type"/>
|
||||
<field name="product_id"/>
|
||||
<field name="product_name" readonly="1"/>
|
||||
<field name="kode"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="quantity"/>
|
||||
<field name="uom_id" readonly="1"/>
|
||||
<field name="lot_id"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Visual">
|
||||
<group>
|
||||
<field name="warna"/>
|
||||
<field name="aroma"/>
|
||||
<field name="tekstur"/>
|
||||
<field name="pest"/>
|
||||
<field name="kemasan"/>
|
||||
<field name="jahitan"/>
|
||||
<field name="label"/>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Kualitas">
|
||||
<group>
|
||||
<group>
|
||||
<field name="density"/>
|
||||
<field name="ka_output"/>
|
||||
<field name="ka_output_max"/>
|
||||
<field name="ka_supply"/>
|
||||
<field name="ka_supply_max"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="kadar_air"/>
|
||||
<field name="ka_process_max"/>
|
||||
<field name="suhu_ruang"/>
|
||||
<field name="suhu_produk"/>
|
||||
<field name="umur_barang"/>
|
||||
<field name="umur_simpan"/>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- QC Search View -->
|
||||
<record id="view_scada_quality_control_search" model="ir.ui.view">
|
||||
<field name="name">scada.quality.control.search</field>
|
||||
<field name="model">scada.quality.control</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search QC">
|
||||
<field name="kode"/>
|
||||
<field name="product_id"/>
|
||||
<field name="qc_type"/>
|
||||
<field name="tanggal_uji"/>
|
||||
<filter string="Raw Material" name="qc_raw" domain="[('qc_type','=','raw')]"/>
|
||||
<filter string="Finished Goods" name="qc_finished" domain="[('qc_type','=','finished')]"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter string="Product" name="group_product" context="{'group_by':'product_id'}"/>
|
||||
<filter string="QC Type" name="group_type" context="{'group_by':'qc_type'}"/>
|
||||
<filter string="Tanggal Uji" name="group_date" context="{'group_by':'tanggal_uji'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- QC Action -->
|
||||
<record id="action_scada_quality_control" model="ir.actions.act_window">
|
||||
<field name="name">Quality Control</field>
|
||||
<field name="res_model">scada.quality.control</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="search_view_id" ref="view_scada_quality_control_search"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Create your first QC record
|
||||
</p>
|
||||
<p>
|
||||
QC record tracks quality attributes for raw materials and finished goods.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
@@ -0,0 +1,118 @@
|
||||
# Manufacturing Serial Number Module
|
||||
|
||||
## Deskripsi
|
||||
Modul ini menyediakan sistem tracking serial number otomatis untuk produk hasil manufacturing di Odoo 14 Community Edition.
|
||||
|
||||
## Fitur Utama
|
||||
|
||||
### 1. **Auto Generate Serial Number**
|
||||
- Serial number unik dibuat otomatis setiap kali Manufacturing Order selesai
|
||||
- Format: `PREFIX-SEQUENCE-RANDOMCODE` (contoh: `MFG-S000001-A3X9`)
|
||||
- Prefix bisa menggunakan kode produk (Product Reference)
|
||||
|
||||
### 2. **Integrasi dengan Manufacturing Order**
|
||||
- Checkbox "Auto Generate Serial" di Manufacturing Order
|
||||
- Smart button untuk melihat semua serial yang dihasilkan
|
||||
- Tab "Serial Numbers" untuk melihat detail serial
|
||||
- Button manual "Generate Serials Now" jika perlu
|
||||
|
||||
### 3. **Product Configuration**
|
||||
- Field "Use Manufacturing Serial" di Product form
|
||||
- Smart button untuk melihat history serial per produk
|
||||
- Counter jumlah serial yang sudah dihasilkan
|
||||
|
||||
### 4. **Serial Number Management**
|
||||
- State tracking: Draft → Produced → Delivered → Cancelled
|
||||
- Link ke Manufacturing Order
|
||||
- Search & filter berdasarkan product, state, date
|
||||
- Group by product, MO, state, atau date
|
||||
|
||||
### 5. **Security & Access Rights**
|
||||
- MRP User: Read, Write, Create
|
||||
- MRP Manager: Full access termasuk Delete
|
||||
- Stock User: Read only
|
||||
|
||||
## Instalasi
|
||||
|
||||
1. Copy folder `manufacturing_serial_number` ke direktori addons Odoo
|
||||
2. Restart Odoo server
|
||||
3. Aktifkan Developer Mode
|
||||
4. Update Apps List
|
||||
5. Cari "Manufacturing Serial Number" dan klik Install
|
||||
|
||||
## Cara Penggunaan
|
||||
|
||||
### Setup Produk
|
||||
1. Buka **Inventory > Products**
|
||||
2. Pilih produk yang ingin di-track
|
||||
3. Di tab **Inventory**, aktifkan **"Use Manufacturing Serial"**
|
||||
4. Save
|
||||
|
||||
### Menggunakan di Manufacturing
|
||||
1. Buat Manufacturing Order baru
|
||||
2. Pastikan checkbox **"Auto Generate Serial"** aktif
|
||||
3. Process manufacturing order seperti biasa
|
||||
4. Saat klik **"Mark as Done"**, serial numbers akan dibuat otomatis
|
||||
5. Lihat serial numbers di Smart Button atau tab "Serial Numbers"
|
||||
|
||||
### Manual Generate (Opsional)
|
||||
Jika serial belum ter-generate:
|
||||
1. Buka Manufacturing Order yang sudah Done/In Progress
|
||||
2. Klik tab **"Serial Numbers"**
|
||||
3. Klik button **"Generate Serials Now"**
|
||||
|
||||
### Melihat History Serial
|
||||
- **Per Product**: Buka Product → klik Smart Button "Mfg Serials"
|
||||
- **Per MO**: Buka Manufacturing Order → klik Smart Button "Serials"
|
||||
- **All Serials**: Menu Manufacturing > Manufacturing Serials > Serial Numbers
|
||||
|
||||
## Konfigurasi Lanjutan
|
||||
|
||||
### Format Serial Number
|
||||
Edit di file `models/manufacturing_serial.py`, method `_generate_serial_number()`:
|
||||
```python
|
||||
def _generate_serial_number(self, product_id=None):
|
||||
prefix = 'MFG' # Ubah prefix default di sini
|
||||
# ... rest of code
|
||||
```
|
||||
|
||||
### Batch Size Limit
|
||||
Default maksimal 1000 serial per MO. Ubah di `models/mrp_production.py`:
|
||||
```python
|
||||
if qty_to_generate > 1000: # Ubah angka ini
|
||||
raise UserError(...)
|
||||
```
|
||||
|
||||
## Struktur Data
|
||||
|
||||
### Model: manufacturing.serial
|
||||
- `serial_number`: Nomor serial unik
|
||||
- `product_id`: Produk yang diproduksi
|
||||
- `mrp_production_id`: Link ke Manufacturing Order
|
||||
- `production_date`: Tanggal produksi
|
||||
- `state`: Status (draft/produced/delivered/cancelled)
|
||||
- `lot_id`: Link ke Stock Lot (opsional)
|
||||
|
||||
## Dependencies
|
||||
- mrp (Manufacturing)
|
||||
- stock (Inventory)
|
||||
- product (Product Management)
|
||||
|
||||
## Kompatibilitas
|
||||
- Odoo 14 Community Edition
|
||||
- Odoo 14 Enterprise Edition
|
||||
|
||||
## Lisensi
|
||||
LGPL-3
|
||||
|
||||
## Support
|
||||
Untuk pertanyaan atau issue, hubungi tim development.
|
||||
|
||||
## Changelog
|
||||
|
||||
### Version 14.0.1.0.0 (2026-02-14)
|
||||
- Initial release
|
||||
- Auto generate serial numbers
|
||||
- Manufacturing Order integration
|
||||
- Product configuration
|
||||
- Serial management views
|
||||
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import models
|
||||
@@ -0,0 +1,33 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
{
|
||||
'name': 'Manufacturing Serial Number',
|
||||
'version': '14.0.1.0.0',
|
||||
'category': 'Manufacturing',
|
||||
'summary': 'Automatic Serial Number Generation for Manufacturing Products',
|
||||
'description': """
|
||||
Manufacturing Serial Number
|
||||
============================
|
||||
|
||||
Modul ini menyediakan fitur untuk:
|
||||
* Generate otomatis serial number unik untuk setiap produk manufacturing
|
||||
* Tracking serial number per Manufacturing Order
|
||||
* Laporan dan history serial number
|
||||
* Integrasi penuh dengan Manufacturing Order (MRP)
|
||||
|
||||
Cocok untuk community edition yang membutuhkan tracking serial number
|
||||
tanpa harus menggunakan fitur berbayar.
|
||||
""",
|
||||
'author': 'Custom Development',
|
||||
'website': '',
|
||||
'depends': ['mrp', 'stock', 'product'],
|
||||
'data': [
|
||||
'security/ir.model.access.csv',
|
||||
'views/manufacturing_serial_views.xml',
|
||||
'views/mrp_production_views.xml',
|
||||
'views/product_template_views.xml',
|
||||
],
|
||||
'installable': True,
|
||||
'application': False,
|
||||
'auto_install': False,
|
||||
'license': 'LGPL-3',
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import manufacturing_serial
|
||||
from . import mrp_production
|
||||
from . import product_template
|
||||
@@ -0,0 +1,114 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from odoo import models, fields, api, _
|
||||
from odoo.exceptions import ValidationError
|
||||
import random
|
||||
import string
|
||||
|
||||
|
||||
class ManufacturingSerial(models.Model):
|
||||
_name = 'manufacturing.serial'
|
||||
_description = 'Manufacturing Serial Number'
|
||||
_order = 'serial_number desc'
|
||||
_rec_name = 'serial_number'
|
||||
|
||||
serial_number = fields.Char(
|
||||
string='Serial Number',
|
||||
required=True,
|
||||
copy=False,
|
||||
readonly=True,
|
||||
index=True,
|
||||
default='New'
|
||||
)
|
||||
|
||||
product_id = fields.Many2one(
|
||||
'product.product',
|
||||
string='Product',
|
||||
required=True,
|
||||
ondelete='restrict'
|
||||
)
|
||||
|
||||
mrp_production_id = fields.Many2one(
|
||||
'mrp.production',
|
||||
string='Manufacturing Order',
|
||||
ondelete='cascade'
|
||||
)
|
||||
|
||||
production_date = fields.Datetime(
|
||||
string='Production Date',
|
||||
default=fields.Datetime.now,
|
||||
required=True
|
||||
)
|
||||
|
||||
state = fields.Selection([
|
||||
('draft', 'Draft'),
|
||||
('produced', 'Produced'),
|
||||
('delivered', 'Delivered'),
|
||||
('cancelled', 'Cancelled')
|
||||
], string='State', default='draft', required=True)
|
||||
|
||||
notes = fields.Text(string='Notes')
|
||||
|
||||
company_id = fields.Many2one(
|
||||
'res.company',
|
||||
string='Company',
|
||||
default=lambda self: self.env.company
|
||||
)
|
||||
|
||||
lot_id = fields.Many2one(
|
||||
'stock.production.lot',
|
||||
string='Lot/Serial Number (Stock)',
|
||||
help='Link to stock lot if available'
|
||||
)
|
||||
|
||||
_sql_constraints = [
|
||||
('serial_number_unique', 'unique(serial_number, company_id)',
|
||||
'Serial number must be unique per company!')
|
||||
]
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
if vals.get('serial_number', 'New') == 'New':
|
||||
vals['serial_number'] = self._generate_serial_number(vals.get('product_id'))
|
||||
return super(ManufacturingSerial, self).create(vals)
|
||||
|
||||
def _generate_serial_number(self, product_id=None):
|
||||
"""Generate unique serial number"""
|
||||
prefix = 'MFG'
|
||||
|
||||
if product_id:
|
||||
product = self.env['product.product'].browse(product_id)
|
||||
if product.default_code:
|
||||
prefix = product.default_code[:6].upper()
|
||||
|
||||
# Generate sequential number
|
||||
sequence = self.env['ir.sequence'].next_by_code('manufacturing.serial') or '0001'
|
||||
|
||||
# Add random suffix for extra uniqueness
|
||||
random_suffix = ''.join(random.choices(string.ascii_uppercase + string.digits, k=4))
|
||||
|
||||
serial_number = f"{prefix}-{sequence}-{random_suffix}"
|
||||
|
||||
# Check if exists, regenerate if needed
|
||||
if self.search([('serial_number', '=', serial_number)], limit=1):
|
||||
return self._generate_serial_number(product_id)
|
||||
|
||||
return serial_number
|
||||
|
||||
def action_set_produced(self):
|
||||
self.write({'state': 'produced'})
|
||||
|
||||
def action_set_delivered(self):
|
||||
self.write({'state': 'delivered'})
|
||||
|
||||
def action_cancel(self):
|
||||
self.write({'state': 'cancelled'})
|
||||
|
||||
def name_get(self):
|
||||
result = []
|
||||
for record in self:
|
||||
name = f"{record.serial_number}"
|
||||
if record.product_id:
|
||||
name = f"{record.serial_number} - {record.product_id.name}"
|
||||
result.append((record.id, name))
|
||||
return result
|
||||
@@ -0,0 +1,109 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from odoo import models, fields, api, _
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class MrpProduction(models.Model):
|
||||
_inherit = 'mrp.production'
|
||||
|
||||
serial_ids = fields.One2many(
|
||||
'manufacturing.serial',
|
||||
'mrp_production_id',
|
||||
string='Serial Numbers',
|
||||
readonly=True
|
||||
)
|
||||
|
||||
serial_count = fields.Integer(
|
||||
string='Serial Count',
|
||||
compute='_compute_serial_count'
|
||||
)
|
||||
|
||||
auto_generate_serial = fields.Boolean(
|
||||
string='Auto Generate Serial',
|
||||
default=True,
|
||||
help='Automatically generate serial numbers when production is done'
|
||||
)
|
||||
|
||||
@api.depends('serial_ids')
|
||||
def _compute_serial_count(self):
|
||||
for record in self:
|
||||
record.serial_count = len(record.serial_ids)
|
||||
|
||||
def button_mark_done(self):
|
||||
"""Override to generate serial numbers when marking as done"""
|
||||
res = super(MrpProduction, self).button_mark_done()
|
||||
|
||||
for production in self:
|
||||
if production.auto_generate_serial and production.product_id:
|
||||
# Check if product needs serial tracking
|
||||
if production.product_id.tracking in ['serial', 'lot'] or \
|
||||
production.product_id.use_manufacturing_serial:
|
||||
production._generate_manufacturing_serials()
|
||||
|
||||
return res
|
||||
|
||||
def _generate_manufacturing_serials(self):
|
||||
"""Generate serial numbers for finished products"""
|
||||
self.ensure_one()
|
||||
|
||||
SerialObj = self.env['manufacturing.serial']
|
||||
|
||||
# Calculate quantity to generate (based on product qty_done)
|
||||
qty_to_generate = int(self.product_qty)
|
||||
|
||||
if qty_to_generate <= 0:
|
||||
return
|
||||
|
||||
# Limit to reasonable number
|
||||
if qty_to_generate > 1000:
|
||||
raise UserError(_('Cannot generate more than 1000 serial numbers at once. Please reduce quantity.'))
|
||||
|
||||
serial_list = []
|
||||
for i in range(qty_to_generate):
|
||||
serial_vals = {
|
||||
'product_id': self.product_id.id,
|
||||
'mrp_production_id': self.id,
|
||||
'production_date': fields.Datetime.now(),
|
||||
'state': 'produced',
|
||||
'company_id': self.company_id.id,
|
||||
}
|
||||
serial_list.append(serial_vals)
|
||||
|
||||
# Batch create serials
|
||||
if serial_list:
|
||||
SerialObj.create(serial_list)
|
||||
|
||||
return True
|
||||
|
||||
def action_view_serial_numbers(self):
|
||||
"""Open serial numbers view"""
|
||||
self.ensure_one()
|
||||
return {
|
||||
'name': _('Serial Numbers'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'res_model': 'manufacturing.serial',
|
||||
'view_mode': 'tree,form',
|
||||
'domain': [('mrp_production_id', '=', self.id)],
|
||||
'context': {
|
||||
'default_mrp_production_id': self.id,
|
||||
'default_product_id': self.product_id.id,
|
||||
},
|
||||
}
|
||||
|
||||
def action_generate_serials_manual(self):
|
||||
"""Manual action to generate serials"""
|
||||
for production in self:
|
||||
if production.state in ['done', 'progress']:
|
||||
production._generate_manufacturing_serials()
|
||||
|
||||
return {
|
||||
'type': 'ir.actions.client',
|
||||
'tag': 'display_notification',
|
||||
'params': {
|
||||
'title': _('Success'),
|
||||
'message': _('Serial numbers generated successfully.'),
|
||||
'type': 'success',
|
||||
'sticky': False,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from odoo import models, fields, api
|
||||
|
||||
|
||||
class ProductTemplate(models.Model):
|
||||
_inherit = 'product.template'
|
||||
|
||||
use_manufacturing_serial = fields.Boolean(
|
||||
string='Use Manufacturing Serial',
|
||||
default=False,
|
||||
help='Enable automatic serial number generation for manufacturing'
|
||||
)
|
||||
|
||||
serial_count = fields.Integer(
|
||||
string='Total Serials Generated',
|
||||
compute='_compute_serial_count'
|
||||
)
|
||||
|
||||
@api.depends('product_variant_ids.serial_ids')
|
||||
def _compute_serial_count(self):
|
||||
for template in self:
|
||||
serials = self.env['manufacturing.serial'].search([
|
||||
('product_id', 'in', template.product_variant_ids.ids)
|
||||
])
|
||||
template.serial_count = len(serials)
|
||||
|
||||
def action_view_serial_numbers(self):
|
||||
"""View all serial numbers for this product"""
|
||||
self.ensure_one()
|
||||
return {
|
||||
'name': 'Serial Numbers',
|
||||
'type': 'ir.actions.act_window',
|
||||
'res_model': 'manufacturing.serial',
|
||||
'view_mode': 'tree,form',
|
||||
'domain': [('product_id', 'in', self.product_variant_ids.ids)],
|
||||
'context': {'default_product_id': self.product_variant_ids[0].id if self.product_variant_ids else False},
|
||||
}
|
||||
|
||||
|
||||
class ProductProduct(models.Model):
|
||||
_inherit = 'product.product'
|
||||
|
||||
serial_ids = fields.One2many(
|
||||
'manufacturing.serial',
|
||||
'product_id',
|
||||
string='Serial Numbers'
|
||||
)
|
||||
@@ -0,0 +1,4 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_manufacturing_serial_user,access_manufacturing_serial_user,model_manufacturing_serial,mrp.group_mrp_user,1,1,1,0
|
||||
access_manufacturing_serial_manager,access_manufacturing_serial_manager,model_manufacturing_serial,mrp.group_mrp_manager,1,1,1,1
|
||||
access_manufacturing_serial_stock_user,access_manufacturing_serial_stock_user,model_manufacturing_serial,stock.group_stock_user,1,0,0,0
|
||||
|
@@ -0,0 +1,122 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<!-- Manufacturing Serial Tree View -->
|
||||
<record id="view_manufacturing_serial_tree" model="ir.ui.view">
|
||||
<field name="name">manufacturing.serial.tree</field>
|
||||
<field name="model">manufacturing.serial</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Manufacturing Serial Numbers" decoration-success="state=='produced'" decoration-info="state=='draft'" decoration-muted="state=='cancelled'">
|
||||
<field name="serial_number"/>
|
||||
<field name="product_id"/>
|
||||
<field name="mrp_production_id"/>
|
||||
<field name="production_date"/>
|
||||
<field name="state"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Manufacturing Serial Form View -->
|
||||
<record id="view_manufacturing_serial_form" model="ir.ui.view">
|
||||
<field name="name">manufacturing.serial.form</field>
|
||||
<field name="model">manufacturing.serial</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Manufacturing Serial Number">
|
||||
<header>
|
||||
<button name="action_set_produced" string="Set Produced" type="object"
|
||||
states="draft" class="oe_highlight"/>
|
||||
<button name="action_set_delivered" string="Set Delivered" type="object"
|
||||
states="produced" class="oe_highlight"/>
|
||||
<button name="action_cancel" string="Cancel" type="object"
|
||||
states="draft,produced" confirm="Are you sure you want to cancel this serial?"/>
|
||||
<field name="state" widget="statusbar" statusbar_visible="draft,produced,delivered"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<!-- Add smart buttons here if needed -->
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="serial_number" readonly="1"/>
|
||||
<field name="product_id"/>
|
||||
<field name="mrp_production_id"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="production_date"/>
|
||||
<field name="lot_id"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Notes">
|
||||
<field name="notes" placeholder="Additional notes..."/>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Manufacturing Serial Search View -->
|
||||
<record id="view_manufacturing_serial_search" model="ir.ui.view">
|
||||
<field name="name">manufacturing.serial.search</field>
|
||||
<field name="model">manufacturing.serial</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Serial Numbers">
|
||||
<field name="serial_number"/>
|
||||
<field name="product_id"/>
|
||||
<field name="mrp_production_id"/>
|
||||
<filter string="Draft" name="draft" domain="[('state','=','draft')]"/>
|
||||
<filter string="Produced" name="produced" domain="[('state','=','produced')]"/>
|
||||
<filter string="Delivered" name="delivered" domain="[('state','=','delivered')]"/>
|
||||
<separator/>
|
||||
<filter string="This Month" name="this_month"
|
||||
domain="[('production_date','>=', (context_today() - relativedelta(day=1)).strftime('%Y-%m-%d')), ('production_date','<', (context_today() + relativedelta(months=1, day=1)).strftime('%Y-%m-%d'))]"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter string="Product" name="group_product" context="{'group_by':'product_id'}"/>
|
||||
<filter string="Manufacturing Order" name="group_mrp" context="{'group_by':'mrp_production_id'}"/>
|
||||
<filter string="State" name="group_state" context="{'group_by':'state'}"/>
|
||||
<filter string="Production Date" name="group_date" context="{'group_by':'production_date'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Manufacturing Serial Action -->
|
||||
<record id="action_manufacturing_serial" model="ir.actions.act_window">
|
||||
<field name="name">Manufacturing Serial Numbers</field>
|
||||
<field name="res_model">manufacturing.serial</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="search_view_id" ref="view_manufacturing_serial_search"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Create your first manufacturing serial number
|
||||
</p>
|
||||
<p>
|
||||
Serial numbers will be automatically generated when manufacturing orders are completed.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Menu Items -->
|
||||
<menuitem id="menu_manufacturing_serial_root"
|
||||
name="Manufacturing Serials"
|
||||
parent="mrp.menu_mrp_root"
|
||||
sequence="50"/>
|
||||
|
||||
<menuitem id="menu_manufacturing_serial"
|
||||
name="Serial Numbers"
|
||||
parent="menu_manufacturing_serial_root"
|
||||
action="action_manufacturing_serial"
|
||||
sequence="10"/>
|
||||
|
||||
<!-- IR Sequence for Serial Numbers -->
|
||||
<record id="seq_manufacturing_serial" model="ir.sequence">
|
||||
<field name="name">Manufacturing Serial Number</field>
|
||||
<field name="code">manufacturing.serial</field>
|
||||
<field name="prefix">S</field>
|
||||
<field name="padding">6</field>
|
||||
<field name="number_increment">1</field>
|
||||
<field name="implementation">standard</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<!-- MRP Production Form View - Inherit -->
|
||||
<record id="view_mrp_production_form_inherit_serial" model="ir.ui.view">
|
||||
<field name="name">mrp.production.form.inherit.serial</field>
|
||||
<field name="model">mrp.production</field>
|
||||
<field name="inherit_id" ref="mrp.mrp_production_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<!-- Add Smart Button -->
|
||||
<xpath expr="//div[@name='button_box']" position="inside">
|
||||
<button name="action_view_serial_numbers"
|
||||
type="object"
|
||||
class="oe_stat_button"
|
||||
icon="fa-barcode"
|
||||
attrs="{'invisible': [('serial_count', '=', 0)]}">
|
||||
<field name="serial_count" widget="statinfo" string="Serials"/>
|
||||
</button>
|
||||
</xpath>
|
||||
|
||||
<!-- Add Auto Generate Serial Field -->
|
||||
<xpath expr="//field[@name='product_id']" position="after">
|
||||
<field name="auto_generate_serial"
|
||||
attrs="{'invisible': [('state', 'in', ['done', 'cancel'])]}"/>
|
||||
</xpath>
|
||||
|
||||
<!-- Add Serial Numbers Page -->
|
||||
<xpath expr="//notebook" position="inside">
|
||||
<page string="Serial Numbers" attrs="{'invisible': [('serial_count', '=', 0)]}">
|
||||
<group>
|
||||
<button name="action_generate_serials_manual"
|
||||
string="Generate Serials Now"
|
||||
type="object"
|
||||
class="btn-primary"
|
||||
attrs="{'invisible': ['|', ('state', 'not in', ['progress', 'done']), ('serial_count', '>', 0)]}"
|
||||
help="Manually generate serial numbers for this production"/>
|
||||
</group>
|
||||
<field name="serial_ids" readonly="1">
|
||||
<tree decoration-success="state=='produced'" decoration-info="state=='draft'">
|
||||
<field name="serial_number"/>
|
||||
<field name="product_id"/>
|
||||
<field name="production_date"/>
|
||||
<field name="state"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- MRP Production Tree View - Add Serial Count -->
|
||||
<record id="view_mrp_production_tree_inherit_serial" model="ir.ui.view">
|
||||
<field name="name">mrp.production.tree.inherit.serial</field>
|
||||
<field name="model">mrp.production</field>
|
||||
<field name="inherit_id" ref="mrp.mrp_production_tree_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='state']" position="before">
|
||||
<field name="serial_count" string="Serials" optional="show"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<!-- Product Template Form View - Inherit -->
|
||||
<record id="view_product_template_form_inherit_mfg_serial" model="ir.ui.view">
|
||||
<field name="name">product.template.form.inherit.mfg.serial</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="inherit_id" ref="product.product_template_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<!-- Add Smart Button for Serial Numbers -->
|
||||
<xpath expr="//div[@name='button_box']" position="inside">
|
||||
<button name="action_view_serial_numbers"
|
||||
type="object"
|
||||
class="oe_stat_button"
|
||||
icon="fa-barcode"
|
||||
attrs="{'invisible': [('serial_count', '=', 0)]}">
|
||||
<field name="serial_count" widget="statinfo" string="Mfg Serials"/>
|
||||
</button>
|
||||
</xpath>
|
||||
|
||||
<!-- Add Manufacturing Serial Field in Inventory Tab -->
|
||||
<xpath expr="//page[@name='inventory']//group[@name='group_lots_and_weight']" position="after">
|
||||
<group string="Manufacturing Serial" name="group_manufacturing_serial">
|
||||
<field name="use_manufacturing_serial"
|
||||
help="Enable automatic serial number generation when this product is manufactured"/>
|
||||
</group>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Product Template Tree View - Show Serial Count -->
|
||||
<record id="view_product_template_tree_inherit_mfg_serial" model="ir.ui.view">
|
||||
<field name="name">product.template.tree.inherit.mfg.serial</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="inherit_id" ref="product.product_template_tree_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='default_code']" position="after">
|
||||
<field name="serial_count" string="Mfg Serials" optional="hide"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||