[ADD] new module crm_rma_prodlot_supplier

This commit is contained in:
Yanina Aular (Vauxoo)
2015-10-19 16:32:41 -04:30
parent feb1eda708
commit df07d7b3b6
15 changed files with 700 additions and 0 deletions

View File

@@ -0,0 +1,71 @@
.. 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
============================
CRM RMA Product Lot Supplier
============================
It allows to know the real supplier for a specific product having beforehand its serial/lot number simplifying obtaining it.
For example, when creating/editing a claim for a laptop that it may have two o more suppliers, using this module (taking advantage of lot number) let you know which supplier has provided which specific product related to the claim, or use time frame given by supplier or its address based on stored information about supplier without any aditional steps.
Installation
============
To install this module, just select it from availables modules
Configuration
=============
No configuration is needed
Usage
=====
When a warehouse transfer is made, the supplier field for the product lot is automatically filled.
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/145/8.0
For further information, please visit:
* https://www.odoo.com/forum/help-1
Known issues / Roadmap
======================
* The functionalities contained in this module only applies for Invoice Control: Based on generated draft invoices and Based on incoming shipments
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/rma/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed feedback
`here <https://github.com/OCA/rma/issues/new?body=module:%20crm_rma_prodlot_supplier%0Aversion:%208.0.1.0.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Credits
=======
Contributors
------------
* Yanina Aular <yanina.aular@vauxoo.com>
* Osval Reyes <osval@vauxoo.com>
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 http://odoo-community.org.

View File

@@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright 2015 Vauxoo
# Author: Yanina Aular, Osval Reyes
#
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
from . import models

View File

@@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright 2015 Vauxoo
# Author: Yanina Aular, Osval Reyes
#
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
{
'name': 'Claim Prodlot Supplier',
'version': '8.0.1.0.0',
'author': 'Vauxoo,Odoo Community Association (OCA)',
'website': 'http://www.vauxoo.com/',
'category': 'RMA',
'license': 'AGPL-3',
'depends': [
'stock',
'crm_claim',
'purchase',
],
'data': [
'views/stock_view.xml',
],
'installable': True,
}

View File

@@ -0,0 +1,36 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * crm_rma_prodlot_supplier
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 8.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-07-17 19:57+0000\n"
"PO-Revision-Date: 2015-07-17 19:57+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: crm_rma_prodlot_supplier
#: model:ir.model,name:crm_rma_prodlot_supplier.model_stock_production_lot
msgid "Lot/Serial"
msgstr ""
#. module: crm_rma_prodlot_supplier
#: model:ir.model,name:crm_rma_prodlot_supplier.model_stock_transfer_details
msgid "Picking wizard"
msgstr ""
#. module: crm_rma_prodlot_supplier
#: field:stock.production.lot,supplier_id:0
msgid "Supplier"
msgstr ""
#. module: crm_rma_prodlot_supplier
#: help:stock.production.lot,supplier_id:0
msgid "Supplier of good in claim"
msgstr ""

View File

@@ -0,0 +1,36 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * crm_rma_prodlot_supplier
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 8.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-07-17 19:57+0000\n"
"PO-Revision-Date: 2015-07-17 19:57+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: crm_rma_prodlot_supplier
#: model:ir.model,name:crm_rma_prodlot_supplier.model_stock_production_lot
msgid "Lot/Serial"
msgstr "Lote/No. de Serie"
#. module: crm_rma_prodlot_supplier
#: model:ir.model,name:crm_rma_prodlot_supplier.model_stock_transfer_details
msgid "Picking wizard"
msgstr "Asistente de albarán"
#. module: crm_rma_prodlot_supplier
#: field:stock.production.lot,supplier_id:0
msgid "Supplier"
msgstr "Proveedor"
#. module: crm_rma_prodlot_supplier
#: help:stock.production.lot,supplier_id:0
msgid "Supplier of good in claim"
msgstr "Proveedor del producto en la reclamación"

View File

@@ -0,0 +1,16 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * crm_rma_prodlot_supplier
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 8.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-07-17 19:57+0000\n"
"PO-Revision-Date: 2015-07-17 19:57+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"

View File

@@ -0,0 +1,16 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * crm_rma_prodlot_supplier
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 8.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-07-17 19:57+0000\n"
"PO-Revision-Date: 2015-07-17 19:57+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"

View File

@@ -0,0 +1,21 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * crm_rma_prodlot_supplier
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 8.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-07-17 19:57+0000\n"
"PO-Revision-Date: 2015-07-17 19:57+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: crm_rma_prodlot_supplier
#: help:stock.production.lot,supplier_id:0
msgid "Supplier of good in claim"
msgstr "Proveedor del producto en el reclamo"

View File

@@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright 2015 Vauxoo
# Author: Yanina Aular, Osval Reyes
#
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
from . import stock_production_lot
from . import stock_transfer_details
from . import stock_picking

View File

@@ -0,0 +1,56 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright 2015 Vauxoo
# Author: Yanina Aular
#
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp import api, models
class StockPicking(models.Model):
_inherit = 'stock.picking'
@api.multi
def action_invoice_create(self, journal_id,
group=False, type='out_invoice'):
invoices = super(StockPicking, self).\
action_invoice_create(journal_id=journal_id,
group=group,
type=type)
if type == 'in_invoice':
prodlot_obj = self.env['stock.production.lot']
for picking in self:
for move in picking.move_lines:
if move and move.quant_ids:
lot = move.quant_ids[0].lot_id
if lot.supplier_invoice_line_id:
continue
for inv_id in invoices:
for inv_line in self.env['account.invoice'].\
browse(inv_id).invoice_line:
lots = prodlot_obj.\
search([('supplier_invoice_line_id',
'=',
inv_line.id)])
if inv_line.product_id.id == \
lot.product_id.id and \
len(lots) < inv_line.quantity:
lot.write({'supplier_invoice_line_id':
inv_line.id})
return invoices

View File

@@ -0,0 +1,84 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright 2015 Vauxoo
# Author: Yanina Aular, Osval Reyes
#
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp import api, fields, models
class StockProductionLot(models.Model):
_inherit = 'stock.production.lot'
supplier_id = fields.Many2one('res.partner', string='Supplier',
help="Supplier of good in claim")
supplier_invoice_line_id = \
fields.Many2one('account.invoice.line',
string='Supplier Invoice Line',
help="Supplier invoice with the "
"purchase of goods sold to "
"customer")
@api.model
def default_get(self, fields_list):
"""
Set partner when product lot is created
@param fields_list: record values
@return: return record
"""
res = super(StockProductionLot, self).default_get(fields_list)
prodlot_obj = self.env['stock.production.lot']
transfer_item_id = self._context.get('active_id', False)
if not transfer_item_id:
return res
picking = self.env['stock.transfer_details_items'].\
browse(transfer_item_id)
if picking.transfer_id.picking_id.picking_type_id.code != 'incoming':
return res
partner_id = picking.transfer_id.picking_id.partner_id
for move_line in picking.transfer_id.picking_id.move_lines:
if res.get('product_id') != move_line.product_id.id:
continue
lots = prodlot_obj.search([
('supplier_invoice_line_id',
'in', move_line.purchase_line_id.invoice_lines.mapped('id'))
])
if len(lots) < move_line.purchase_line_id.product_qty:
for inv_line in move_line.purchase_line_id.invoice_lines:
lots = prodlot_obj.\
search([('supplier_invoice_line_id',
'=', inv_line.id)])
if len(lots) < inv_line.quantity and \
inv_line.product_id.id == res.get('product_id'):
res.update({'supplier_invoice_line_id': inv_line.id})
if partner_id:
res.update({'supplier_id': partner_id.id})
return res

View File

@@ -0,0 +1,76 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright 2015 Vauxoo
# Author: Yanina Aular, Osval Reyes
#
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp import api, models
class StockTransferDetails(models.TransientModel):
_inherit = 'stock.transfer_details'
@api.multi
def do_detailed_transfer(self):
"""
When incoming type transfer are made and stock move have serial/lot
number, the supplier is assigned to the serial/lot number taken from
picking.
@return: do_detailed_transfer boolean results
"""
prodlot = self.env['stock.production.lot']
if self.picking_id.picking_type_id.code != 'incoming':
return super(StockTransferDetails, self).do_detailed_transfer()
for items_packs_ids in [self.item_ids, self.packop_ids]:
for prod in items_packs_ids:
lot_id = prod.lot_id
if not lot_id:
continue
if not lot_id.supplier_id:
lot_id.write({
'supplier_id': self.picking_id.partner_id.id
})
for move_id in self.picking_id.move_lines:
if lot_id.product_id.id != move_id.product_id.id:
continue
lots = prodlot.search([
('supplier_invoice_line_id',
'in',
move_id.purchase_line_id.invoice_lines.mapped('id'))
])
if len(lots) < move_id.purchase_line_id.product_qty:
for inv_line in move_id.purchase_line_id.invoice_lines:
lots = prodlot.search([('supplier_invoice_line_id',
'=', inv_line.id)])
if len(lots) < inv_line.quantity and \
inv_line.product_id.id == \
lot_id.product_id.id:
lot_id.write({
'supplier_invoice_line_id': inv_line.id
})
return super(StockTransferDetails, self).do_detailed_transfer()

View File

@@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright 2015 Vauxoo
# Author: Yanina Aular, Osval Reyes
#
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
from . import test_crm_rma_prodlot_supplier

View File

@@ -0,0 +1,152 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright 2015 Vauxoo
# Author: Yanina Aular, Osval Reyes
#
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp.tests.common import TransactionCase
from datetime import date
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
class TestCrmRmaProdLotSupplier(TransactionCase):
def setUp(self):
super(TestCrmRmaProdLotSupplier, self).setUp()
self.picking = self.env['stock.picking']
self.wizard = self.env['stock.transfer_details']
self.wizard_item = self.env['stock.transfer_details_items']
self.production_lot = self.env['stock.production.lot']
self.purchase_order = self.env['purchase.order']
self.product_id = self.env['product.product'].\
browse(self.ref('product.product_product_8'))
self.purchase_order_id = self.create_purchase_order()
def create_purchase_order(self):
purchase_order_id = self.purchase_order.create({
'partner_id': self.ref('base.res_partner_1'),
'location_id': self.ref('stock.picking_type_in'),
'pricelist_id': 1,
'order_line': [(0, 0, {
'name': 'test',
'product_id': self.product_id.id,
'price_unit': self.product_id.list_price,
'product_qty': 16,
'date_planned': date.today().replace(day=31, month=12).
strftime(DEFAULT_SERVER_DATETIME_FORMAT),
})]
})
purchase_order_id.wkf_confirm_order()
purchase_order_id.action_invoice_create()
purchase_order_id.action_picking_create()
self.assertEquals(purchase_order_id.state, 'confirmed')
self.assertEquals(1, len(self.picking.
search([('origin', '=',
purchase_order_id.name)])))
self.picking_ids = purchase_order_id.picking_ids
return purchase_order_id
def test_01_do_detail_transfer(self):
"""
Testing do_detailed_transfer method
"""
lot_ids = []
for picking_id in self.picking_ids:
# create wizard
wizard_id = self.wizard.create({
'picking_id': picking_id.id,
})
# make the transfers
for move_id in picking_id.move_lines:
lot_id = self.production_lot.create({
'product_id': move_id.product_id.id,
})
self.wizard_item.create({
'transfer_id': wizard_id.id,
'product_id': move_id.product_id.id,
'quantity': move_id.product_qty,
'sourceloc_id': move_id.location_id.id,
'destinationloc_id':
self.ref('stock.stock_location_stock'),
'lot_id': lot_id.id,
'product_uom_id': move_id.product_uom.id,
})
# keep lot_id for later check
lot_ids.append(lot_id)
wizard_id.do_detailed_transfer()
# check lot_ids
failed_lot_ids = [
lid for lid in lot_ids
if not lid.supplier_id or not
lid.supplier_invoice_line_id]
self.assertEquals(failed_lot_ids, [])
def test_02_default_get(self):
"""
Test default_get method
"""
failed_lot_ids = lot_ids = []
# make the transfers
for picking_id in self.picking_ids:
wizard_id = self.wizard.create({
'picking_id': picking_id.id
})
for move_id in picking_id.move_lines:
wizard_item_id = self.wizard_item.create({
'transfer_id': wizard_id.id,
'product_id': move_id.product_id.id,
'quantity': move_id.product_qty,
'sourceloc_id': move_id.location_id.id,
'destinationloc_id':
self.ref('stock.stock_location_stock'),
'lot_id': False,
'product_uom_id': move_id.product_uom.id,
})
lot_id = self.production_lot.with_context({
'active_model': wizard_item_id._name,
'active_id': wizard_item_id.id,
'product_id': move_id.product_id.id
}).create({
'name': 'Transfer for ' + self.purchase_order_id.name
})
# keep lot_id for later check
lot_ids.append(lot_id)
wizard_id.do_detailed_transfer()
# check lot_ids
failed_lot_ids = [
lid for lid in lot_ids
if not lid.supplier_id or not
lid.supplier_invoice_line_id]
self.assertEquals(failed_lot_ids, [])

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_production_lot_form_supplier" model="ir.ui.view">
<field name="name">lot.supplier</field>
<field name="model">stock.production.lot</field>
<field name="inherit_id" ref="stock.view_production_lot_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='product_id']" position="after">
<field name="supplier_id" readonly="1"/>
<field name="supplier_invoice_line_id" readonly="1"/>
</xpath>
</field>
</record>
<record id="view_lot_form_supplier_context" model="ir.ui.view">
<field name="name">lot.supplier.context</field>
<field name="model">stock.transfer_details</field>
<field name="inherit_id" ref="stock.view_stock_enter_transfer_details"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='item_ids']" position="before">
<field name="picking_id" invisible="1"/>
</xpath>
<xpath expr="//field[@name='item_ids']/tree/field[@name='lot_id']" position="attributes">
<attribute name="context">{'product_id': product_id,
'active_id': active_id}</attribute>
</xpath>
</field>
</record>
</data>
</openerp>