1
# -*- coding: utf-8 -*-
2
##############################################################################
4
# OpenERP, Open Source Management Solution
5
# Copyright (C) 2004-2011 Pexego (<www.pexego.es>). All Rights Reserved
6
# $Omar Castiñeira Saavedra$
8
# This program is free software: you can redistribute it and/or modify
9
# it under the terms of the GNU General Public License as published by
10
# the Free Software Foundation, either version 3 of the License, or
11
# (at your option) any later version.
13
# This program is distributed in the hope that it will be useful,
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
# GNU General Public License for more details.
18
# You should have received a copy of the GNU General Public License
19
# along with this program. If not, see <http://www.gnu.org/licenses/>.
21
##############################################################################
23
"""reasons to block production lots"""
25
from osv import osv, fields
28
from tools.translate import _
30
class block_prodlot_cases(osv.osv):
31
"""reasons to block production lots"""
32
_name = "block.prodlot.cases"
33
_description = "Blockade cases"
36
'name': fields.char('Name', size=64, required=True, states={'confirm':[('readonly', True)]}),
37
'description': fields.text('Description', required=True),
38
'blocked_prodlots_ids': fields.many2many('stock.production.lot', 'blocked_prodlots_cases_ids', 'case_id', 'blocked_prodlot', 'Blocked Prodlots', states={'confirm':[('readonly', True)]}),
39
'parent_block_prodlot': fields.many2one('stock.production.lot', 'Blockade Root', required=True, ondelete="set null", states={'confirm':[('readonly', True)]}),
40
'state': fields.selection([('in_review', 'In Review'), ('confirm', 'Confirm'), ('cancelled', 'Cancelled')], 'State', required=True, readonly=True)
47
def send_blockade_case_notification(self, cr, uid, case_id, state = 'in_review'):
48
"""send a notification to Production Lots / Blockade Notifications users for blockade cases"""
49
group_id = self.pool.get('res.groups').search(cr, uid, [('name', '=', 'Production Lots / Blockade Notifications')])
52
group_id = self.pool.get('res.groups').browse(cr, uid, group_id[0])
54
obj_case_id = self.browse(cr, uid, case_id)
55
#get a string comma list from object case prodlots collection
56
# pylint: disable-msg=W0141
57
lots_affected_names = u','.join(map(str, map(lambda x:x.name, obj_case_id.blocked_prodlots_ids)))
59
if state == 'in_review':
60
message = _("New production lots in review, will raise a warning meanwhile be in this state.\n\nLots names: %s\n\nBlockade Description: %s\n\n \
61
Blockade was raised from production_lot: %s.") % (lots_affected_names, obj_case_id.description, obj_case_id.parent_block_prodlot.name)
63
message = _("New production lots blocked. Now not can you use this prodlots definitely.\n\nLots names: %s\n\nBlockade Description: %s\n\n \
64
Blockade was raised from production_lot: %s.") % (lots_affected_names, obj_case_id.description, obj_case_id.parent_block_prodlot.name)
66
for user in group_id.user_ids:
67
self.pool.get('res.request').create(cr, uid, {
68
'name': _("Blockade Case %s: %s") % (obj_case_id.id, obj_case_id.name),
73
'ref_doc1': 'block.prodlot.cases,%d' % (obj_case_id.id,),
81
def confirm_blockade_case(self, cr, uid, ids, context = None):
82
"""confirm blockade case and block definitely prodlots in alert affected by case"""
83
if context is None: context = {}
85
if isinstance(ids, (int, long)):
88
for obj_block_prodlot_case_id in self.browse(cr, uid, ids):
90
for obj_blocked_prodlot_id in obj_block_prodlot_case_id.blocked_prodlots_ids:
91
#searches if prodlots have other blockade cases that interrumpt his blockade
92
cr.execute("select * from blocked_prodlots_cases_ids inner join block_prodlot_cases on id = case_id \
93
where blocked_prodlot = %s and case_id != %s and state not in ('confirm','cancelled')", (obj_blocked_prodlot_id.id, obj_block_prodlot_case_id.id))
95
#if prodlot have another blockade cases in review it cannot block
99
obj_real_report_prodlots_ids = self.pool.get('stock.report.prodlots').search(cr, uid, [('prodlot_id', '=', obj_blocked_prodlot_id.id),('qty','>',0)])
101
for obj_real_report_prodlots_id in self.pool.get('stock.report.prodlots').browse(cr, uid, obj_real_report_prodlots_ids):
103
if obj_real_report_prodlots_id.location_id.usage not in ('internal'):
106
move_id = self.pool.get('stock.move').create(cr, uid, {
107
'product_uom': obj_real_report_prodlots_id.product_id.uom_id.id,
108
'date' : time.strftime("%Y-%m-%d"),
109
'date_expected' : time.strftime("%Y-%m-%d"),
110
'prodlot_id': obj_blocked_prodlot_id.id,
111
'product_qty': obj_real_report_prodlots_id.qty,
112
'location_id': obj_real_report_prodlots_id.location_id.id,
113
'product_id': obj_real_report_prodlots_id.product_id.id,
114
'name': _("BLOCK: ") + obj_real_report_prodlots_id.prodlot_id.name + obj_real_report_prodlots_id.location_id.name,
116
'location_dest_id': obj_real_report_prodlots_id.product_id.product_tmpl_id.property_waste.id
119
created_move_ids.append(move_id)
121
#for update block and in_alert store attribute
122
self.pool.get('stock.production.lot').write(cr, uid, [obj_blocked_prodlot_id.id], {'date': time.strftime("%Y-%m-%d %H:%M:%S")})
125
picking_id = self.pool.get('stock.picking').create(cr, uid, {
126
'origin': _("BLOCKCASE:") + str(obj_block_prodlot_case_id.id),
129
'move_type': 'direct',
132
self.pool.get('stock.move').write(cr, uid, created_move_ids, {'picking_id': picking_id})
134
wf_service = netsvc.LocalService("workflow")
135
wf_service.trg_validate(uid, 'stock.picking', picking_id, 'button_confirm', cr)
137
self.write(cr, uid, [obj_block_prodlot_case_id.id], {
141
#send block notification to users
142
self.send_blockade_case_notification(cr, uid, obj_block_prodlot_case_id.id, 'confirm')
144
#for update block and in_alert store attribute
145
self.pool.get('stock.production.lot').write(cr, uid, [x.id for x in obj_block_prodlot_case_id.blocked_prodlots_ids], {})
148
def cancel_blockade_case(self, cr, uid, ids, context = None):
149
"""cancelled blockade cases"""
150
if context is None: context = {}
151
self.write(cr, uid, ids, {'state': 'cancelled'})
152
for obj_block_prodlot_case_id in self.browse(cr, uid, ids):
153
self.pool.get('stock.production.lot').write(cr, uid, [x.id for x in obj_block_prodlot_case_id.blocked_prodlots_ids], {})
156
def write(self, cr, uid, ids, vals, context = None):
157
"""overwrites write method for update production lots when case updating"""
158
if context is None: context = {}
161
if isinstance(ids, (int, long)):
164
for obj_case_id in self.browse(cr, uid, ids):
165
moves_to_update = list(set(moves_to_update + [x.id for x in obj_case_id.blocked_prodlots_ids]))
167
res = super(block_prodlot_cases, self).write(cr, uid, ids, vals, context)
169
self.pool.get('stock.production.lot').write(cr, uid, moves_to_update, {})
173
def create(self, cr, uid, vals, context = None):
174
"""overwrites this method to send notification informative with context of in alert prodlots and case"""
175
if context is None: context = {}
176
case_id = super(block_prodlot_cases, self).create(cr, uid, vals, context=context)
178
#send in_review notification
179
self.send_blockade_case_notification(cr, uid, case_id, 'in_review')
183
def unlink(self, cr, uid, ids, context = None):
184
"""overwrites unlink function to update prodlots_state"""
185
if context is None: context = {}
188
for blockade_case_id in self.browse(cr, uid, ids):
189
if blockade_case_id.state == 'confirm':
190
raise osv.except_osv(_("Warning!"), _("Can't delete confirmed blockade case."))
192
affected_lots.extend([x.id for x in blockade_case_id.blocked_prodlots_ids])
194
res = super(block_prodlot_cases, self).unlink(cr, uid, ids, context = context)
197
self.pool.get('stock.production.lot').write(cr, uid, affected_lots, {})
201
block_prodlot_cases()
203
class stock_production_lot(osv.osv):
204
"""inherit object to add many2many relationship with block.prodlot.cases"""
205
_inherit = "stock.production.lot"
208
'blocked_prodlots_cases_ids': fields.many2many('block.prodlot.cases', 'blocked_prodlots_cases_ids', 'blocked_prodlot', 'case_id', "Blockade Cases"),
211
stock_production_lot()