Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
*.pyc
*.py~
.cache
.idea
.project
.pydevproject
.sync
.settings
/docs/_build
/_bin
Thumbs.db
*/ghostdriver.log
*.csv
/output
.venv
/build
/dist
/log
*.spec
*.json
*.xml
/node_modules
4 changes: 4 additions & 0 deletions product_unique_serial_picking/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Product Unique Serial Number
==================
Add a field to product to activate check if is a product unique serial number.
Add a check constraint to deny stock moves with quantity different to 1 if has unique serial number as True.
3 changes: 3 additions & 0 deletions product_unique_serial_picking/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
import model
import wizard
19 changes: 19 additions & 0 deletions product_unique_serial_picking/__openerp__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
{
'name': "Product Serial Unique Number Picking",
'author': "vauxoo",
'website': "http://www.vauxoo.com",
'category': 'stock',
'version': '1.0',
'depends': ['stock_no_negative'],
'data': [
'wizard/product_serial_wizard.xml',
"views/product_view.xml",
"views/stock_view.xml",
],
'demo': [
"demo/test_demo.xml",
],
'installable': True,
'auto_install': False,
}
45 changes: 45 additions & 0 deletions product_unique_serial_picking/demo/test_demo.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="0">

<!-- Products -->

<record id="product_demo_1" model="product.product">
<field name="name">Huawei Ascend</field>
<field name="track_all" eval="True"/>
<field name="check_no_negative" eval="False"/>
<field name="categ_id" ref="product.product_category_all"/>
<field name="lot_unique_ok" eval="True"/>
<field name="standard_price">75.50</field>
<field name="list_price">82.25</field>
</record>

<record id="product_demo_2" model="product.product">
<field name="name">Nokia 2630</field>
<field name="track_all" eval="True"/>
<field name="check_no_negative" eval="True"/>
<field name="categ_id" ref="product.product_category_all"/>
<field name="lot_unique_ok" eval="True"/>
<field name="standard_price">35.50</field>
<field name="list_price">42.28</field>
</record>

<!-- Sales Orders -->

<record id="serial_number_demo_1" model="stock.production.lot">
<field name="name">86137801852514</field>
<field name="product_id" ref="product_demo_1"/>
</record>

<record id="serial_number_demo_2" model="stock.production.lot">
<field name="name">86137801852515</field>
<field name="product_id" ref="product_demo_1"/>
</record>

<record id="serial_number_demo_3" model="stock.production.lot">
<field name="name">86137801852516</field>
<field name="product_id" ref="product_demo_1"/>
</record>

</data>
</openerp>
3 changes: 3 additions & 0 deletions product_unique_serial_picking/model/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
import product
import stock
12 changes: 12 additions & 0 deletions product_unique_serial_picking/model/product.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# -*- coding: utf-8 -*-
from openerp import fields, models


class ProductTemplate(models.Model):
_inherit = 'product.template'

lot_unique_ok = fields.Boolean('Unique lot',
help='Forces set qty=1 '
'to specify a Unique '
'Serial Number for '
'all moves')
98 changes: 98 additions & 0 deletions product_unique_serial_picking/model/stock.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# -*- coding: utf-8 -*-

from openerp import _, api, fields, exceptions, models


class StockProductionLot(models.Model):
_inherit = 'stock.production.lot'

@api.one
@api.depends('quant_ids')
def _get_last_location_id(self):
last_quant_data = self.env['stock.quant'].search_read(
[('id', 'in', self.quant_ids.ids)],
['location_id'],
order='in_date DESC, id DESC',
limit=1)
if last_quant_data:
self.last_location_id = last_quant_data[0][
'location_id'][0]
else:
self.last_location_id = False

last_location_id = fields.Many2one(
'stock.location',
string="Last location",
compute='_get_last_location_id',
store=True) # TODO: Fix fails recomputed

# Overwrite field to deny create serial number duplicated
ref = fields.Char('Internal Reference',
help="Internal reference number"
" in this case it"
" is same of manufacturer's"
" serial number",
related="name", store=True, readonly=True)


class StockMove(models.Model):
_inherit = 'stock.move'

def check_after_action_done(self, cr, uid, operation_or_move,
lot_id=None, context=None):
super(StockMove, self).check_after_action_done(
cr, uid, operation_or_move,
lot_id, context=context)
return self.check_unicity_qty_available(
cr, uid, operation_or_move,
lot_id, context=context)

def check_unicity_move_qty(self, cr, uid, ids, context=None):
"""
Check move quantity to verify that has qty = 1
if 'lot unique' is ok on product
"""
if not isinstance(ids, list):
ids = [ids]
for move in self.browse(cr, uid, ids, context=context):
if move.product_id.lot_unique_ok:
for move_operation in \
move.linked_move_operation_ids:
if abs(move_operation.qty) > 1:
raise exceptions.ValidationError(_(
"Product '%s' has active"
" 'unique lot' "
"but has qty > 1"
) % (move.product_id.name))

def check_unicity_qty_available(self, cr, uid, operation_or_move,
lot_id,
context=None):
"""
Check quantity on hand to verify that has qty = 1
if 'lot unique' is ok on product
"""
if operation_or_move.product_id.lot_unique_ok and lot_id:
ctx = context.copy()
ctx.update({'lot_id': lot_id})
product_ctx = self.pool.get('product.product').browse(
cr, uid, [operation_or_move.product_id.id],
context=ctx)[0]
qty = product_ctx.qty_available
if not 0 <= qty <= 1:
lot = self.pool.get('stock.production.lot').browse(
cr, uid, [lot_id])[0]
raise exceptions.ValidationError(_(
"Product '%s' has active "
"'unique lot'\n"
"but with this move "
"you will have a quantity of "
"'%s' in lot '%s'"
) % (operation_or_move.product_id.name, qty, lot.name))
return True

def check_tracking(self, cr, uid, move, lot_id, context=None):
res = super(StockMove, self).check_tracking(
cr, uid, move, lot_id, context=context)
self.check_unicity_move_qty(cr, uid, [move.id], context=context)
return res
Loading