diff --git a/product_customer_code/README.rst b/product_customer_code/README.rst new file mode 100644 index 00000000000..00448f3eba2 --- /dev/null +++ b/product_customer_code/README.rst @@ -0,0 +1,85 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +===================== +Product Customer Code +===================== + +Provide products with customer specific codes + + +Installation +============= + + No external library is used. + + + +Configuration +============= + + No configuration is required. + + +Usage +===== + +To use this module, you need to navigate on the product variant form view and +add the customer specific codes. + +Make sure your user has permissions to Manage Variants. + +If you want to make a field searchable by the customer code you must pass the +partner/customer via context since the product and partner are both required in +the creation of a customer code. + + +e.g: +``` + + +``` + + +Known issues / Roadmap +====================== + +* None + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues +`_. In case of trouble, please +check there if your issue has already been reported. If you spotted it first, +help us smash it by providing detailed and welcomed feedback. + +Credits +======= + +Images +------ + +* Odoo Community Association: `Icon `_. + +Contributors +------------ + +* Vauxoo +* Paul Catinean + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +To contribute to this module, please visit https://odoo-community.org. \ No newline at end of file diff --git a/product_customer_code/__init__.py b/product_customer_code/__init__.py index df5910868b4..567548c78f5 100644 --- a/product_customer_code/__init__.py +++ b/product_customer_code/__init__.py @@ -1,2 +1,4 @@ -import product_customer_code -import product +# -*- coding: utf-8 -*- + +from . import models +from . import tests diff --git a/product_customer_code/__manifest__.py b/product_customer_code/__manifest__.py index af8cd13e819..e0ed03fe83d 100644 --- a/product_customer_code/__manifest__.py +++ b/product_customer_code/__manifest__.py @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- ########################################################################### # Module Writen to OpenERP, Open Source Management Solution # @@ -8,53 +8,25 @@ ############################################################################ # Coded by: el_rodo_1 (rodo@vauxoo.com) ############################################################################ -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## + { "name": "Products Customer Code", - "version": "1.0", + "version": "10.0.1.0.0", "author": "Vauxoo,Odoo Community Association (OCA)", "website": "http://www.vauxoo.com/", "license": "AGPL-3", "category": "Generic Modules/Product", "summary": "Add many Customers' Codes in product", "depends": [ - "base", - "product", + "base", + "product", ], - "description": """ -Customer' codes in product -========================== - -This module does just like the product.supplierinfo but for customers instead. For instance it -allows to have different references for the same product according to the customer. - -.. image:: product_customer_code/static/src/img/screenshot1.png - -.. tip:: - - You will need install some of the Apps which enable the product menu to see this module in - action, like Sales, Purchase or Warehouse Management - """, "data": [ "security/product_customer_code_security.xml", "security/ir.model.access.csv", - "product_customer_code_view.xml", - "product_product_view.xml", + "views/product_customer_code_view.xml", + "views/product_product_view.xml", + "views/res_partner_view.xml", ], - "active": False, - 'installable': False, + 'installable': True, } diff --git a/product_customer_code/models/__init__.py b/product_customer_code/models/__init__.py new file mode 100644 index 00000000000..93301444ced --- /dev/null +++ b/product_customer_code/models/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- + +from . import product_customer_code +from . import product +from . import res_partner diff --git a/product_customer_code/models/product.py b/product_customer_code/models/product.py new file mode 100644 index 00000000000..0782da8eb2d --- /dev/null +++ b/product_customer_code/models/product.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +########################################################################### +# Module Writen to OpenERP, Open Source Management Solution +# +# Copyright (c) 2012 Vauxoo - http://www.vauxoo.com +# All Rights Reserved. +# info@vauxoo.com +############################################################################ +# Coded by: Rodo (rodo@vauxoo.com),Moy (moylop260@vauxoo.com) +############################################################################ + +from odoo import models, fields, api + + +class ProductProduct(models.Model): + _inherit = "product.product" + + product_customer_codes = fields.One2many( + comodel_name='product.customer.code', + inverse_name='product', + string='Customer Codes', + copy=False + ) + + @api.model + def name_search(self, name='', args=None, operator='ilike', limit=100): + res = super(ProductProduct, self).name_search( + name=name, args=args, operator=operator, limit=limit) + if not res: + partner_id = self._context.get('partner_id') + if partner_id: + product_customer_code_obj = self.env['product.customer.code'] + product_codes = product_customer_code_obj.search([ + ('product_code', '=', name), + ('partner', '=', partner_id) + ], limit=limit) + return product_codes.product.name_get() + return res + + @api.multi + def name_get(self): + res = super(ProductProduct, self).name_get() + partner_id = self._context.get('partner_id') + if partner_id: + product_customer_code_obj = self.env['product.customer.code'] + for product in self: + product_code = product_customer_code_obj.search([ + ('product', '=', product.id), + ('partner', '=', partner_id) + ], limit=1) + if product_code: + # convert tuple to list + lst = list(res[0]) + # change value in the list + lst[1] = res[0][1].__add__(' (').__add__( + product_code.product_code).__add__(')') + # convert list to tuple + res[0] = tuple(lst) + return res diff --git a/product_customer_code/models/product_customer_code.py b/product_customer_code/models/product_customer_code.py new file mode 100644 index 00000000000..66626c9e378 --- /dev/null +++ b/product_customer_code/models/product_customer_code.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +########################################################################### +# Module Writen to OpenERP, Open Source Management Solution +# +# Copyright (c) 2012 Vauxoo - http://www.vauxoo.com +# All Rights Reserved. +# info@vauxoo.com +############################################################################ +# Coded by: Rodo (rodo@vauxoo.com),Moy (moylop260@vauxoo.com) +############################################################################ + +from odoo import models, fields + + +class ProductCustomerCode(models.Model): + _name = "product.customer.code" + _description = "Add multiple product customer codes" + + _rec_name = 'product_code' + + product_code = fields.Char( + string='Customer Product Code', + required=True, + help="""This customer's product code will be used when searching into + a request for quotation.""", + ) + + product_name = fields.Char( + string='Customer Product Name', + help="""This customer's product name will be used when searching into + a request for quotation.""", + ) + + product = fields.Many2one( + comodel_name='product.product', + string='Product', + required=True, + ) + + partner = fields.Many2one( + comodel_name='res.partner', + string='Customer', + required=True + ) + + company = fields.Many2one( + comodel_name='res.company', + string='Company', + required=False, + default=lambda self: self.env['res.company']._company_default_get(), + ) + + _sql_constraints = [ + ('unique_code', 'unique(product_code,company,partner)', + 'Product customer code must be unique'), + ] + + # TODO: Add index to product_code, partner diff --git a/product_customer_code/models/res_partner.py b/product_customer_code/models/res_partner.py new file mode 100644 index 00000000000..f6b454154f1 --- /dev/null +++ b/product_customer_code/models/res_partner.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- + +from odoo import models, fields + + +class ResPartner(models.Model): + _inherit = 'res.partner' + + product_codes = fields.One2many( + comodel_name='product.customer.code', + inverse_name='partner', + string='Products' + ) diff --git a/product_customer_code/product.py b/product_customer_code/product.py deleted file mode 100644 index 350a66f23db..00000000000 --- a/product_customer_code/product.py +++ /dev/null @@ -1,73 +0,0 @@ -# -*- coding: utf-8 -*- -########################################################################### -# Module Writen to OpenERP, Open Source Management Solution -# -# Copyright (c) 2012 Vauxoo - http://www.vauxoo.com -# All Rights Reserved. -# info@vauxoo.com -############################################################################ -# Coded by: Rodo (rodo@vauxoo.com),Moy (moylop260@vauxoo.com) -############################################################################ -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## -from openerp.osv import orm, fields -from openerp.tools.translate import _ - - -class product_product(orm.Model): - _inherit = "product.product" - - _columns = { - 'product_customer_code_ids': fields.one2many('product.customer.code', - 'product_id', - 'Customer Codes'), - } - - def copy(self, cr, uid, id, default=None, context=None): - if not default: - default = {} - default['product_customer_code_ids'] = False - res = super(product_product, self).copy( - cr, uid, id, default=default, context=context) - return res - - def name_search(self, cr, user, name='', args=None, operator='ilike', - context=None, limit=80): - res = super(product_product, self).name_search( - cr, user, name, args, operator, context, limit) - if not context: - context = {} - product_customer_code_obj = self.pool.get('product.customer.code') - if not res: - ids = [] - partner_id = context.get('partner_id', False) - if partner_id: - id_prod_code = \ - product_customer_code_obj.search(cr, user, - [('product_code', - '=', name), - ('partner_id', '=', - partner_id)], - limit=limit, - context=context) - # TODO: Search for product customer name - id_prod = id_prod_code and product_customer_code_obj.browse( - cr, user, id_prod_code, context=context) or [] - for ppu in id_prod: - ids.append(ppu.product_id.id) - if ids: - res = self.name_get(cr, user, ids, context) - return res diff --git a/product_customer_code/product_customer_code.py b/product_customer_code/product_customer_code.py deleted file mode 100644 index d3593891a20..00000000000 --- a/product_customer_code/product_customer_code.py +++ /dev/null @@ -1,67 +0,0 @@ -# -*- coding: utf-8 -*- -########################################################################### -# Module Writen to OpenERP, Open Source Management Solution -# -# Copyright (c) 2012 Vauxoo - http://www.vauxoo.com -# All Rights Reserved. -# info@vauxoo.com -############################################################################ -# Coded by: Rodo (rodo@vauxoo.com),Moy (moylop260@vauxoo.com) -############################################################################ -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## -from openerp.osv import orm, fields -from openerp.tools.translate import _ - - -class product_customer_code(orm.Model): - _name = "product.customer.code" - _description = "Add manies Code of Customer's" - - _rec_name = 'product_code' - - _columns = { - 'product_code': fields.char('Customer Product Code', size=64, - required=True, - help="""This customer's product code - will be used when searching into - a request for quotation."""), - 'product_name': fields.char('Customer Product Name', size=128, - help="""This customer's product name will - be used when searching into a - request for quotation."""), - 'product_id': fields.many2one('product.product', 'Product', - required=True), - 'partner_id': fields.many2one('res.partner', 'Customer', - required=True), - 'company_id': fields.many2one('res.company', 'Company', - required=False), - } - - _defaults = { - 'company_id': lambda s, cr, - uid, c: s.pool.get('res.company'). - _company_default_get(cr, uid, - 'product.customer.code', - context=c), - } - - _sql_constraints = [ - ('unique_code', 'unique(product_code,company_id,partner_id)', - 'Product Code of customer must be unique'), - ] - - # TODO: Add index to product_code, partner_id diff --git a/product_customer_code/product_customer_code_view.xml b/product_customer_code/product_customer_code_view.xml deleted file mode 100644 index 0fddfd30f01..00000000000 --- a/product_customer_code/product_customer_code_view.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - view.product.customer.code.form - product.customer.code - -
- - - - - - -
- - - view.product.customer.code.tree - product.customer.code - - - - - - - - - - - - Product Customer Code - product.customer.code - form - - - - - view.product.customer.code.certificate.search - product.customer.code - - - - - - - - - - - - - - - - - - - -
-
diff --git a/product_customer_code/product_product_view.xml b/product_customer_code/product_product_view.xml deleted file mode 100644 index 3aec998b591..00000000000 --- a/product_customer_code/product_product_view.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - product.normal.form.inh.product.customer.code.01 - product.product - - - - - - - - - - -
- - - - -
-
-
-
- -
-
\ No newline at end of file diff --git a/product_customer_code/security/product_customer_code_security.xml b/product_customer_code/security/product_customer_code_security.xml index ebc3b409efc..48e4989c475 100644 --- a/product_customer_code/security/product_customer_code_security.xml +++ b/product_customer_code/security/product_customer_code_security.xml @@ -1,14 +1,14 @@ - + - - Product_Customer / Manager - + + Product_Customer / Manager + - - Product_Customer / User - + + Product_Customer / User + - + diff --git a/product_customer_code/static/src/description/index.html b/product_customer_code/static/src/description/index.html new file mode 100644 index 00000000000..29bf8d1600a --- /dev/null +++ b/product_customer_code/static/src/description/index.html @@ -0,0 +1,28 @@ +
+
+

Provide products with customer specific codes

+
+ +
+
+ +

+ This module is similar to product.supplierinfo but for customers. +

+
+
+ +

+ For instance it allows having different references to the same product + according to the customer. +

+
+
+ +

+ You will need install some of the Apps which enable the product menu to + see this module in action, like Sales, Purchase or Warehouse Management +

+
+
+
\ No newline at end of file diff --git a/product_customer_code/tests/__init__.py b/product_customer_code/tests/__init__.py new file mode 100644 index 00000000000..570c028813c --- /dev/null +++ b/product_customer_code/tests/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import test_product_customer_codes diff --git a/product_customer_code/tests/test_product_customer_codes.py b/product_customer_code/tests/test_product_customer_codes.py new file mode 100644 index 00000000000..61edbed910b --- /dev/null +++ b/product_customer_code/tests/test_product_customer_codes.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- + +from odoo.tests.common import TransactionCase + + +class TestCustomerCodes(TransactionCase): + + def setUp(self): + super(TestCustomerCodes, self).setUp() + self.product_ipad_mini = self.env.ref('product.product_product_6') + self.partner_agrolait = self.env.ref('base.res_partner_2') + + def test_name_search(self): + # Add customer code to iPad product + self.product_ipad_mini.write({ + 'product_customer_codes': [(0, 0, { + 'product_code': 'N9TT-9G0A-B7FQ-RANC', + 'partner': self.partner_agrolait.id, + })], + }) + + # Search product by customer code + product_obj = self.env['product.product'].with_context({ + 'partner_id': self.partner_agrolait.id + }) + products = product_obj.name_search('N9TT-9G0A-B7FQ-RANC') + self.assertTrue(len(products) == 1, + 'Searching by customer code should return one product') diff --git a/product_customer_code/views/product_customer_code_view.xml b/product_customer_code/views/product_customer_code_view.xml new file mode 100644 index 00000000000..ad820cf2d4f --- /dev/null +++ b/product_customer_code/views/product_customer_code_view.xml @@ -0,0 +1,59 @@ + + + + + view.product.customer.code.form + product.customer.code + +
+ + + + + + +
+ + + view.product.customer.code.tree + product.customer.code + + + + + + + + + + + + Product Customer Code + product.customer.code + form + + + + + view.product.customer.code.certificate.search + product.customer.code + + + + + + + + + + + + + + + + + + + +
diff --git a/product_customer_code/views/product_product_view.xml b/product_customer_code/views/product_product_view.xml new file mode 100644 index 00000000000..55894ec26f7 --- /dev/null +++ b/product_customer_code/views/product_product_view.xml @@ -0,0 +1,28 @@ + + + + + product.normal.form.inh.product.customer.code.01 + product.product + + + + + + + + + +
+ + + + +
+
+
+
+
+
+ +
diff --git a/product_customer_code/views/res_partner_view.xml b/product_customer_code/views/res_partner_view.xml new file mode 100644 index 00000000000..1455cc3c383 --- /dev/null +++ b/product_customer_code/views/res_partner_view.xml @@ -0,0 +1,29 @@ + + + + + product.customer.code.partner.form.view.inherit + res.partner + + + + + + + + + +
+ + + + +
+
+
+
+ +
+
+ +