1
# -*- coding: utf-8 -*-
2
##############################################################################
4
# OpenERP, Open Source Management Solution
5
# Copyright (C) 2011 TeMPO Consulting, MSF
7
# This program is free software: you can redistribute it and/or modify
8
# it under the terms of the GNU Affero General Public License as
9
# published by the Free Software Foundation, either version 3 of the
10
# License, or (at your option) any later version.
12
# This program is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU Affero General Public License for more details.
17
# You should have received a copy of the GNU Affero General Public License
18
# along with this program. If not, see <http://www.gnu.org/licenses/>.
20
##############################################################################
23
from osv import fields
25
from tools.translate import _
28
class allocation_stock_setup(osv.osv_memory):
29
_name = 'allocation.stock.setup'
30
_inherit = 'res.config'
33
'allocation_setup': fields.selection([('allocated', 'Allocated'),
34
('unallocated', 'Unallocated'),
36
# UF-1261 : As long as the Unallocated stock are not developped, user shouldn't be able to change this option
38
string='Allocated stocks', required=True),
39
'unallocated_ok': fields.selection([('yes', 'Yes'), ('no', 'No')], string='System will use unallocated moves on finance side ?', readonly=True),
40
'error_ok': fields.boolean(string='Error'),
41
'error_msg': fields.text(string='Error', readonly=True),
42
'error_po_ok': fields.boolean(string='Error'),
43
'error_cross_ok': fields.boolean(string='Error'),
44
'error_central_ok': fields.boolean(string='Error'),
45
'error_location_ok': fields.boolean(string='Error'),
46
'error_po_ids': fields.many2many('purchase.order', 'allocated_purchase_order_config_rel',
47
'wizard_id', 'order_id', string='PO'),
48
'error_sm_cross_ids': fields.many2many('stock.picking', 'allocated_stock_picking_config_rel',
49
'wizard_id', 'picking_id', string='Picking'),
50
'error_sm_central_ids': fields.many2many('stock.picking', 'allocated_stock_picking_central_config_rel',
51
'wizard_id', 'picking_id', string='Picking'),
52
'error_location_ids': fields.many2many('stock.location', 'allocated_stock_location_config_rel',
53
'wizard_id', 'location_id', string='Location'),
57
'error_msg': lambda *a: '''You have some documents which block the possibility to change the Allocated stocks configuration to Unallocated.
58
These documents can be some Cross-docking purchase orders not done, stock moves to/from a cross-docking or central stock location.
59
To change the Allocated stocks configuration, locations which will be inactivated should be empty.
61
Please click on the below buttons to see the different blocking documents.''',
62
'allocation_setup': lambda *a: 'mixed',
65
def default_get(self, cr, uid, fields, context=None):
67
Display the default value for delivery process
69
setup_id = self.pool.get('unifield.setup.configuration').get_config(cr, uid)
70
res = super(allocation_stock_setup, self).default_get(cr, uid, fields, context=context)
71
res['allocation_setup'] = setup_id.allocation_setup
72
res['unallocated_ok'] = setup_id.unallocated_ok and 'yes' or 'no'
76
def allocation_on_change(self, cr, uid, ids, allocation_setup='allocated', context=None):
77
if allocation_setup in ('mixed', 'unallocated'):
78
return {'value': {'unallocated_ok': 'yes'}}
80
return {'value': {'unallocated_ok': 'no'}}
82
def _get_allocated_mvmt(self, cr, uid, type='unallocated'):
84
Search if unallocated PO and moves not done exist
86
data_obj = self.pool.get('ir.model.data')
87
po_ids = self.pool.get('purchase.order').search(cr, uid, [('cross_docking_ok', '=', True), ('state', 'not in', ['cancel', 'done'])])
89
picking_cross_ids = []
91
if type != 'unallocated':
92
cross_loc_ids = self.pool.get('stock.location').search(cr, uid, [('cross_docking_location_ok', '=', True)])
93
move_ids = self.pool.get('stock.move').search(cr, uid, [('state', 'not in', ['cancel', 'done']),
95
('location_id', 'in', cross_loc_ids),
96
('location_dest_id', 'in', cross_loc_ids)])
98
move_ids.extend(self.pool.get('stock.move').search(cr, uid, [('move_cross_docking_ok', '=', True)]))
100
for move in self.pool.get('stock.move').browse(cr, uid, move_ids):
101
picking_cross_ids.append(move.picking_id.id)
103
picking_cross_ids.extend(self.pool.get('stock.picking').search(cr, uid, [('cross_docking_ok', '=', True)]))
105
med_loc_id = data_obj.get_object_reference(cr, uid, 'msf_config_locations', 'stock_location_medical')[1]
106
log_loc_id = data_obj.get_object_reference(cr, uid, 'stock_override', 'stock_location_logistic')[1]
107
if type != 'unallocated':
108
med_loc_id = data_obj.get_object_reference(cr, uid, 'msf_config_locations', 'stock_location_unalloc_medical')[1]
109
log_loc_id = data_obj.get_object_reference(cr, uid, 'msf_config_locations', 'stock_location_unalloc_logistic')[1]
110
med_loc_ids = self.pool.get('stock.location').search(cr, uid, [('location_id', 'child_of', med_loc_id)])
111
log_loc_ids = self.pool.get('stock.location').search(cr, uid, [('location_id', 'child_of', log_loc_id)])
113
central_loc_ids = med_loc_ids + log_loc_ids
114
move_ids = self.pool.get('stock.move').search(cr, uid, [('state', 'not in', ['cancel', 'done']),
116
('location_id', 'in', central_loc_ids),
117
('location_dest_id', 'in', central_loc_ids)])
118
picking_central_ids = []
119
for move in self.pool.get('stock.move').browse(cr, uid, move_ids):
120
picking_central_ids.append(move.picking_id.id)
123
all_location_ids = cross_loc_ids + central_loc_ids
124
nok_location_ids = []
125
for location_id in all_location_ids:
126
product_qty = self.pool.get('stock.location')._product_virtual_get(cr, uid, location_id)
127
for product in product_qty:
128
if product_qty[product]:
129
nok_location_ids.append(location_id)
132
return po_ids, picking_cross_ids, picking_central_ids, nok_location_ids
134
def execute(self, cr, uid, ids, context=None):
136
Fill the delivery process field in company
138
assert len(ids) == 1, "We should only get one object from the form"
139
payload = self.browse(cr, uid, ids[0], context=context)
141
setup_obj = self.pool.get('unifield.setup.configuration')
142
data_obj = self.pool.get('ir.model.data')
143
loc_obj = self.pool.get('stock.location')
145
setup_id = setup_obj.get_config(cr, uid)
147
# Get all locations concerned by this modification
148
med_loc_id = data_obj.get_object_reference(cr, uid, 'msf_config_locations', 'stock_location_medical')[1]
149
log_loc_id = data_obj.get_object_reference(cr, uid, 'stock_override', 'stock_location_logistic')[1]
151
med_loc_ids = loc_obj.search(cr, uid, [('location_id', 'child_of', med_loc_id), ('active', 'in', ['t', 'f'])])
152
log_loc_ids = loc_obj.search(cr, uid, [('location_id', 'child_of', log_loc_id), ('active', 'in', ['t', 'f'])])
153
cross_docking_loc_ids = loc_obj.search(cr, uid, [('cross_docking_location_ok', '=', True), ('active', 'in', ['t', 'f'])])
155
unallocated_ids = loc_obj.search(cr, uid, [('central_location_ok', '=', True), ('active', 'in', ['t', 'f'])])
156
allocated_ids = cross_docking_loc_ids + med_loc_ids + log_loc_ids
157
all_loc_ids = unallocated_ids + allocated_ids
159
if payload.allocation_setup == 'allocated':
160
po_ids, picking_cross_ids, picking_central_ids, nok_location_ids = self._get_allocated_mvmt(cr, uid, 'allocated')
161
if po_ids or picking_cross_ids or picking_central_ids or nok_location_ids:
162
self.write(cr, uid, [payload.id], {'allocation_setup': 'allocated',
164
'error_po_ok': po_ids and True or False,
165
'error_cross_ok': picking_cross_ids and True or False,
166
'error_central_ok': picking_central_ids and True or False,
167
'error_location_ok': nok_location_ids and True or False,
168
'error_po_ids': [(6,0,po_ids)],
169
'error_sm_cross_ids': [(6,0,picking_cross_ids)],
170
'error_sm_central_ids': [(6,0,picking_central_ids)],
171
'error_location_ids': [(6,0,nok_location_ids)],})
172
todo_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'unifield_setup', 'allocation_stock_setup_todo')[1]
173
self.pool.get('ir.actions.todo').write(cr, uid, [todo_id], {'state': 'open'})
174
view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'unifield_setup', 'view_allocation_stock_setup')[1]
176
'res_id': payload.id,
179
'view_id': [view_id],
180
'res_model': 'allocation.stock.setup',
181
'type': 'ir.actions.act_window',
183
# Inactive unallocated locations
184
loc_obj.write(cr, uid, unallocated_ids, {'active': False}, context=context)
185
# Active allocated locations
186
loc_obj.write(cr, uid, allocated_ids, {'active': True}, context=context)
187
elif payload.allocation_setup == 'unallocated':
188
po_ids, picking_cross_ids, picking_central_ids, nok_location_ids = self._get_allocated_mvmt(cr, uid, 'unallocated')
189
if po_ids or picking_cross_ids or picking_central_ids or nok_location_ids:
190
self.write(cr, uid, [payload.id], {'allocation_setup': 'unallocated',
192
'error_po_ok': po_ids and True or False,
193
'error_cross_ok': picking_cross_ids and True or False,
194
'error_central_ok': picking_central_ids and True or False,
195
'error_location_ok': nok_location_ids and True or False,
196
'error_po_ids': [(6,0,po_ids)],
197
'error_sm_cross_ids': [(6,0,picking_cross_ids)],
198
'error_sm_central_ids': [(6,0,picking_central_ids)],
199
'error_location_ids': [(6,0,nok_location_ids)],})
200
todo_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'unifield_setup', 'allocation_stock_setup_todo')[1]
201
self.pool.get('ir.actions.todo').write(cr, uid, [todo_id], {'state': 'open'})
202
view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'unifield_setup', 'view_allocation_stock_setup')[1]
204
'res_id': payload.id,
207
'view_id': [view_id],
208
'res_model': 'allocation.stock.setup',
209
'type': 'ir.actions.act_window',
211
# Inactive allocated locations
212
loc_obj.write(cr, uid, allocated_ids, {'active': False}, context=context)
213
# Active unallocated locations
214
loc_obj.write(cr, uid, unallocated_ids, {'active': True}, context=context)
216
# Active all locations
217
loc_obj.write(cr, uid, all_loc_ids, {'active': True}, context=context)
219
setup_obj.write(cr, uid, [setup_id.id], {'allocation_setup': payload.allocation_setup,
220
'unallocated_ok': payload.allocation_setup in ['unallocated', 'mixed']}, context=context)
222
def go_to_po(self, cr, uid, ids, context=None):
223
payload = self.browse(cr, uid, ids[0])
225
for po in payload.error_po_ids:
227
return {'type': 'ir.actions.act_window',
228
'res_model': 'purchase.order',
230
'view_mode': 'tree,form',
232
'domain': [('id', 'in', po_ids)],
235
def go_to_cross(self, cr, uid, ids, context=None):
236
payload = self.browse(cr, uid, ids[0])
238
for pick in payload.error_sm_cross_ids:
239
pick_ids.append(pick.id)
240
return {'type': 'ir.actions.act_window',
241
'res_model': 'stock.picking',
243
'view_mode': 'tree,form',
245
'domain': [('id', 'in', pick_ids)],
248
def go_to_central(self, cr, uid, ids, context=None):
249
payload = self.browse(cr, uid, ids[0])
251
for pick in payload.error_sm_central_ids:
252
pick_ids.append(pick.id)
253
return {'type': 'ir.actions.act_window',
254
'res_model': 'stock.picking',
257
'view_mode': 'tree,form',
258
'domain': [('id', 'in', pick_ids)],
261
def go_to_location(self, cr, uid, ids, context=None):
262
payload = self.browse(cr, uid, ids[0])
264
for loc in payload.error_location_ids:
265
loc_ids.append(loc.id)
266
return {'type': 'ir.actions.act_window',
267
'res_model': 'stock.location',
269
'view_mode': 'tree,form',
271
'domain': [('id', 'in', loc_ids)],
274
allocation_stock_setup()