diff --git a/app_product_type_sequence/__init__.py b/app_product_type_sequence/__init__.py new file mode 100644 index 00000000..7ddf3c86 --- /dev/null +++ b/app_product_type_sequence/__init__.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +''' +Created on 2017-10-28 +@author: 广州尚鹏,http://www.sunpop.cn +@email: 300883@qq.com +@resource of Sunpop +Odoo10离线中文用户手册下载 +http://www.sunpop.cn/odoo10_user_manual_document_offline/ +Odoo10离线开发手册下载-含python教程,jquery参考,Jinja2模板,PostgresSQL参考(odoo开发必备) +http://www.sunpop.cn/odoo10_developer_document_offline/ + +@description: +''' + +from . import models +from . import controllers +from .hooks import pre_init_hook + diff --git a/app_product_type_sequence/__openerp__.py b/app_product_type_sequence/__openerp__.py new file mode 100644 index 00000000..32dc9d33 --- /dev/null +++ b/app_product_type_sequence/__openerp__.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- + +# Created on 2017-11-05 +# author: 广州尚鹏,http://www.sunpop.cn +# email: 300883@qq.com +# resource of Sunpop +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +# Odoo在线中文用户手册(长期更新) +# http://www.sunpop.cn/documentation/user/10.0/zh_CN/index.html + +# Odoo10离线中文用户手册下载 +# http://www.sunpop.cn/odoo10_user_manual_document_offline/ +# Odoo10离线开发手册下载-含python教程,jquery参考,Jinja2模板,PostgresSQL参考(odoo开发必备) +# http://www.sunpop.cn/odoo10_developer_document_offline/ +# description: +{ + 'name': 'App Product Internal Type,Auto Sequence, Auto Code(Variants Supported), Auto Attributes', + 'summary': 'Auto Internal Reference.', + "version": '10.0.2.2', + 'category': 'Sales', + 'author': 'Sunpop.cn', + 'website': 'http://www.sunpop.cn', + 'license': 'AGPL-3', + 'sequence': 2, + 'installable': True, + 'auto_install': True, + 'application': True, + 'images': ['static/description/set2.jpg'], + 'currency': 'EUR', + 'price': 98, + 'description': u""" + App Product Auto Sequence, Auto Code(Variants Supported), Auto Attributes + + This module allows to associate a sequence to the product reference.
+ The reference (default code) is unique (SQL constraint) and required.
+ Support Product with or without Variants. + 1.Auto Sequence or code for every product.自动产品编码。 + 2.Auto Sequence or for every product variants, like product20171130-001.自动多规格产品编码,形式为 主产品编码-001。 + 3.Product code must be Unique.产品编码强制要求唯一。 + 4.Define different product type, each product type use own rule of sequence.可自定义产品类型,不同产品类型使用不同编码规则。 + 5.Quick access in sale , inventory, system menu.可以在销售、库存、系统菜单中快速定义。 + 6.Multi language support.
多语种支持。 + 7.Setup default Auto Sequence for each product category,自动设置每个产品目录使用的产品编码规则 + 8.Auto setup product attribute lik Sale/Purchase, Stockable/Consumable/Service, Stock Routes. 自动设置产品的销售/采购,可库存产品/服务/消耗品,购买/制造/按订单生成等库存路线 + """, + 'pre_init_hook': 'pre_init_hook', + 'depends': [ + 'product', + 'stock', + ], + 'data': [ + # 视图 + "security/ir.model.access.csv", + "security/security.xml", + 'views/product_template_view.xml', + 'views/product_product_view.xml', + 'views/product_category_view.xml', + 'views/product_internal_type_view.xml', + 'data/product_sequence.xml', + ], + 'demo': [ + ], +} diff --git a/app_product_type_sequence/controllers/__init__.py b/app_product_type_sequence/controllers/__init__.py new file mode 100644 index 00000000..12a7e529 --- /dev/null +++ b/app_product_type_sequence/controllers/__init__.py @@ -0,0 +1 @@ +from . import main diff --git a/app_product_type_sequence/controllers/main.py b/app_product_type_sequence/controllers/main.py new file mode 100644 index 00000000..40a96afc --- /dev/null +++ b/app_product_type_sequence/controllers/main.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/app_product_type_sequence/data/product_sequence.xml b/app_product_type_sequence/data/product_sequence.xml new file mode 100644 index 00000000..a790f2c2 --- /dev/null +++ b/app_product_type_sequence/data/product_sequence.xml @@ -0,0 +1,104 @@ + + + + + + + Sequence for All Products + product.product + PR%(y)s%(month)s + 5 + + True + + + + Sequence for Manufactured Product + product.product + CP%(y)s%(month)s + 5 + + True + + + + Sequence for Manufactured Components + product.product + BC%(y)s%(month)s + 5 + + True + + + + Sequence for Sourced Material + product.product + WL%(y)s%(month)s + 5 + + True + + + + + + + Manufactured Product + cp + 10 + product + 1 + 0 + + Set prefix as "CP" in link sequence + + + + + Manufactured Components + bc + 20 + product + 0 + 0 + + Set prefix as "BC" in link sequence + + + + + Sourced Material + wl + 30 + product + 0 + 1 + + Set prefix as "WL" in link sequence + + + + + + Service + fw + 50 + service + 1 + 1 + Set prefix as "PR" in link sequence + + + + + Consumer + xh + 60 + consu + 1 + 1 + Set prefix as "PR" in link sequence + + + + diff --git a/app_product_type_sequence/data/product_sequence_dp.xml b/app_product_type_sequence/data/product_sequence_dp.xml new file mode 100644 index 00000000..4b8b3ff3 --- /dev/null +++ b/app_product_type_sequence/data/product_sequence_dp.xml @@ -0,0 +1,104 @@ + + + + + + + Sequence for All Products + product.product + P%(y)s%(month)s + 5 + + True + + + + Sequence for Manufactured Product + product.product + D%(y)s%(month)s + 5 + + True + + + + Sequence for Components Product + product.product + C%(y)s%(month)s + 5 + + True + + + + Sequence for Sourced Product + product.product + S%(y)s%(month)s + 5 + + True + + + + Service + product.product + V%(y)s%(month)s + 5 + + True + + + + + + Manufactured Product + d + product + 1 + 0 + + Set prefix as "D" in link sequence + + + + Components Product + c + product + 0 + 1 + + Set prefix as "C" in link sequence + + + + Sourced Product + s + product + 1 + 1 + + Set prefix as "S" in link sequence + + + + Service + v + service + 1 + 1 + + Set prefix as "V" in link sequence + + + + + + internal_type + product.template + default + + + + + + diff --git a/app_product_type_sequence/data/product_sequence_felive.xml b/app_product_type_sequence/data/product_sequence_felive.xml new file mode 100644 index 00000000..5278299c --- /dev/null +++ b/app_product_type_sequence/data/product_sequence_felive.xml @@ -0,0 +1,134 @@ + + + + + + + Sequence for All Products + product.product + PR%(y)s%(month)s + 5 + + True + + + + Sequence for Manufactured Product + product.product + CP%(y)s%(month)s + 5 + + True + + + + Sequence for Manufactured Components + product.product + BJ%(y)s%(month)s + 5 + + True + + + + Sequence for Sourced Material + product.product + BC%(y)s%(month)s + 5 + + True + + + + Sequence for Sourced Product + product.product + WL%(y)s%(month)s + 5 + + True + + + + + + 图纸成品 + cp + 1 + product + 1 + 0 + + Set prefix as "CP" in link sequence + + + + + 图纸板件 + bj + 2 + product + 0 + 0 + + Set prefix as "BJ" in link sequence + + + + + 大板 + bc + 3 + product + 0 + 1 + + Set prefix as "BC" in link sequence + + + + + 基础物料 + cl + 4 + product + 1 + 1 + + Set prefix as "CL" in link sequence + + + + + 服务与费用 + fw + 5 + service + 1 + 1 + Set prefix as "PR" in link sequence + + + + + 消耗品 + xh + 6 + consu + 0 + 0 + Set prefix as "PR" in link sequence + + + + + + + + + + + + + + + diff --git a/app_product_type_sequence/data/product_sequence_origin.xml b/app_product_type_sequence/data/product_sequence_origin.xml new file mode 100644 index 00000000..488f1619 --- /dev/null +++ b/app_product_type_sequence/data/product_sequence_origin.xml @@ -0,0 +1,100 @@ + + + + + + + Sequence for All Products + product.product + PR%(y)s%(month)s + 5 + + True + + + + Sequence for Manufactured Product + product.product + CP%(y)s%(month)s + 5 + + True + + + + Sequence for Manufactured Components + product.product + BC%(y)s%(month)s + 5 + + True + + + + Sequence for Sourced Material + product.product + CL%(y)s%(month)s + 5 + + True + + + + + + + Manufactured Product + cp + product + 1 + 0 + + Set prefix as "CP" in link sequence + + + + + Manufactured Components + bc + product + 0 + 0 + + Set prefix as "BC" in link sequence + + + + + Components Product + bc + product + 0 + 1 + + Set prefix as "BC" in link sequence + + + + + Sourced Material + cl + product + 1 + 1 + + Set prefix as "CL" in link sequence + + + + + + + + + + + + + + + diff --git a/app_product_type_sequence/hooks.py b/app_product_type_sequence/hooks.py new file mode 100644 index 00000000..4a0ea85d --- /dev/null +++ b/app_product_type_sequence/hooks.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- + +# Created on 2017-11-05 +# author: 广州尚鹏,http://www.sunpop.cn +# email: 300883@qq.com +# resource of Sunpop +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +# Odoo在线中文用户手册(长期更新) +# http://www.sunpop.cn/documentation/user/10.0/zh_CN/index.html + +# Odoo10离线中文用户手册下载 +# http://www.sunpop.cn/odoo10_user_manual_document_offline/ +# Odoo10离线开发手册下载-含python教程,jquery参考,Jinja2模板,PostgresSQL参考(odoo开发必备) +# http://www.sunpop.cn/odoo10_developer_document_offline/ +# description: + +def pre_init_hook(cr): + """ + Updates existing codes matching the default 'New' or + empty. Primarily this ensures installation does not + fail for demo data. + :param cr: database cursor + :return: void + """ + cr.execute("UPDATE product_product " + "SET default_code = '!!PR!!' || id " + "WHERE default_code IS NULL OR default_code = 'New';") + + cr.execute("UPDATE product_template " + "Set default_code = " + "(select default_code from product_product " + "where product_product.product_tmpl_id = product_template.id limit 1)" + "WHERE default_code IS NULL OR default_code = 'New';") diff --git a/app_product_type_sequence/i18n/zh_CN.po b/app_product_type_sequence/i18n/zh_CN.po new file mode 100644 index 00000000..6e5c7abf --- /dev/null +++ b/app_product_type_sequence/i18n/zh_CN.po @@ -0,0 +1,249 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * app_product_type_sequence +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0+e-20171107\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2017-12-19 13:34+0000\n" +"PO-Revision-Date: 2017-12-19 13:34+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: app_product_type_sequence +#: model:ir.model.fields,help:app_product_type_sequence.field_product_internal_type_type +msgid "A stockable product is a product for which you manage stock. The \"Inventory\" app has to be installed.\n" +"A consumable product, on the other hand, is a product for which stock is not managed.\n" +"A service is a non-material product you provide.\n" +"A digital content is a non-material product you sell online. The files attached to the products are the one that are sold on the e-commerce such as e-books, music, pictures,... The \"Digital Product\" module has to be installed." +msgstr "A stockable product is a product for which you manage stock. The \"Inventory\" app has to be installed.\n" +"A consumable product, on the other hand, is a product for which stock is not managed.\n" +"A service is a non-material product you provide.\n" +"A digital content is a non-material product you sell online. The files attached to the products are the one that are sold on the e-commerce such as e-books, music, pictures,... The \"Digital Product\" module has to be installed." + +#. module: app_product_type_sequence +#: model:ir.ui.view,arch_db:app_product_type_sequence.product_internal_type_form_view +msgid "Auto Set Product's Value To:" +msgstr "自动设置产品默认参数为:" + +#. module: app_product_type_sequence +#: model:ir.model.fields,field_description:app_product_type_sequence.field_product_internal_type_purchase_ok +msgid "Can be Purchased" +msgstr "可用于采购" + +#. module: app_product_type_sequence +#: model:ir.model.fields,field_description:app_product_type_sequence.field_product_internal_type_rental +msgid "Can be Rent" +msgstr "可用于出租" + +#. module: app_product_type_sequence +#: model:ir.model.fields,field_description:app_product_type_sequence.field_product_internal_type_sale_ok +msgid "Can be Sold" +msgstr "可用于销售" + +#. module: app_product_type_sequence +#: model:product.internal.type,name:app_product_type_sequence.internal_type_sourced_material +msgid "Components Product" +msgstr "原材料" + +#. module: app_product_type_sequence +#: code:addons/app_product_type_sequence/models/product_internal_type.py:34 +#: selection:product.internal.type,type:0 +#, python-format +msgid "Consumable" +msgstr "可消耗" + +#. module: app_product_type_sequence +#: model:ir.model.fields,field_description:app_product_type_sequence.field_product_internal_type_create_uid +msgid "Created by" +msgstr "创建人" + +#. module: app_product_type_sequence +#: model:ir.model.fields,field_description:app_product_type_sequence.field_product_internal_type_create_date +msgid "Created on" +msgstr "创建时间" + +#. module: app_product_type_sequence +#: model:ir.model.fields,field_description:app_product_type_sequence.field_product_category_internal_type +msgid "Default Internal Type" +msgstr "默认产品内部类型" + +#. module: app_product_type_sequence +#: model:ir.model.fields,help:app_product_type_sequence.field_product_internal_type_route_ids +msgid "Depending on the modules installed, this will allow you to define the route of the product: whether it will be bought, manufactured, MTO/MTS,..." +msgstr "取决于安装的模块,它允许在产品定义路线:购买,制造,MTO/MTS,等等..." + +#. module: app_product_type_sequence +#: model:ir.model.fields,field_description:app_product_type_sequence.field_product_internal_type_description +msgid "Description" +msgstr "说明" + +#. module: app_product_type_sequence +#: model:ir.model.fields,field_description:app_product_type_sequence.field_product_internal_type_display_name +#: model:ir.model.fields,field_description:app_product_type_sequence.field_product_internal_type_name +#: model:ir.ui.view,arch_db:app_product_type_sequence.product_internal_type_form_view +msgid "Display Name" +msgstr "显示名称" + +#. module: app_product_type_sequence +#: model:ir.model.fields,field_description:app_product_type_sequence.field_product_internal_type_id +msgid "ID" +msgstr "ID" + +#. module: app_product_type_sequence +#: model:ir.model.fields,field_description:app_product_type_sequence.field_product_product_default_code_index +msgid "Internal Reference Index" +msgstr "Varient序号" + +#. module: app_product_type_sequence +#: model:ir.model.fields,field_description:app_product_type_sequence.field_product_product_default_code_stored +#: model:ir.model.fields,field_description:app_product_type_sequence.field_product_template_default_code_stored +msgid "Internal Reference Stored" +msgstr "主产品编码" + +#. module: app_product_type_sequence +#: model:ir.model.fields,field_description:app_product_type_sequence.field_product_product_internal_type +#: model:ir.model.fields,field_description:app_product_type_sequence.field_product_template_internal_type +msgid "Internal Type" +msgstr "内部类型" + +#. module: app_product_type_sequence +#: model:ir.model.fields,field_description:app_product_type_sequence.field_product_internal_type___last_update +msgid "Last Modified on" +msgstr "最后修改日" + +#. module: app_product_type_sequence +#: model:ir.model.fields,field_description:app_product_type_sequence.field_product_internal_type_write_uid +msgid "Last Updated by" +msgstr "最后更新人" + +#. module: app_product_type_sequence +#: model:ir.model.fields,field_description:app_product_type_sequence.field_product_internal_type_write_date +msgid "Last Updated on" +msgstr "最后更新时间" + +#. module: app_product_type_sequence +#: model:ir.model.fields,field_description:app_product_type_sequence.field_product_internal_type_link_sequence +msgid "Link Sequence" +msgstr "使用的序列" + +#. module: app_product_type_sequence +#: model:product.internal.type,name:app_product_type_sequence.internal_type_mrp_product +msgid "Manufactured Product" +msgstr "制造成品" + +#. module: app_product_type_sequence +#: code:addons/app_product_type_sequence/models/product_product.py:23 +#: code:addons/app_product_type_sequence/models/product_template.py:33 +#, python-format +msgid "New" +msgstr "新建" + +#. module: app_product_type_sequence +#: code:addons/app_product_type_sequence/models/product_template.py:41 +#, python-format +msgid "Please save product first before adding varients!" +msgstr "增加产品变体前,请先保存当前产品!" + +#. module: app_product_type_sequence +#: model:ir.model.fields,help:app_product_type_sequence.field_product_internal_type_sequence_prefix +msgid "Prefix value of the record for the sequence" +msgstr "序列记录的前缀" + +#. module: app_product_type_sequence +#: model:ir.model,name:app_product_type_sequence.model_product_product +msgid "Product" +msgstr "产品" + +#. module: app_product_type_sequence +#: model:ir.model,name:app_product_type_sequence.model_product_category +msgid "Product Category" +msgstr "产品类别" + +#. module: app_product_type_sequence +#: model:ir.actions.act_window,name:app_product_type_sequence.internal_type_action +#: model:ir.ui.menu,name:app_product_type_sequence.menu_internal_type_action_purchase +#: model:ir.ui.menu,name:app_product_type_sequence.menu_internal_type_action_sale +#: model:ir.ui.menu,name:app_product_type_sequence.menu_internal_type_action_stock +#: model:ir.ui.menu,name:app_product_type_sequence.menu_internal_type_action_sys +#: model:ir.ui.view,arch_db:app_product_type_sequence.product_internal_type_form_view +#: model:ir.ui.view,arch_db:app_product_type_sequence.product_internal_type_tree_view +msgid "Product Internal Type" +msgstr "产品编码类型" + +#. module: app_product_type_sequence +#: model:ir.model,name:app_product_type_sequence.model_product_template +msgid "Product Template" +msgstr "产品模板" + +#. module: app_product_type_sequence +#: model:ir.model.fields,field_description:app_product_type_sequence.field_product_internal_type_type +msgid "Product Type" +msgstr "产品类型" + +#. module: app_product_type_sequence +#: code:addons/app_product_type_sequence/models/product_product.py:83 +#, python-format +msgid "Product varient can only create in Product view!" +msgstr "请在产品管理页面增加产品的多属性!" + +#. module: app_product_type_sequence +#: model:ir.model.fields,field_description:app_product_type_sequence.field_product_internal_type_route_ids +msgid "Routes" +msgstr "路线" + +#. module: app_product_type_sequence +#: model:ir.model.fields,field_description:app_product_type_sequence.field_product_internal_type_sequence_prefix +msgid "Sequence Prefix" +msgstr "编号前缀" + +#. module: app_product_type_sequence +#: model:ir.model.fields,field_description:app_product_type_sequence.field_product_internal_type_sequence +msgid "Sequence" +msgstr "显示顺序" + +#. module: app_product_type_sequence +#: code:addons/app_product_type_sequence/models/product_internal_type.py:35 +#: selection:product.internal.type,type:0 +#, python-format +msgid "Service" +msgstr "服务" + +#. module: app_product_type_sequence +#: model:product.internal.type,name:app_product_type_sequence.internal_type_sourced_product +msgid "Sourced Product" +msgstr "外购成品" + +#. module: app_product_type_sequence +#: model:ir.model.fields,help:app_product_type_sequence.field_product_internal_type_sale_ok +msgid "Specify if the product can be selected in a sales order line." +msgstr "如果产品能在销售单明细在被选择,则指定。" + +#. module: app_product_type_sequence +#: code:addons/app_product_type_sequence/models/product_internal_type.py:36 +#: selection:product.internal.type,type:0 +#, python-format +msgid "Stockable Product" +msgstr "可库存产品" + +#. module: app_product_type_sequence +#: sql_constraint:product.internal.type:0 +#: sql_constraint:product.product:0 +msgid "The reference must be unique" +msgstr "产品内部编码不可重复!" + +#. module: app_product_type_sequence +#: model:ir.model.fields,field_description:app_product_type_sequence.field_product_internal_type_ref +msgid "Unique Code" +msgstr "唯一编码" + +#. module: app_product_type_sequence +#: model:ir.model,name:app_product_type_sequence.model_product_internal_type +msgid "product.internal.type" +msgstr "product.internal.type" + diff --git a/app_product_type_sequence/models/__init__.py b/app_product_type_sequence/models/__init__.py new file mode 100644 index 00000000..c01cf434 --- /dev/null +++ b/app_product_type_sequence/models/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +from . import product_template +from . import product_product +from . import product_category +from . import product_internal_type \ No newline at end of file diff --git a/app_product_type_sequence/models/product_category.py b/app_product_type_sequence/models/product_category.py new file mode 100644 index 00000000..841b8f20 --- /dev/null +++ b/app_product_type_sequence/models/product_category.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- + +# Created on 2017-11-28 +# author: 广州尚鹏,http://www.sunpop.cn +# email: 300883@qq.com +# resource of Sunpop +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +# Odoo在线中文用户手册(长期更新) +# http://www.sunpop.cn/documentation/user/10.0/zh_CN/index.html + +# Odoo10离线中文用户手册下载 +# http://www.sunpop.cn/odoo10_user_manual_document_offline/ +# Odoo10离线开发手册下载-含python教程,jquery参考,Jinja2模板,PostgresSQL参考(odoo开发必备) +# http://www.sunpop.cn/odoo10_developer_document_offline/ +# description: + +from openerp import api, fields, models, exceptions, _ + + +class ProductCategory(models.Model): + _name = "product.category" + _inherit = ['product.category'] + + internal_type = fields.Many2one( + 'product.internal.type', 'Default Internal Type', + auto_join=True, required=False) diff --git a/app_product_type_sequence/models/product_internal_type.py b/app_product_type_sequence/models/product_internal_type.py new file mode 100644 index 00000000..5b8690f8 --- /dev/null +++ b/app_product_type_sequence/models/product_internal_type.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- + +# Created on 2017-11-05 +# author: 广州尚鹏,http://www.sunpop.cn +# email: 300883@qq.com +# resource of Sunpop +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +# Odoo在线中文用户手册(长期更新) +# http://www.sunpop.cn/documentation/user/10.0/zh_CN/index.html + +# Odoo10离线中文用户手册下载 +# http://www.sunpop.cn/odoo10_user_manual_document_offline/ +# Odoo10离线开发手册下载-含python教程,jquery参考,Jinja2模板,PostgresSQL参考(odoo开发必备) +# http://www.sunpop.cn/odoo10_developer_document_offline/ +# description: + +from openerp import api, fields, models, _ + + +class ProductInternalType(models.Model): + _name = "product.internal.type" + _order = 'sequence, name' + + sequence = fields.Integer('Sequence', default=9) + name = fields.Char('Display Name', default='Normal', translate=True) + description = fields.Char('Description') + ref = fields.Char('Unique Code', required=True) + + link_sequence = fields.Many2one( + 'ir.sequence', 'Link Sequence', + auto_join=True, required=True, domain="[('code', '=', 'product.product')]") + sequence_prefix = fields.Char(u'Sequence Prefix', related='link_sequence.prefix', readonly=True, store=False) + # 各种默认值,填则自动录入,不填则不管 + type = fields.Selection([ + ('consu', _('Consumable')), + ('service', _('Service')), + ('product', _('Stockable Product'))], string='Product Type', + help='A stockable product is a product for which you manage stock. The "Inventory" app has to be installed.\n' + 'A consumable product, on the other hand, is a product for which stock is not managed.\n' + 'A service is a non-material product you provide.\n' + 'A digital content is a non-material product you sell online. The files attached to the products are the one that are sold on ' + 'the e-commerce such as e-books, music, pictures,... The "Digital Product" module has to be installed.') + + rental = fields.Boolean('Can be Rent') + sale_ok = fields.Boolean( + 'Can be Sold', default=True, + help="Specify if the product can be selected in a sales order line.") + purchase_ok = fields.Boolean('Can be Purchased', default=True) + + # 使用目录的默认路线来处理,暂时不用内部类型路线 + route_ids = fields.Many2many('stock.location.route', string='Routes', + domain=[('product_selectable', '=', True)], + help="Depending on the modules installed, this will allow you to define the route of the product: whether it will be bought, manufactured, MTO/MTS,...") + + company_id = fields.Many2one( + 'res.company', 'Company', + default=lambda self: self.env.user.company_id.id, index=1) + + _sql_constraints = [ + ('uniq_ref', + 'unique(ref)', + 'The reference must be unique'), + ] \ No newline at end of file diff --git a/app_product_type_sequence/models/product_product.py b/app_product_type_sequence/models/product_product.py new file mode 100644 index 00000000..28ded679 --- /dev/null +++ b/app_product_type_sequence/models/product_product.py @@ -0,0 +1,140 @@ +# -*- coding: utf-8 -*- + +# Created on 2017-01-09 +# author: 广州尚鹏,http://www.sunpop.cn +# email: 300883@qq.com +# resource of Sunpop +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +# Odoo在线中文用户手册(长期更新) +# http://www.sunpop.cn/documentation/user/10.0/zh_CN/index.html + +# Odoo10离线中文用户手册下载 +# http://www.sunpop.cn/odoo10_user_manual_document_offline/ +# Odoo10离线开发手册下载-含python教程,jquery参考,Jinja2模板,PostgresSQL参考(odoo开发必备) +# http://www.sunpop.cn/odoo10_developer_document_offline/ +# description: +from openerp import models, fields, api, exceptions, _ + + +class ProductProduct(models.Model): + _inherit = 'product.product' + + default_code = fields.Char('Internal Reference', index=True, default=lambda self: _('New'), copy=False) + default_code_index = fields.Integer('Internal Reference Index', readonly=True) + + # todo: 检查数据,要保证数据唯一性 + _sql_constraints = [ + ('uniq_default_code', + 'unique(default_code)', + 'The reference must be unique'), + ] + + @api.model + def default_get(self, fields): + context = self._context or {} + res = super(ProductProduct, self).default_get(fields) + # 内部编码类型默认值的录入 + if context.get("default_internal_type"): + self._onchange_internal_type() + elif context.get("default_internal_type_ref"): + types = self.env['product.internal.type'].search_read([('ref', '=', context.get("default_internal_type_ref"))], limit=1) + if types: + res.update({'internal_type':types[0]['id']}) + self._onchange_internal_type() + return res + + @api.model + def create(self, vals): + # todo: but 先建空白产品后,编辑2个以上变体,序号会少个 -1 + # code_index: 当没有变体现时,值为0,有变体时,为该变体序号 + code_index = 0 + if 'default_code' not in vals or vals['default_code'] == _('New'): + if 'product_tmpl_id' in vals: + # 按产品模板创建产品,有多种情况 + template = self.env['product.template'].search([('id', '=', vals['product_tmpl_id'])], limit=1) + if template.default_code and template.default_code != '': + code_stored = template.default_code + else: + code_stored = template.default_code_stored + if not code_stored: + code_stored = '' + mylen = len(template.product_variant_ids) + try: + attr = vals['attribute_value_ids'][0][2] + except: + attr = 0 + + # if self.env.context.get('create_from_tmpl') and not(attr): 此条件已限制,不让在template中先直接创建变体,要求先保存 + if self.env.context.get('create_from_tmpl') and not(attr): + # 从产品模板创建的第一个sku产品,不带属性 + # 没有属性值,则是单规格产品。attribute_value_ids格式为[6,0,[]]。多规格时,attribute_value_ids格式为[6,0,[x]] + code_index = 0 + vals['default_code_index'] = code_index + vals['default_code'] = code_stored + elif mylen == 0: + # 有属性值了,自己是第一个规格 + code_index = 1 + vals['default_code_index'] = code_index + vals['default_code'] = code_stored + '#%03d'%(code_index) + elif mylen == 1: + # 已存在1个,当存在的1个有属性时,要改已存在的product值 + code_index = template.product_variant_ids[:1].default_code_index + if template.product_variant_ids[:1].attribute_value_ids: + if code_index == 0: + code_index = 1 + template.product_variant_ids[:1].default_code_index = code_index + template.product_variant_ids[:1].default_code = code_stored + '#%03d'%(code_index) + # 接着改当前操作的product值 + code_index = code_index + 1 + vals['default_code_index'] = code_index + vals['default_code'] = code_stored + '#%03d'%(code_index) + elif mylen > 1: + # 找到最大的序号 + variant_max = max(template.product_variant_ids,key=lambda x: x['default_code_index']) + code_index = variant_max['default_code_index'] + 1 + vals['default_code_index'] = code_index + vals['default_code'] = code_stored + '#%03d'%(code_index) + else: + # 当按模板 + # 此条件常规不出现,但特殊项目会有 + variant_max = max(template.product_variant_ids,key=lambda x: x['default_code_index']) + code_index = variant_max['default_code_index'] + 1 + vals['default_code_index'] = code_index + vals['default_code'] = code_stored + '#%03d'%(code_index) + else: + # create from product_product + # 默认使用制造成品的编码 + sequence = self.env.ref('app_product_type_sequence.internal_type_mrp_product', raise_if_not_found=False) + if 'internal_type' in vals: + sequence = self.env['product.internal.type'].search([('id', '=', vals['internal_type'])], limit=1) + vals['default_code'] = sequence.link_sequence.next_by_id() + else: + # 如果有自己输入 ref,则不需要自运输生成 + # sequence = self.env['product.internal.type'].search([('id', '=', vals['internal_type'])], limit=1) + # if sequence: + # vals['default_code'] = sequence.link_sequence.next_by_id() + pass + return super(ProductProduct, self).create(vals) + + @api.multi + def copy(self, default=None): + if len(self.product_tmpl_id.product_variant_ids)>1 : + raise exceptions.ValidationError(_('Product varient can only create in Product view!')) + return super(ProductProduct, self).copy(default=None) + + # 当内部类型变化时,改变产品的各默认值 + @api.onchange('internal_type') + def _onchange_internal_type(self): + if self.internal_type: + self.type = self.internal_type.type + self.rental = self.internal_type.rental + self.sale_ok = self.internal_type.sale_ok + self.purchase_ok = self.internal_type.purchase_ok + self.route_ids = self.internal_type.route_ids + + # 分类变动时,如果分类绑定了内部类型则联动 + @api.onchange('categ_id') + def _onchange_cate_id(self): + if self.categ_id and self.categ_id.internal_type: + self.internal_type = self.categ_id.internal_type \ No newline at end of file diff --git a/app_product_type_sequence/models/product_template.py b/app_product_type_sequence/models/product_template.py new file mode 100644 index 00000000..bd51b4a0 --- /dev/null +++ b/app_product_type_sequence/models/product_template.py @@ -0,0 +1,101 @@ +# -*- coding: utf-8 -*- + +# Created on 2017-11-05 +# author: 广州尚鹏,http://www.sunpop.cn +# email: 300883@qq.com +# resource of Sunpop +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +# Odoo在线中文用户手册(长期更新) +# http://www.sunpop.cn/documentation/user/10.0/zh_CN/index.html + +# Odoo10离线中文用户手册下载 +# http://www.sunpop.cn/odoo10_user_manual_document_offline/ +# Odoo10离线开发手册下载-含python教程,jquery参考,Jinja2模板,PostgresSQL参考(odoo开发必备) +# http://www.sunpop.cn/odoo10_developer_document_offline/ +# description: + +from openerp import api, fields, models, exceptions, _ + + +class ProductTemplate(models.Model): + _name = "product.template" + _inherit = ['product.template'] + + # auto_join只要搜索product.template,自动会join。如果经常用到 internal_type 效率会高。 + internal_type = fields.Many2one( + 'product.internal.type', 'Internal Type', + auto_join=True, required=True) + + default_code = fields.Char( + 'Internal Reference', + compute='_compute_default_code', + inverse='_set_default_code', + store=True, default=lambda self: _('New'), copy=False) + # 因为default_code有odoo的处理方式,影响面大,故会将其另存到 default_code_stored + default_code_stored = fields.Char('Internal Reference Stored', + default=lambda self: _('New')) + + @api.model + def default_get(self, fields): + context = self._context or {} + res = super(ProductTemplate, self).default_get(fields) + # 内部编码类型默认值的录入 + if context.get("default_internal_type"): + self._onchange_internal_type() + elif context.get("default_internal_type_ref"): + types = self.env['product.internal.type'].search_read([('ref', '=', context.get("default_internal_type_ref"))], limit=1) + if types: + res.update({'internal_type':types[0]['id']}) + self._onchange_internal_type() + return res + + @api.model + def create(self, vals): + if 'attribute_line_ids' in vals: + if len(vals['attribute_line_ids'])>0: + raise exceptions.ValidationError(_('Please save product first before adding varients!')) + + if 'default_code' not in vals or vals['default_code'] == _('New'): + sequence = self.env['product.internal.type'].search([('id', '=', vals['internal_type'])], limit=1) + if not sequence: + sequence = self.env.ref('app_product_type_sequence.internal_type_mrp_product', raise_if_not_found=False) + vals['default_code'] = sequence.link_sequence.next_by_id() + else: + pass + + if vals['default_code']: + vals['default_code_stored'] = vals['default_code'] + + return super(ProductTemplate, self).create(vals) + + @api.depends('product_variant_ids', 'product_variant_ids.default_code') + def _compute_default_code(self): + unique_variants = self.filtered(lambda template: len(template.product_variant_ids) == 1) + # 设置default_code + for template in unique_variants: + template.default_code = template.product_variant_ids.default_code + for template in (self - unique_variants): + if len(template.product_variant_ids)>1: + template.default_code = '' + + @api.one + def _set_default_code(self): + if len(self.product_variant_ids) == 1: + self.product_variant_ids.default_code = self.default_code_stored + + # 当内部类型变化时,改变产品模板的各默认值 + @api.onchange('internal_type') + def _onchange_internal_type(self): + if self.internal_type: + self.type = self.internal_type.type + self.rental = self.internal_type.rental + self.sale_ok = self.internal_type.sale_ok + self.purchase_ok = self.internal_type.purchase_ok + self.route_ids = self.internal_type.route_ids + + # 分类变动时,如果分类绑定了内部类型则联动 + @api.onchange('categ_id') + def _onchange_cate_id(self): + if self.categ_id and self.categ_id.internal_type: + self.internal_type = self.categ_id.internal_type \ No newline at end of file diff --git a/app_product_type_sequence/security/ir.model.access.csv b/app_product_type_sequence/security/ir.model.access.csv new file mode 100644 index 00000000..02697c29 --- /dev/null +++ b/app_product_type_sequence/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_sale_order_type_manager,access_sale_order_type_manager,model_product_internal_type,sales_team.group_sale_manager,1,1,1,1 +access_sale_order_type_salesman,access_sale_order_type_salesman,model_product_internal_type,sales_team.group_sale_salesman,1,0,0,0 diff --git a/app_product_type_sequence/security/security.xml b/app_product_type_sequence/security/security.xml new file mode 100644 index 00000000..c3ab0e2f --- /dev/null +++ b/app_product_type_sequence/security/security.xml @@ -0,0 +1,12 @@ + + + + Product Internal Type multi-company + + ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])] + + + + + + diff --git a/app_product_type_sequence/static/description/icon.png b/app_product_type_sequence/static/description/icon.png new file mode 100644 index 00000000..2a04f219 Binary files /dev/null and b/app_product_type_sequence/static/description/icon.png differ diff --git a/app_product_type_sequence/static/description/index.html b/app_product_type_sequence/static/description/index.html new file mode 100644 index 00000000..ecb4de17 --- /dev/null +++ b/app_product_type_sequence/static/description/index.html @@ -0,0 +1,171 @@ +
+
+

App Product Auto Sequence, Auto Code(Variants Supported), Auto Attributes

+
+

+ This module allows to associate a sequence to the product reference.
+ The reference (default code) is unique (SQL constraint) and required.
+ Support Product with or without Variants. +

+
    +
  • + Auto Sequence or code for every product. +
  • +
  • + Auto Sequence or for every product variants, like product20171130-001. +
  • +
  • + Product code must be Unique. +
  • +
  • + Define different product type, each product type use own rule of sequence. +
  • +
  • + Quick access in sale , inventory, system menu. +
  • +
  • + Multi language support. +
  • +
  • + Setup default Auto Sequence for each product category. +
  • +
  • + Auto setup product attribute lik Sale/Purchase, Stockable/Consumable/Service, Stock Routes. +
  • +
+
+ +
+
+ +
+
+ +
+

Sample Rule: if we create on oct 2017

+
    +
  • + Manufactured Products: M20171100001 +
  • +
  • + Components Products: C20171100001 +
  • +
  • + Sourced Products: S20171100001 +
  • +
+

+ Sepcial for variants. add [-00?]
+

    +
  • + Products with color[red]: M20171100001#001 +
  • +
  • + Products with color[blue]: M20171100001#002 +
  • +
  • + Products with color[white]: M20171100001#003 +
  • +
+

+

Installation:

+

+ Prior to installing this module, if you have any existing products you should ensure they already have a + unique reference (or no reference) set.
+ Products with a default_code of '/' or empty will automatically be assigned a code of "!!DP!!" followed + by the system id for that product.
+ Otherwise the setting of the unique constraint will fail and the module will fail to install.
+ + Notice:
+ Odoo product variants is very special.
+ When u create a product(not product template) with attribute, It would delete the first product, which + have no attribute. + So it's very normal that the first product variants begin wit ???-002.
+ And we make a rule that the product variants can only create after you create normal product template. +

+

How to use: Very simple

+

+ After installed the app. You can Go to anyone of the menu:
+

    +
  • + Sales->Configuration->Products->Product Internal Type +
  • +
  • + Inventory->Configuration->Products->Product Internal Type +
  • +
  • + Settings->Sequences & Identifiers->Product Internal Type +
  • +
+

+

+ You would see the default Product Intertype we create. + +

+ +
+

+

+ And create the product and code by yourself. +

+ +
+

+

+ Notice: The "Sequence Code" Field of sequence must be "product.product" +

+ +
+

+ Go to Prior to installing this module, if you have any existing products you should ensure they already have + a + unique reference (or no reference) set.
+ Products with a default_code of '/' or empty will automatically be assigned a code of "!!DP!!" followed + by the system id for that product.
+ Otherwise the setting of the unique constraint will fail and the module will fail to install.
+ + Notice:
+ Odoo product variants is very special.
+ When u create a product(not product template) with attribute, It would delete the first product, which + have no attribute. + So it's very normal that the first product variants begin wit ???-002.
+ And we make a rule that the product variants can only create after you create normal product template. +

+
+
+
+ +
+
+ +
+
+
+

Technical Help & Support

+
+
+
+

+ For any type of technical help & support requests, Feel free to contact us

+ + guohuadeng@hotmail.com +

+ Via QQ: 300883

+ + 300883@qq.com +
+
+

+ Visit our website for more support.

+ + http://www.sunpop.cn +
+
+
+
\ No newline at end of file diff --git a/app_product_type_sequence/static/description/set0.jpg b/app_product_type_sequence/static/description/set0.jpg new file mode 100644 index 00000000..7cf34652 Binary files /dev/null and b/app_product_type_sequence/static/description/set0.jpg differ diff --git a/app_product_type_sequence/static/description/set1.jpg b/app_product_type_sequence/static/description/set1.jpg new file mode 100644 index 00000000..77910e22 Binary files /dev/null and b/app_product_type_sequence/static/description/set1.jpg differ diff --git a/app_product_type_sequence/static/description/set2.jpg b/app_product_type_sequence/static/description/set2.jpg new file mode 100644 index 00000000..f05874e3 Binary files /dev/null and b/app_product_type_sequence/static/description/set2.jpg differ diff --git a/app_product_type_sequence/static/description/set3.jpg b/app_product_type_sequence/static/description/set3.jpg new file mode 100644 index 00000000..78c9e415 Binary files /dev/null and b/app_product_type_sequence/static/description/set3.jpg differ diff --git a/app_product_type_sequence/static/description/set4.jpg b/app_product_type_sequence/static/description/set4.jpg new file mode 100644 index 00000000..f2d148cf Binary files /dev/null and b/app_product_type_sequence/static/description/set4.jpg differ diff --git a/app_product_type_sequence/static/description/set5.jpg b/app_product_type_sequence/static/description/set5.jpg new file mode 100644 index 00000000..2d422293 Binary files /dev/null and b/app_product_type_sequence/static/description/set5.jpg differ diff --git a/app_product_type_sequence/tests/__init__.py b/app_product_type_sequence/tests/__init__.py new file mode 100644 index 00000000..269a938e --- /dev/null +++ b/app_product_type_sequence/tests/__init__.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- +''' +Created on 2017-10-28 +@author: 广州尚鹏,http://www.sunpop.cn +@email: 300883@qq.com +@resource of Sunpop +Odoo10离线中文用户手册下载 +http://www.sunpop.cn/odoo10_user_manual_document_offline/ +Odoo10离线开发手册下载-含python教程,jquery参考,Jinja2模板,PostgresSQL参考(odoo开发必备) +http://www.sunpop.cn/odoo10_developer_document_offline/ + +@description: +''' + +from . import test_product_sequence diff --git a/app_product_type_sequence/tests/test_product_sequence.py b/app_product_type_sequence/tests/test_product_sequence.py new file mode 100644 index 00000000..f275be4f --- /dev/null +++ b/app_product_type_sequence/tests/test_product_sequence.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +''' +Created on 2017-10-28 +@author: 广州尚鹏,http://www.sunpop.cn +@email: 300883@qq.com +@resource of Sunpop +Odoo10离线中文用户手册下载 +http://www.sunpop.cn/odoo10_user_manual_document_offline/ +Odoo10离线开发手册下载-含python教程,jquery参考,Jinja2模板,PostgresSQL参考(odoo开发必备) +http://www.sunpop.cn/odoo10_developer_document_offline/ + +@description: +''' + +from odoo.tests.common import TransactionCase +from ..hooks import pre_init_hook + + +class TestProductSequence(TransactionCase): + """Tests for creating product with and without Product Sequence""" + + def setUp(self): + super(TestProductSequence, self).setUp() + self.product_product = self.env['product.product'] + + def test_product_create_with_default_code(self): + product = self.product_product.create(dict( + name="Apple", + default_code='PROD01' + )) + self.assertEqual(product.default_code, 'PROD01') + + def test_product_create_without_default_code(self): + product_1 = self.product_product.create(dict( + name="Orange", + default_code='/')) + self.assertRegexpMatches(str(product_1.default_code), r'PR/*') + + def test_product_copy(self): + product_2 = self.product_product.create(dict( + name="Apple", + default_code='PROD02' + )) + copy_product_2 = product_2.copy() + self.assertEqual(copy_product_2.default_code, 'PROD02-copy') + + def test_pre_init_hook(self): + product_3 = self.product_product.create(dict( + name="Apple", + default_code='PROD03' + )) + self.cr.execute( + "update product_product set default_code='/' where id=%s" + % (product_3.id,)) + product_3.invalidate_cache() + self.assertEqual(product_3.default_code, '/') + pre_init_hook(self.cr) + product_3.invalidate_cache() + self.assertEqual(product_3.default_code, '!!mig!!%s' % (product_3.id,)) diff --git a/app_product_type_sequence/views/product_category_view.xml b/app_product_type_sequence/views/product_category_view.xml new file mode 100644 index 00000000..80cfcf4f --- /dev/null +++ b/app_product_type_sequence/views/product_category_view.xml @@ -0,0 +1,27 @@ + + + + + + product.category.list.internal_type + product.category + + + + + + + + + + product.category.form._internal_type + product.category + + + + + + + + + diff --git a/app_product_type_sequence/views/product_internal_type_view.xml b/app_product_type_sequence/views/product_internal_type_view.xml new file mode 100644 index 00000000..82bb18fc --- /dev/null +++ b/app_product_type_sequence/views/product_internal_type_view.xml @@ -0,0 +1,81 @@ + + + + + + product.internal.type.tree + product.internal.type + + + + + + + + + + + + + + + + + + product.internal.type.form + product.internal.type + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + Product Internal Type + ir.actions.act_window + product.internal.type + tree,form + + + + + + + + + + +
+
diff --git a/app_product_type_sequence/views/product_product_view.xml b/app_product_type_sequence/views/product_product_view.xml new file mode 100644 index 00000000..834bb3ef --- /dev/null +++ b/app_product_type_sequence/views/product_product_view.xml @@ -0,0 +1,16 @@ + + + + + + product.product.tree + product.product + + + + + + + + + diff --git a/app_product_type_sequence/views/product_template_view.xml b/app_product_type_sequence/views/product_template_view.xml new file mode 100644 index 00000000..a26a5e81 --- /dev/null +++ b/app_product_type_sequence/views/product_template_view.xml @@ -0,0 +1,54 @@ + + + + + + product.template.product.tree + product.template + + + + + + + + + + product.template.common.form + product.template + + + +
+

+

+
+
+
+
+ + + Products + ir.actions.act_window + product.template + tree,kanban,form + form + + {"search_default_filter_to_sell":1} + +

+ Click to define a new product. +

+

+ You must define a product for everything you sell, whether it's a physical product, a consumable or a service you offer to customers. +

+

+ The product form contains information to simplify the sale process: price, notes in the quotation, accounting data, procurement methods, + etc. +

+
+
+
+
diff --git a/app_product_type_sequence/产品自动生成唯一编码自动输入关键属性-支持多规格.txt b/app_product_type_sequence/产品自动生成唯一编码自动输入关键属性-支持多规格.txt new file mode 100644 index 00000000..4e5f1474 --- /dev/null +++ b/app_product_type_sequence/产品自动生成唯一编码自动输入关键属性-支持多规格.txt @@ -0,0 +1,18 @@ +App Product Auto Sequence, Auto Code(Variants Supported) + + + App Product Auto Sequence, Auto Code(Variants Supported), Auto Attributes + + This module allows to associate a sequence to the product reference.
+ The reference (default code) is unique (SQL constraint) and required.
+ Support Product with or without Variants. + 1.Auto Sequence or code for every product.自动产品编码。 + 2.Auto Sequence or for every product variants, like product20171130-001.自动多规格产品编码,形式为 主产品编码-001。 + 3.Product code must be Unique.产品编码强制要求唯一。 + 4.Define different product type, each product type use own rule of sequence.可自定义产品类型,不同产品类型使用不同编码规则。 + 5.Quick access in sale , inventory, system menu.可以在销售、库存、系统菜单中快速定义。 + 6.Multi language support.
多语种支持。 + 7.Setup default Auto Sequence for each product category,自动设置每个产品目录使用的产品编码规则 + 8.Auto setup product attribute lik Sale/Purchase, Stockable/Consumable/Service, Stock Routes. 自动设置产品的销售/采购,可库存产品/服务/消耗品,购买/制造/按订单生成等库存路线 + +http://www.sunpop.cn/product/app-product-auto-sequence-auto-codevariants-supported/