93.9.1
by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking |
1 |
##############################################################################
|
2 |
#
|
|
3 |
# OpenERP, Open Source Management Solution
|
|
4 |
# Copyright (C) 2011 TeMPO Consulting, MSF
|
|
5 |
#
|
|
6 |
# This program is free software: you can redistribute it and/or modify
|
|
7 |
# it under the terms of the GNU Affero General Public License as
|
|
8 |
# published by the Free Software Foundation, either version 3 of the
|
|
9 |
# License, or (at your option) any later version.
|
|
10 |
#
|
|
11 |
# This program is distributed in the hope that it will be useful,
|
|
12 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14 |
# GNU Affero General Public License for more details.
|
|
15 |
#
|
|
16 |
# You should have received a copy of the GNU Affero General Public License
|
|
17 |
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
18 |
#
|
|
19 |
##############################################################################
|
|
20 |
||
21 |
from datetime import datetime |
|
22 |
from dateutil.relativedelta import relativedelta |
|
23 |
import time |
|
24 |
from operator import itemgetter |
|
25 |
from itertools import groupby |
|
26 |
||
27 |
from osv import fields, osv |
|
28 |
from tools.translate import _ |
|
29 |
import netsvc |
|
30 |
import tools |
|
31 |
import decimal_precision as dp |
|
32 |
import logging |
|
778.8.1
by jf
Data: loading order for yml test |
33 |
from os import path |
93.9.1
by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking |
34 |
|
35 |
||
243.1.5
by Quentin THEURET
UF-370 [IMP] Added an overriding of procurement.order action_confirm method to give a default reason type when a stock move is created from a procurement order |
36 |
#----------------------------------------------------------
|
37 |
# Procurement Order
|
|
38 |
#----------------------------------------------------------
|
|
39 |
class procurement_order(osv.osv): |
|
40 |
_name = 'procurement.order' |
|
41 |
_inherit = 'procurement.order' |
|
409.3.25
by chloups208
uf-651 - adapt to give confirmed date a default value if object comes from workflow |
42 |
|
43 |
def create(self, cr, uid, vals, context=None): |
|
44 |
'''
|
|
45 |
create method for filling flag from yml tests
|
|
46 |
'''
|
|
47 |
if context is None: |
|
48 |
context = {} |
|
559.15.1
by jf
From yml |
49 |
if context.get('update_mode') in ['init', 'update'] and 'from_yml_test' not in vals: |
409.3.25
by chloups208
uf-651 - adapt to give confirmed date a default value if object comes from workflow |
50 |
logging.getLogger('init').info('PRO: set from yml test to True') |
51 |
vals['from_yml_test'] = True |
|
52 |
return super(procurement_order, self).create(cr, uid, vals, context=context) |
|
243.1.5
by Quentin THEURET
UF-370 [IMP] Added an overriding of procurement.order action_confirm method to give a default reason type when a stock move is created from a procurement order |
53 |
|
54 |
def action_confirm(self, cr, uid, ids, context=None): |
|
55 |
""" Confirms procurement and writes exception message if any.
|
|
56 |
@return: True
|
|
57 |
"""
|
|
58 |
move_obj = self.pool.get('stock.move') |
|
59 |
for procurement in self.browse(cr, uid, ids, context=context): |
|
60 |
if procurement.product_qty <= 0.00: |
|
61 |
raise osv.except_osv(_('Data Insufficient !'), |
|
62 |
_('Please check the Quantity in Procurement Order(s), it should not be less than 1!')) |
|
63 |
if procurement.product_id.type in ('product', 'consu'): |
|
64 |
if not procurement.move_id: |
|
65 |
source = procurement.location_id.id |
|
66 |
reason_type_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'reason_types_moves', 'reason_type_other')[1] |
|
67 |
if procurement.procure_method == 'make_to_order': |
|
68 |
reason_type_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'reason_types_moves', 'reason_type_external_supply')[1] |
|
69 |
source = procurement.product_id.product_tmpl_id.property_stock_procurement.id |
|
70 |
id = move_obj.create(cr, uid, { |
|
71 |
'name': procurement.name, |
|
72 |
'location_id': source, |
|
73 |
'location_dest_id': procurement.location_id.id, |
|
74 |
'product_id': procurement.product_id.id, |
|
75 |
'product_qty': procurement.product_qty, |
|
76 |
'product_uom': procurement.product_uom.id, |
|
77 |
'date_expected': procurement.date_planned, |
|
78 |
'state': 'draft', |
|
79 |
'company_id': procurement.company_id.id, |
|
80 |
'auto_validate': True, |
|
81 |
'reason_type_id': reason_type_id, |
|
82 |
})
|
|
83 |
move_obj.action_confirm(cr, uid, [id], context=context) |
|
84 |
self.write(cr, uid, [procurement.id], {'move_id': id, 'close_move': 1}) |
|
85 |
self.write(cr, uid, ids, {'state': 'confirmed', 'message': ''}) |
|
86 |
return True |
|
87 |
||
892.7.24
by chloups208
uf-1050 work the state of sale order line, update copy methods to allow to set default value for state, the splitted fo has sourced lines, lines of original fo are done |
88 |
def copy_data(self, cr, uid, id, default=None, context=None): |
89 |
'''
|
|
90 |
reset link to purchase order from update of on order purchase order
|
|
91 |
'''
|
|
92 |
if not default: |
|
93 |
default = {} |
|
1105.3.4
by chloups208
uf-1191 split function for Purchase Order, taking into account full behavior of Field Order back update, added original on order purchase order line reference to get line number value during new purchase order line creation |
94 |
default.update({'so_back_update_dest_po_id_procurement_order': False, |
95 |
'so_back_update_dest_pol_id_procurement_order': False}) |
|
892.7.24
by chloups208
uf-1050 work the state of sale order line, update copy methods to allow to set default value for state, the splitted fo has sourced lines, lines of original fo are done |
96 |
return super(procurement_order, self).copy_data(cr, uid, id, default, context=context) |
97 |
||
409.3.25
by chloups208
uf-651 - adapt to give confirmed date a default value if object comes from workflow |
98 |
_columns = {'from_yml_test': fields.boolean('Only used to pass addons unit test', readonly=True, help='Never set this field to true !'), |
892.7.23
by chloups208
uf-1050 added origin value in procurement and sale order line for merging new purchase order line in the source purchase order which originated the split with impact |
99 |
# this field is used when the po is modified during on order process, and the so must be modified accordingly
|
100 |
# the resulting new purchase order line will be merged in specified po_id
|
|
101 |
'so_back_update_dest_po_id_procurement_order': fields.many2one('purchase.order', string='Destination of new purchase order line', readonly=True), |
|
1105.3.4
by chloups208
uf-1191 split function for Purchase Order, taking into account full behavior of Field Order back update, added original on order purchase order line reference to get line number value during new purchase order line creation |
102 |
'so_back_update_dest_pol_id_procurement_order': fields.many2one('purchase.order.line', string='Original purchase order line', readonly=True), |
409.3.25
by chloups208
uf-651 - adapt to give confirmed date a default value if object comes from workflow |
103 |
}
|
104 |
||
105 |
_defaults = {'from_yml_test': lambda *a: False, |
|
106 |
}
|
|
107 |
||
243.1.5
by Quentin THEURET
UF-370 [IMP] Added an overriding of procurement.order action_confirm method to give a default reason type when a stock move is created from a procurement order |
108 |
procurement_order() |
109 |
||
93.9.1
by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking |
110 |
|
111 |
#----------------------------------------------------------
|
|
112 |
# Stock Picking
|
|
113 |
#----------------------------------------------------------
|
|
114 |
class stock_picking(osv.osv): |
|
115 |
_inherit = "stock.picking" |
|
116 |
_description = "Picking List" |
|
584.11.3
by Quentin THEURET
UF-801 [FIX] Fixed log message by changing 'Done' to 'Closed'. |
117 |
|
118 |
def _hook_state_list(self, cr, uid, *args, **kwargs): |
|
119 |
'''
|
|
120 |
Change terms into states list
|
|
121 |
'''
|
|
122 |
state_list = kwargs['state_list'] |
|
123 |
||
124 |
state_list['done'] = _('is closed.') |
|
125 |
||
126 |
return state_list |
|
374.5.1
by Quentin THEURET
UF-402 [IMP] Modified states values according to the naming convention |
127 |
|
128 |
_columns = { |
|
129 |
'state': fields.selection([ |
|
130 |
('draft', 'Draft'), |
|
131 |
('auto', 'Waiting'), |
|
132 |
('confirmed', 'Confirmed'), |
|
133 |
('assigned', 'Available'), |
|
134 |
('done', 'Closed'), |
|
135 |
('cancel', 'Cancelled'), |
|
136 |
], 'State', readonly=True, select=True, |
|
137 |
help="* Draft: not confirmed yet and will not be scheduled until confirmed\n"\ |
|
138 |
"* Confirmed: still waiting for the availability of products\n"\ |
|
139 |
"* Available: products reserved, simply waiting for confirmation.\n"\ |
|
140 |
"* Waiting: waiting for another move to proceed before it becomes automatically available (e.g. in Make-To-Order flows)\n"\ |
|
141 |
"* Closed: has been processed, can't be modified or cancelled anymore\n"\ |
|
142 |
"* Cancelled: has been cancelled, can't be confirmed anymore"), |
|
509
by jf
UF-651 [MERGE] Order dates mechanism |
143 |
'from_yml_test': fields.boolean('Only used to pass addons unit test', readonly=True, help='Never set this field to true !'), |
781.5.3
by Quentin THEURET
UF-956 [FIX] Made partner and address readonly when the picking is closed/cancelled |
144 |
'address_id': fields.many2one('res.partner.address', 'Delivery address', help="Address of partner", readonly=False, states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, domain="[('partner_id', '=', partner_id)]"), |
781.5.1
by Quentin THEURET
[FIX] Made the partner not mandatory on internal picking |
145 |
'partner_id2': fields.many2one('res.partner', 'Partner', required=False), |
878.4.4
by pierre-marie
UF-1060 - General picking documents modifications - End of second and third part |
146 |
'from_wkf': fields.boolean('From wkf'), |
374.5.1
by Quentin THEURET
UF-402 [IMP] Modified states values according to the naming convention |
147 |
}
|
409.3.25
by chloups208
uf-651 - adapt to give confirmed date a default value if object comes from workflow |
148 |
|
149 |
_defaults = {'from_yml_test': lambda *a: False, |
|
878.4.4
by pierre-marie
UF-1060 - General picking documents modifications - End of second and third part |
150 |
'from_wkf': lambda *a: False, |
409.3.25
by chloups208
uf-651 - adapt to give confirmed date a default value if object comes from workflow |
151 |
}
|
152 |
||
153 |
def create(self, cr, uid, vals, context=None): |
|
154 |
'''
|
|
155 |
create method for filling flag from yml tests
|
|
156 |
'''
|
|
157 |
if context is None: |
|
158 |
context = {} |
|
878.4.5
by pierre-marie
UF-1060 - General picking documents modifications - End of second and third part |
159 |
|
160 |
if not context.get('active_id',False): |
|
878.4.4
by pierre-marie
UF-1060 - General picking documents modifications - End of second and third part |
161 |
vals['from_wkf'] = True |
1229.4.1
by matthieu.choplin at msf
[utp-122] in case we duplicate an internal moves coming from a workflow, we keep the product editable |
162 |
# in case me make a copy of a stock.picking coming from a workflow
|
163 |
if context.get('not_workflow', False): |
|
164 |
vals['from_wkf'] = False |
|
878.4.4
by pierre-marie
UF-1060 - General picking documents modifications - End of second and third part |
165 |
|
559.15.2
by jf
yml_test for PICKING |
166 |
if context.get('update_mode') in ['init', 'update'] and 'from_yml_test' not in vals: |
409.3.25
by chloups208
uf-651 - adapt to give confirmed date a default value if object comes from workflow |
167 |
logging.getLogger('init').info('PICKING: set from yml test to True') |
168 |
vals['from_yml_test'] = True |
|
633.6.6
by Quentin THEURET
UF-855 [IMP] Add 3 addresses on OUT/PICK |
169 |
|
170 |
if not vals.get('partner_id2') and vals.get('address_id'): |
|
171 |
addr = self.pool.get('res.partner.address').browse(cr, uid, vals.get('address_id'), context=context) |
|
172 |
vals['partner_id2'] = addr.partner_id and addr.partner_id.id or False |
|
173 |
||
174 |
if not vals.get('address_id') and vals.get('partner_id2'): |
|
175 |
addr = self.pool.get('res.partner').address_get(cr, uid, vals.get('partner_id2'), ['delivery', 'default']) |
|
176 |
if not addr.get('delivery'): |
|
177 |
vals['address_id'] = addr.get('default') |
|
178 |
else: |
|
179 |
vals['address_id'] = addr.get('delivery') |
|
409.3.25
by chloups208
uf-651 - adapt to give confirmed date a default value if object comes from workflow |
180 |
return super(stock_picking, self).create(cr, uid, vals, context=context) |
93.9.1
by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking |
181 |
|
706
by jf
[FIX] context None |
182 |
def write(self, cr, uid, ids, vals, context=None): |
633.6.6
by Quentin THEURET
UF-855 [IMP] Add 3 addresses on OUT/PICK |
183 |
'''
|
184 |
Update the partner or the address according to the other
|
|
185 |
'''
|
|
186 |
if not vals.get('address_id') and vals.get('partner_id2'): |
|
187 |
for pick in self.browse(cr, uid, ids, context=context): |
|
188 |
if pick.partner_id.id != vals.get('partner_id2'): |
|
189 |
addr = self.pool.get('res.partner').address_get(cr, uid, vals.get('partner_id2'), ['delivery', 'default']) |
|
190 |
if not addr.get('delivery'): |
|
191 |
vals['address_id'] = addr.get('default') |
|
192 |
else: |
|
193 |
vals['address_id'] = addr.get('delivery') |
|
194 |
||
195 |
if not vals.get('partner_id2') and vals.get('address_id'): |
|
196 |
for pick in self.browse(cr, uid, ids, context=context): |
|
197 |
if pick.address_id.id != vals.get('address_id'): |
|
198 |
addr = self.pool.get('res.partner.address').browse(cr, uid, vals.get('address_id'), context=context) |
|
199 |
vals['partner_id2'] = addr.partner_id and addr.partner_id.id or False |
|
200 |
||
201 |
return super(stock_picking, self).write(cr, uid, ids, vals, context=context) |
|
202 |
||
706
by jf
[FIX] context None |
203 |
def on_change_partner(self, cr, uid, ids, partner_id, address_id, context=None): |
633.6.6
by Quentin THEURET
UF-855 [IMP] Add 3 addresses on OUT/PICK |
204 |
'''
|
205 |
Change the delivery address when the partner change.
|
|
206 |
'''
|
|
207 |
v = {} |
|
208 |
d = {} |
|
209 |
||
210 |
if not partner_id: |
|
211 |
v.update({'address_id': False}) |
|
212 |
else: |
|
1213.5.4
by Quentin THEURET
UF-1472 [IMP] Change document name in res.log when confirm a Picking ticket |
213 |
d.update({'address_id': [('partner_id', '=', partner_id)]}) |
633.6.6
by Quentin THEURET
UF-855 [IMP] Add 3 addresses on OUT/PICK |
214 |
|
215 |
||
216 |
if address_id: |
|
217 |
addr = self.pool.get('res.partner.address').browse(cr, uid, address_id, context=context) |
|
218 |
||
219 |
if not address_id or addr.partner_id.id != partner_id: |
|
220 |
addr = self.pool.get('res.partner').address_get(cr, uid, partner_id, ['delivery', 'default']) |
|
221 |
if not addr.get('delivery'): |
|
222 |
addr = addr.get('default') |
|
223 |
else: |
|
224 |
addr = addr.get('delivery') |
|
225 |
||
226 |
v.update({'address_id': addr}) |
|
227 |
||
228 |
||
229 |
return {'value': v, |
|
230 |
'domain': d} |
|
231 |
||
706
by jf
[FIX] context None |
232 |
def set_manually_done(self, cr, uid, ids, all_doc=True, context=None): |
451.4.2
by Quentin THEURET
UF-631 [ADD] Added a report to documents done |
233 |
'''
|
234 |
Set the picking to done
|
|
235 |
'''
|
|
236 |
move_ids = [] |
|
451.5.7
by Quentin THEURET
UF-631 [IMP] Removed the done state on workflows |
237 |
|
238 |
if isinstance(ids, (int, long)): |
|
239 |
ids = [ids] |
|
240 |
||
451.4.2
by Quentin THEURET
UF-631 [ADD] Added a report to documents done |
241 |
for pick in self.browse(cr, uid, ids, context=context): |
242 |
for move in pick.move_lines: |
|
451.4.12
by Quentin THEURET
UF-631 [IMP] Reworked stock move cancellation |
243 |
if move.state not in ('cancel', 'done'): |
451.4.2
by Quentin THEURET
UF-631 [ADD] Added a report to documents done |
244 |
move_ids.append(move.id) |
245 |
||
246 |
#Set all stock moves to done
|
|
559.27.7
by Quentin THEURET
UF-780 [FIX] Get a confirmation message on closing action |
247 |
self.pool.get('stock.move').set_manually_done(cr, uid, move_ids, all_doc=all_doc, context=context) |
451.4.2
by Quentin THEURET
UF-631 [ADD] Added a report to documents done |
248 |
|
249 |
return True |
|
93.9.1
by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking |
250 |
|
778.7.8
by chloups208
uf-643 claim processing from incoming shipment |
251 |
def _do_partial_hook(self, cr, uid, ids, context=None, *args, **kwargs): |
93.9.1
by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking |
252 |
'''
|
778.7.8
by chloups208
uf-643 claim processing from incoming shipment |
253 |
Please copy this to your module's method also.
|
254 |
This hook belongs to the do_partial method from stock_override>stock.py>stock_picking
|
|
255 |
|
|
256 |
- allow to modify the defaults data for move creation and copy
|
|
93.9.1
by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking |
257 |
'''
|
258 |
defaults = kwargs.get('defaults') |
|
259 |
assert defaults is not None, 'missing defaults' |
|
260 |
||
261 |
return defaults |
|
778.7.8
by chloups208
uf-643 claim processing from incoming shipment |
262 |
|
263 |
def _picking_done_cond(self, cr, uid, ids, context=None, *args, **kwargs): |
|
264 |
'''
|
|
265 |
Please copy this to your module's method also.
|
|
266 |
This hook belongs to the do_partial method from stock_override>stock.py>stock_picking
|
|
267 |
|
|
268 |
- allow to conditionally execute the picking processing to done
|
|
269 |
'''
|
|
270 |
return True |
|
271 |
||
272 |
def _custom_code(self, cr, uid, ids, context=None, *args, **kwargs): |
|
273 |
'''
|
|
274 |
Please copy this to your module's method also.
|
|
275 |
This hook belongs to the do_partial method from stock_override>stock.py>stock_picking
|
|
276 |
|
|
277 |
- allow to execute specific custom code before processing picking to done
|
|
278 |
- no supposed to modify partial_datas
|
|
279 |
'''
|
|
280 |
return True |
|
93.9.1
by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking |
281 |
|
282 |
# @@@override stock>stock.py>stock_picking>do_partial
|
|
283 |
def do_partial(self, cr, uid, ids, partial_datas, context=None): |
|
284 |
""" Makes partial picking and moves done.
|
|
285 |
@param partial_datas : Dictionary containing details of partial picking
|
|
286 |
like partner_id, address_id, delivery_date,
|
|
287 |
delivery moves with product_id, product_qty, uom
|
|
288 |
@return: Dictionary of values
|
|
289 |
"""
|
|
290 |
if context is None: |
|
291 |
context = {} |
|
292 |
else: |
|
293 |
context = dict(context) |
|
294 |
res = {} |
|
295 |
move_obj = self.pool.get('stock.move') |
|
296 |
product_obj = self.pool.get('product.product') |
|
297 |
currency_obj = self.pool.get('res.currency') |
|
298 |
uom_obj = self.pool.get('product.uom') |
|
299 |
sequence_obj = self.pool.get('ir.sequence') |
|
300 |
wf_service = netsvc.LocalService("workflow") |
|
820.2.1
by jf
UF-1020 Avg cost price |
301 |
|
947.3.4
by Quentin THEURET
UF-1067 [IMP] Product average cost computation : Don't compute with products qty in cross docking locations |
302 |
internal_loc_ids = self.pool.get('stock.location').search(cr, uid, [('usage','=','internal'), ('cross_docking_location_ok', '=', False)]) |
820.2.1
by jf
UF-1020 Avg cost price |
303 |
ctx_avg = context.copy() |
304 |
ctx_avg['location'] = internal_loc_ids |
|
93.9.1
by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking |
305 |
for pick in self.browse(cr, uid, ids, context=context): |
306 |
new_picking = None |
|
878.4.3
by pierre-marie
UF-1060 - General picking documents modifications - End of second an third part |
307 |
complete, too_many, too_few , not_aval = [], [], [], [] |
93.9.1
by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking |
308 |
move_product_qty = {} |
309 |
prodlot_ids = {} |
|
310 |
product_avail = {} |
|
311 |
for move in pick.move_lines: |
|
312 |
if move.state in ('done', 'cancel'): |
|
313 |
continue
|
|
878.4.3
by pierre-marie
UF-1060 - General picking documents modifications - End of second an third part |
314 |
elif move.state in ('confirmed'): |
315 |
not_aval.append(move) |
|
316 |
continue
|
|
217
by jf
OEB-32 [FIX] @revno 4694 Partial shipment impossible |
317 |
partial_data = partial_datas.get('move%s'%(move.id), {}) |
318 |
#Commented in order to process the less number of stock moves from partial picking wizard
|
|
319 |
#assert partial_data, _('Missing partial picking data for move #%s') % (move.id)
|
|
320 |
product_qty = partial_data.get('product_qty') or 0.0 |
|
93.9.1
by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking |
321 |
move_product_qty[move.id] = product_qty |
217
by jf
OEB-32 [FIX] @revno 4694 Partial shipment impossible |
322 |
product_uom = partial_data.get('product_uom') or False |
323 |
product_price = partial_data.get('product_price') or 0.0 |
|
324 |
product_currency = partial_data.get('product_currency') or False |
|
325 |
prodlot_id = partial_data.get('prodlot_id') or False |
|
93.9.1
by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking |
326 |
prodlot_ids[move.id] = prodlot_id |
451.3.3
by chloups208
uf-655 |
327 |
if move.product_qty == product_qty: |
93.9.1
by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking |
328 |
complete.append(move) |
329 |
elif move.product_qty > product_qty: |
|
330 |
too_few.append(move) |
|
331 |
else: |
|
332 |
too_many.append(move) |
|
333 |
||
334 |
# Average price computation
|
|
947.3.2
by Quentin THEURET
UF-1067 [IMP] Average cost price : Don't recompute cost price if the destination location is a cross-docking location |
335 |
if (pick.type == 'in') and (move.product_id.cost_method == 'average') and not move.location_dest_id.cross_docking_location_ok: |
820.2.1
by jf
UF-1020 Avg cost price |
336 |
product = product_obj.browse(cr, uid, move.product_id.id, context=ctx_avg) |
93.9.1
by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking |
337 |
move_currency_id = move.company_id.currency_id.id |
338 |
context['currency_id'] = move_currency_id |
|
339 |
qty = uom_obj._compute_qty(cr, uid, product_uom, product_qty, product.uom_id.id) |
|
340 |
||
341 |
if product.id in product_avail: |
|
342 |
product_avail[product.id] += qty |
|
343 |
else: |
|
344 |
product_avail[product.id] = product.qty_available |
|
345 |
||
346 |
if qty > 0: |
|
347 |
new_price = currency_obj.compute(cr, uid, product_currency, |
|
348 |
move_currency_id, product_price) |
|
349 |
new_price = uom_obj._compute_price(cr, uid, product_uom, new_price, |
|
350 |
product.uom_id.id) |
|
351 |
if product.qty_available <= 0: |
|
352 |
new_std_price = new_price |
|
353 |
else: |
|
354 |
# Get the standard price
|
|
355 |
amount_unit = product.price_get('standard_price', context)[product.id] |
|
356 |
new_std_price = ((amount_unit * product_avail[product.id])\ |
|
357 |
+ (new_price * qty))/(product_avail[product.id] + qty) |
|
358 |
# Write the field according to price type field
|
|
359 |
product_obj.write(cr, uid, [product.id], {'standard_price': new_std_price}) |
|
360 |
||
361 |
# Record the values that were chosen in the wizard, so they can be
|
|
362 |
# used for inventory valuation if real-time valuation is enabled.
|
|
363 |
move_obj.write(cr, uid, [move.id], |
|
364 |
{'price_unit': product_price, |
|
365 |
'price_currency_id': product_currency}) |
|
878.4.3
by pierre-marie
UF-1060 - General picking documents modifications - End of second an third part |
366 |
for move in not_aval: |
367 |
if not new_picking: |
|
368 |
new_picking = self.copy(cr, uid, pick.id, |
|
369 |
{
|
|
370 |
'name': sequence_obj.get(cr, uid, 'stock.picking.%s'%(pick.type)), |
|
371 |
'move_lines' : [], |
|
372 |
'state':'draft', |
|
373 |
})
|
|
93.9.1
by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking |
374 |
|
375 |
for move in too_few: |
|
376 |
product_qty = move_product_qty[move.id] |
|
377 |
if not new_picking: |
|
378 |
new_picking = self.copy(cr, uid, pick.id, |
|
379 |
{
|
|
380 |
'name': sequence_obj.get(cr, uid, 'stock.picking.%s'%(pick.type)), |
|
381 |
'move_lines' : [], |
|
382 |
'state':'draft', |
|
383 |
})
|
|
384 |
if product_qty != 0: |
|
385 |
defaults = { |
|
386 |
'product_qty' : product_qty, |
|
387 |
'product_uos_qty': product_qty, #TODO: put correct uos_qty |
|
388 |
'picking_id' : new_picking, |
|
389 |
'state': 'assigned', |
|
390 |
'move_dest_id': False, |
|
391 |
'price_unit': move.price_unit, |
|
392 |
}
|
|
393 |
prodlot_id = prodlot_ids[move.id] |
|
394 |
if prodlot_id: |
|
395 |
defaults.update(prodlot_id=prodlot_id) |
|
396 |
# override : call to hook added
|
|
397 |
defaults = self._do_partial_hook(cr, uid, ids, context, move=move, partial_datas=partial_datas, defaults=defaults) |
|
398 |
move_obj.copy(cr, uid, move.id, defaults) |
|
399 |
||
400 |
move_obj.write(cr, uid, [move.id], |
|
401 |
{
|
|
402 |
'product_qty' : move.product_qty - product_qty, |
|
403 |
'product_uos_qty':move.product_qty - product_qty, #TODO: put correct uos_qty |
|
404 |
})
|
|
405 |
||
406 |
if new_picking: |
|
407 |
move_obj.write(cr, uid, [c.id for c in complete], {'picking_id': new_picking}) |
|
408 |
for move in complete: |
|
409 |
# override : refactoring
|
|
410 |
defaults = {} |
|
411 |
prodlot_id = prodlot_ids.get(move.id) |
|
412 |
if prodlot_id: |
|
413 |
defaults.update(prodlot_id=prodlot_id) |
|
414 |
defaults = self._do_partial_hook(cr, uid, ids, context, move=move, partial_datas=partial_datas, defaults=defaults) |
|
415 |
move_obj.write(cr, uid, [move.id], defaults) |
|
416 |
# override : end
|
|
878.4.3
by pierre-marie
UF-1060 - General picking documents modifications - End of second an third part |
417 |
|
93.9.1
by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking |
418 |
for move in too_many: |
419 |
product_qty = move_product_qty[move.id] |
|
420 |
defaults = { |
|
421 |
'product_qty' : product_qty, |
|
422 |
'product_uos_qty': product_qty, #TODO: put correct uos_qty |
|
423 |
}
|
|
424 |
prodlot_id = prodlot_ids.get(move.id) |
|
425 |
if prodlot_ids.get(move.id): |
|
426 |
defaults.update(prodlot_id=prodlot_id) |
|
427 |
if new_picking: |
|
428 |
defaults.update(picking_id=new_picking) |
|
429 |
# override : call to hook added
|
|
430 |
defaults = self._do_partial_hook(cr, uid, ids, context, move=move, partial_datas=partial_datas, defaults=defaults) |
|
431 |
move_obj.write(cr, uid, [move.id], defaults) |
|
432 |
||
433 |
# At first we confirm the new picking (if necessary)
|
|
434 |
if new_picking: |
|
778.7.15
by chloups208
uf-643 |
435 |
self.write(cr, uid, [pick.id], {'backorder_id': new_picking}) |
778.7.8
by chloups208
uf-643 claim processing from incoming shipment |
436 |
# custom code execution
|
778.7.14
by chloups208
uf-643 claim registration during wizard process with backorder |
437 |
self._custom_code(cr, uid, ids, context=context, partial_datas=partial_datas, concerned_picking=self.browse(cr, uid, new_picking, context=context)) |
778.7.53
by chloups208
uf-643 confirm method in do_partial is performed after custom code, so name of the new picking if modified in custom code is taken into account for self.log messages + messages of assert partial_datas completed with location of call |
438 |
# we confirm the new picking after its name was possibly modified by custom code - so the link message (top message) is correct
|
439 |
wf_service.trg_validate(uid, 'stock.picking', new_picking, 'button_confirm', cr) |
|
93.9.1
by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking |
440 |
# Then we finish the good picking
|
778.7.8
by chloups208
uf-643 claim processing from incoming shipment |
441 |
if self._picking_done_cond(cr, uid, ids, context=context, partial_datas=partial_datas): |
442 |
self.action_move(cr, uid, [new_picking]) |
|
443 |
wf_service.trg_validate(uid, 'stock.picking', new_picking, 'button_done', cr) |
|
93.9.1
by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking |
444 |
wf_service.trg_write(uid, 'stock.picking', pick.id, cr) |
445 |
delivered_pack_id = new_picking |
|
446 |
else: |
|
778.7.8
by chloups208
uf-643 claim processing from incoming shipment |
447 |
# custom code execution
|
448 |
self._custom_code(cr, uid, ids, context=context, partial_datas=partial_datas, concerned_picking=pick) |
|
449 |
if self._picking_done_cond(cr, uid, ids, context=context, partial_datas=partial_datas): |
|
450 |
self.action_move(cr, uid, [pick.id]) |
|
451 |
wf_service.trg_validate(uid, 'stock.picking', pick.id, 'button_done', cr) |
|
93.9.1
by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking |
452 |
delivered_pack_id = pick.id |
453 |
||
454 |
delivered_pack = self.browse(cr, uid, delivered_pack_id, context=context) |
|
455 |
res[pick.id] = {'delivered_picking': delivered_pack.id or False} |
|
456 |
||
457 |
return res |
|
458 |
# @@@override end
|
|
459 |
||
1074.21.1
by Matthieu Dietrich
UF-687: Returns accounting |
460 |
# @@@override stock>stock.py>stock_picking>_get_invoice_type
|
461 |
def _get_invoice_type(self, pick): |
|
462 |
src_usage = dest_usage = None |
|
463 |
inv_type = None |
|
464 |
if pick.invoice_state == '2binvoiced': |
|
465 |
if pick.move_lines: |
|
466 |
src_usage = pick.move_lines[0].location_id.usage |
|
467 |
dest_usage = pick.move_lines[0].location_dest_id.usage |
|
468 |
if pick.type == 'out' and dest_usage == 'supplier': |
|
469 |
inv_type = 'in_refund' |
|
470 |
elif pick.type == 'out' and dest_usage == 'customer': |
|
471 |
inv_type = 'out_invoice' |
|
472 |
elif (pick.type == 'in' and src_usage == 'supplier') or (pick.type == 'internal'): |
|
473 |
inv_type = 'in_invoice' |
|
474 |
elif pick.type == 'in' and src_usage == 'customer': |
|
475 |
inv_type = 'out_refund' |
|
476 |
else: |
|
477 |
inv_type = 'out_invoice' |
|
478 |
return inv_type |
|
479 |
||
809.6.1
by Olivier DOSSMANN
UF-935 [ADD] Add invoice creation automation for stock picking @ done state |
480 |
def action_done(self, cr, uid, ids, context=None): |
481 |
"""
|
|
482 |
Create automatically invoice
|
|
483 |
"""
|
|
484 |
res = super(stock_picking, self).action_done(cr, uid, ids, context=context) |
|
485 |
if res: |
|
828
by jf
UF-935 [IMP] Automate supplier invoice creation |
486 |
if isinstance(ids, (int, long)): |
487 |
ids = [ids] |
|
809.6.1
by Olivier DOSSMANN
UF-935 [ADD] Add invoice creation automation for stock picking @ done state |
488 |
for sp in self.browse(cr, uid, ids): |
892.15.40
by matthieu.choplin at msf
[uf-1055] Merge with trunk and conflicts resolved |
489 |
# we do not create invoice for procurement_request (Internal Request)
|
490 |
if not sp.sale_id.procurement_request and sp.subtype == 'standard': |
|
892.15.32
by matthieu.choplin at msf
For the UF-1055: if the sale.order is an IR, we don't create invoice. The filter view of the sourcing tool was updated to see the splitted line. We update the workflow of the Internal move to have it in confirm state once the IR is confirmed. |
491 |
sp_type = False |
1074.21.3
by Matthieu Dietrich
UF-687: [MERGE] merged with latest unifield-wm |
492 |
inv_type = self._get_invoice_type(sp) |
892.15.32
by matthieu.choplin at msf
For the UF-1055: if the sale.order is an IR, we don't create invoice. The filter view of the sourcing tool was updated to see the splitted line. We update the workflow of the Internal move to have it in confirm state once the IR is confirmed. |
493 |
if sp.type == 'in' or sp.type == 'internal': |
1074.21.3
by Matthieu Dietrich
UF-687: [MERGE] merged with latest unifield-wm |
494 |
if inv_type == 'out_refund': |
495 |
sp_type = 'sale_refund' |
|
496 |
else: |
|
497 |
sp_type = 'purchase' |
|
892.15.32
by matthieu.choplin at msf
For the UF-1055: if the sale.order is an IR, we don't create invoice. The filter view of the sourcing tool was updated to see the splitted line. We update the workflow of the Internal move to have it in confirm state once the IR is confirmed. |
498 |
elif sp.type == 'out': |
1074.21.3
by Matthieu Dietrich
UF-687: [MERGE] merged with latest unifield-wm |
499 |
if inv_type == 'in_refund': |
500 |
sp_type = 'purchase_refund' |
|
501 |
else: |
|
502 |
sp_type = 'sale' |
|
892.15.32
by matthieu.choplin at msf
For the UF-1055: if the sale.order is an IR, we don't create invoice. The filter view of the sourcing tool was updated to see the splitted line. We update the workflow of the Internal move to have it in confirm state once the IR is confirmed. |
503 |
# Journal type
|
504 |
journal_type = sp_type |
|
505 |
# Disturb journal for invoice only on intermission partner type
|
|
506 |
if sp.partner_id.partner_type == 'intermission': |
|
507 |
journal_type = 'intermission' |
|
1193.21.1
by Matthieu Dietrich
UTP-193: [FIX] added instance criteria to journal search |
508 |
journal_ids = self.pool.get('account.journal').search(cr, uid, [('type', '=', journal_type), |
1249.11.1
by Matthieu Dietrich
UF-1525: [IMP] added is_current_instance attribute on journals and analytical journals, and simplified each search domain by using it |
509 |
('is_current_instance', '=', True)]) |
892.15.32
by matthieu.choplin at msf
For the UF-1055: if the sale.order is an IR, we don't create invoice. The filter view of the sourcing tool was updated to see the splitted line. We update the workflow of the Internal move to have it in confirm state once the IR is confirmed. |
510 |
if not journal_ids: |
511 |
raise osv.except_osv(_('Warning'), _('No %s journal found!') % (journal_type,)) |
|
512 |
# Create invoice
|
|
513 |
self.action_invoice_create(cr, uid, [sp.id], journal_ids[0], False, inv_type, {}) |
|
828
by jf
UF-935 [IMP] Automate supplier invoice creation |
514 |
return res |
93.9.1
by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking |
515 |
|
892.14.8
by Olivier DOSSMANN
UF-1091 [ADD] Intermission Voucher IN/OUT generation from picking |
516 |
def action_invoice_create(self, cr, uid, ids, journal_id=False, group=False, type='out_invoice', context=None): |
517 |
"""
|
|
518 |
Attach an intermission journal to the Intermission Voucher IN/OUT if partner type is intermission from the picking.
|
|
892.14.19
by Olivier DOSSMANN
UF-1091 [ADD] Automatic conversion in functional currency for intermission voucher IN/OUT |
519 |
Prepare intermission voucher IN/OUT
|
1149.1.3
by Olivier DOSSMANN
UTP-114 [FIX] Error with invoice created from picking and come from a PO that's purchase_list |
520 |
Change invoice purchase_list field to TRUE if this picking come from a PO which is 'purchase_list'
|
892.14.8
by Olivier DOSSMANN
UF-1091 [ADD] Intermission Voucher IN/OUT generation from picking |
521 |
"""
|
522 |
res = super(stock_picking, self).action_invoice_create(cr, uid, ids, journal_id, group, type, context) |
|
1193.21.1
by Matthieu Dietrich
UTP-193: [FIX] added instance criteria to journal search |
523 |
intermission_journal_ids = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'intermission'), |
1249.11.1
by Matthieu Dietrich
UF-1525: [IMP] added is_current_instance attribute on journals and analytical journals, and simplified each search domain by using it |
524 |
('is_current_instance', '=', True)]) |
892.14.19
by Olivier DOSSMANN
UF-1091 [ADD] Automatic conversion in functional currency for intermission voucher IN/OUT |
525 |
company = self.pool.get('res.users').browse(cr, uid, uid, context).company_id |
526 |
intermission_default_account = company.intermission_default_counterpart |
|
892.14.8
by Olivier DOSSMANN
UF-1091 [ADD] Intermission Voucher IN/OUT generation from picking |
527 |
for pick in self.browse(cr, uid, [x for x in res]): |
1149.1.3
by Olivier DOSSMANN
UTP-114 [FIX] Error with invoice created from picking and come from a PO that's purchase_list |
528 |
# Check if PO and PO is purchase_list
|
529 |
if pick.purchase_id and pick.purchase_id.order_type and pick.purchase_id.order_type == 'purchase_list': |
|
530 |
inv_id = res[pick.id] |
|
531 |
self.pool.get('account.invoice').write(cr, uid, [inv_id], {'purchase_list': True}) |
|
532 |
# Check intermission
|
|
892.14.8
by Olivier DOSSMANN
UF-1091 [ADD] Intermission Voucher IN/OUT generation from picking |
533 |
if pick.partner_id.partner_type == 'intermission': |
534 |
inv_id = res[pick.id] |
|
535 |
if not intermission_journal_ids: |
|
536 |
raise osv.except_osv(_('Error'), _('No Intermission journal found!')) |
|
892.14.18
by Olivier DOSSMANN
UF-1091 [ADD] Always use default account for intermission Voucher IN/OUT |
537 |
if not intermission_default_account or not intermission_default_account.id: |
538 |
raise osv.except_osv(_('Error'), _('Please configure a default intermission account in Company configuration.')) |
|
539 |
self.pool.get('account.invoice').write(cr, uid, [inv_id], {'journal_id': intermission_journal_ids[0], |
|
540 |
'is_intermission': True, 'account_id': intermission_default_account.id,}) |
|
892.14.19
by Olivier DOSSMANN
UF-1091 [ADD] Automatic conversion in functional currency for intermission voucher IN/OUT |
541 |
# Change currency for this invoice
|
542 |
company_currency = company.currency_id and company.currency_id.id or False |
|
543 |
if not company_currency: |
|
544 |
raise osv.except_osv(_('Warning'), _('No company currency found!')) |
|
545 |
wiz_account_change = self.pool.get('account.change.currency').create(cr, uid, {'currency_id': company_currency}) |
|
546 |
self.pool.get('account.change.currency').change_currency(cr, uid, [wiz_account_change], context={'active_id': inv_id}) |
|
892.14.8
by Olivier DOSSMANN
UF-1091 [ADD] Intermission Voucher IN/OUT generation from picking |
547 |
return res |
548 |
||
1074.5.2
by jf
UF-1336 [IMP] Picking / moves |
549 |
def action_confirm(self, cr, uid, ids, context=None): |
550 |
"""
|
|
551 |
stock.picking: action confirm
|
|
552 |
if INCOMING picking: confirm and check availability
|
|
553 |
"""
|
|
554 |
super(stock_picking, self).action_confirm(cr, uid, ids, context=context) |
|
555 |
move_obj = self.pool.get('stock.move') |
|
1074.5.4
by jf
UF-1336 action_assing only on confirmed stock move |
556 |
|
1074.5.2
by jf
UF-1336 [IMP] Picking / moves |
557 |
if isinstance(ids, (int, long)): |
558 |
ids = [ids] |
|
1074.5.4
by jf
UF-1336 action_assing only on confirmed stock move |
559 |
for pick in self.browse(cr, uid, ids): |
560 |
if pick.move_lines and pick.type == 'in': |
|
561 |
not_assigned_move = [x.id for x in pick.move_lines if x.state == 'confirmed'] |
|
562 |
if not_assigned_move: |
|
563 |
move_obj.action_assign(cr, uid, not_assigned_move) |
|
1074.5.2
by jf
UF-1336 [IMP] Picking / moves |
564 |
return True |
565 |
||
93.9.1
by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking |
566 |
stock_picking() |
567 |
||
568 |
# ----------------------------------------------------
|
|
569 |
# Move
|
|
570 |
# ----------------------------------------------------
|
|
571 |
||
572 |
#
|
|
573 |
# Fields:
|
|
574 |
# location_dest_id is only used for predicting futur stocks
|
|
575 |
#
|
|
576 |
class stock_move(osv.osv): |
|
577 |
||
578 |
_inherit = "stock.move" |
|
579 |
_description = "Stock Move with hook" |
|
580 |
||
706
by jf
[FIX] context None |
581 |
def set_manually_done(self, cr, uid, ids, all_doc=True, context=None): |
451.4.2
by Quentin THEURET
UF-631 [ADD] Added a report to documents done |
582 |
'''
|
583 |
Set the stock move to manually done
|
|
584 |
'''
|
|
451.4.12
by Quentin THEURET
UF-631 [IMP] Reworked stock move cancellation |
585 |
return self.write(cr, uid, ids, {'state': 'cancel'}, context=context) |
93.9.1
by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking |
586 |
|
809.11.1
by Quentin THEURET
UF-965 [IMP] Display a warning message when a DPO is confirmed with already confirmed stock moves |
587 |
def _get_from_dpo(self, cr, uid, ids, field_name, args, context=None): |
588 |
'''
|
|
589 |
Return True if the move has a dpo_id
|
|
590 |
'''
|
|
591 |
res = {} |
|
592 |
||
593 |
for move in self.browse(cr, uid, ids, context=context): |
|
594 |
res[move.id] = False |
|
595 |
if move.dpo_id: |
|
1041.1.15
by Quentin THEURET
UF-1040 [IMP] Set locations by default |
596 |
res[move.id] = True |
809.11.1
by Quentin THEURET
UF-965 [IMP] Display a warning message when a DPO is confirmed with already confirmed stock moves |
597 |
|
598 |
return res |
|
599 |
||
600 |
def _search_from_dpo(self, cr, uid, obj, name, args, context=None): |
|
601 |
'''
|
|
602 |
Returns the list of moves from or not from DPO
|
|
603 |
'''
|
|
604 |
for arg in args: |
|
605 |
if arg[0] == 'from_dpo' and arg[1] == '=': |
|
606 |
return [('dpo_id', '!=', False)] |
|
607 |
elif arg[0] == 'from_dpo' and arg[1] in ('!=', '<>'): |
|
608 |
return [('dpo_id', '=', False)] |
|
609 |
||
610 |
return [] |
|
1041.1.15
by Quentin THEURET
UF-1040 [IMP] Set locations by default |
611 |
|
612 |
def _default_location_destination(self, cr, uid, context=None): |
|
613 |
if not context: |
|
614 |
context = {} |
|
615 |
if context.get('picking_type') == 'out': |
|
616 |
wh_ids = self.pool.get('stock.warehouse').search(cr, uid, []) |
|
617 |
if wh_ids: |
|
618 |
return self.pool.get('stock.warehouse').browse(cr, uid, wh_ids[0]).lot_output_id.id |
|
619 |
||
620 |
return False |
|
809.11.1
by Quentin THEURET
UF-965 [IMP] Display a warning message when a DPO is confirmed with already confirmed stock moves |
621 |
|
374.5.1
by Quentin THEURET
UF-402 [IMP] Modified states values according to the naming convention |
622 |
_columns = { |
623 |
'state': fields.selection([('draft', 'Draft'), ('waiting', 'Waiting'), ('confirmed', 'Not Available'), ('assigned', 'Available'), ('done', 'Closed'), ('cancel', 'Cancelled')], 'State', readonly=True, select=True, |
|
584.11.1
by Quentin THEURET
UF-800 [FIX] Rename 'Done' by 'Closed' on all supply documents |
624 |
help='When the stock move is created it is in the \'Draft\' state.\n After that, it is set to \'Not Available\' state if the scheduler did not find the products.\n When products are reserved it is set to \'Available\'.\n When the picking is done the state is \'Closed\'.\ |
374.5.1
by Quentin THEURET
UF-402 [IMP] Modified states values according to the naming convention |
625 |
\nThe state is \'Waiting\' if the move is waiting for another one.'), |
781.5.3
by Quentin THEURET
UF-956 [FIX] Made partner and address readonly when the picking is closed/cancelled |
626 |
'address_id': fields.many2one('res.partner.address', 'Delivery address', help="Address of partner", readonly=False, states={'done': [('readonly', True)], 'cancel': [('readonly', True)]}, domain="[('partner_id', '=', partner_id)]"), |
633.6.6
by Quentin THEURET
UF-855 [IMP] Add 3 addresses on OUT/PICK |
627 |
'partner_id2': fields.many2one('res.partner', 'Partner', required=False), |
639.3.8
by Quentin THEURET
UF-846 [FIX] FIx creation of chaining move coming from a waiting move |
628 |
'already_confirmed': fields.boolean(string='Already confirmed'), |
809.11.2
by Quentin THEURET
UF-965 [IMP] Change link between stock moves and DPO |
629 |
'dpo_id': fields.many2one('purchase.order', string='Direct PO', help='PO from where this stock move is sourced.'), |
809.11.1
by Quentin THEURET
UF-965 [IMP] Display a warning message when a DPO is confirmed with already confirmed stock moves |
630 |
'from_dpo': fields.function(_get_from_dpo, fnct_search=_search_from_dpo, type='boolean', method=True, store=False, string='From DPO ?'), |
1074.5.1
by jf
UF-1299 [IMP] Add a button to change the destination location of an INT: no wizard |
631 |
'from_wkf_line': fields.related('picking_id', 'from_wkf', type='boolean', string='Internal use: from wkf'), |
632 |
'fake_state': fields.related('state', type='char', store=False, string="Internal use"), |
|
374.5.1
by Quentin THEURET
UF-402 [IMP] Modified states values according to the naming convention |
633 |
}
|
634 |
||
1041.1.15
by Quentin THEURET
UF-1040 [IMP] Set locations by default |
635 |
_defaults = { |
636 |
'location_dest_id': _default_location_destination, |
|
637 |
}
|
|
638 |
||
706
by jf
[FIX] context None |
639 |
def create(self, cr, uid, vals, context=None): |
633.6.6
by Quentin THEURET
UF-855 [IMP] Add 3 addresses on OUT/PICK |
640 |
'''
|
641 |
Update the partner or the address according to the other
|
|
642 |
'''
|
|
643 |
if not vals.get('partner_id2') and vals.get('address_id'): |
|
644 |
addr = self.pool.get('res.partner.address').browse(cr, uid, vals.get('address_id'), context=context) |
|
645 |
vals['partner_id2'] = addr.partner_id and addr.partner_id.id or False |
|
646 |
elif not vals.get('partner_id2'): |
|
647 |
vals['partner_id2'] = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.partner_id.id |
|
648 |
||
649 |
if not vals.get('address_id') and vals.get('partner_id2'): |
|
650 |
addr = self.pool.get('res.partner').address_get(cr, uid, vals.get('partner_id2'), ['delivery', 'default']) |
|
651 |
if not addr.get('delivery'): |
|
652 |
vals['address_id'] = addr.get('default') |
|
653 |
else: |
|
654 |
vals['address_id'] = addr.get('delivery') |
|
655 |
||
656 |
return super(stock_move, self).create(cr, uid, vals, context=context) |
|
657 |
||
706
by jf
[FIX] context None |
658 |
def write(self, cr, uid, ids, vals, context=None): |
633.6.6
by Quentin THEURET
UF-855 [IMP] Add 3 addresses on OUT/PICK |
659 |
'''
|
660 |
Update the partner or the address according to the other
|
|
661 |
'''
|
|
662 |
if not vals.get('address_id') and vals.get('partner_id2'): |
|
663 |
for move in self.browse(cr, uid, ids, context=context): |
|
664 |
if move.partner_id.id != vals.get('partner_id'): |
|
665 |
addr = self.pool.get('res.partner').address_get(cr, uid, vals.get('partner_id2'), ['delivery', 'default']) |
|
666 |
if not addr.get('delivery'): |
|
667 |
vals['address_id'] = addr.get('default') |
|
668 |
else: |
|
669 |
vals['address_id'] = addr.get('delivery') |
|
670 |
||
671 |
if not vals.get('partner_id2') and vals.get('address_id'): |
|
672 |
for move in self.browse(cr, uid, ids, context=context): |
|
673 |
if move.address_id.id != vals.get('address_id'): |
|
674 |
addr = self.pool.get('res.partner.address').browse(cr, uid, vals.get('address_id'), context=context) |
|
675 |
vals['partner_id2'] = addr.partner_id and addr.partner_id.id or False |
|
676 |
||
677 |
return super(stock_move, self).write(cr, uid, ids, vals, context=context) |
|
678 |
||
706
by jf
[FIX] context None |
679 |
def on_change_partner(self, cr, uid, ids, partner_id, address_id, context=None): |
633.6.6
by Quentin THEURET
UF-855 [IMP] Add 3 addresses on OUT/PICK |
680 |
'''
|
681 |
Change the delivery address when the partner change.
|
|
682 |
'''
|
|
683 |
v = {} |
|
684 |
d = {} |
|
685 |
||
686 |
if not partner_id: |
|
687 |
v.update({'address_id': False}) |
|
688 |
else: |
|
689 |
d.update({'address_id': [('partner_id', '=', partner_id)]}) |
|
690 |
||
691 |
||
692 |
if address_id: |
|
693 |
addr = self.pool.get('res.partner.address').browse(cr, uid, address_id, context=context) |
|
694 |
||
695 |
if not address_id or addr.partner_id.id != partner_id: |
|
696 |
addr = self.pool.get('res.partner').address_get(cr, uid, partner_id, ['delivery', 'default']) |
|
697 |
if not addr.get('delivery'): |
|
698 |
addr = addr.get('default') |
|
699 |
else: |
|
700 |
addr = addr.get('delivery') |
|
701 |
||
702 |
v.update({'address_id': addr}) |
|
703 |
||
704 |
||
705 |
return {'value': v, |
|
706 |
'domain': d} |
|
707 |
||
734
by jf
UF-846 [DEV] Stock refactoring |
708 |
def copy(self, cr, uid, id, default=None, context=None): |
639.3.10
by Quentin THEURET
UF-846 [IMP] Remove already_confirmed flag on stock move copy |
709 |
'''
|
710 |
Remove the already confirmed flag
|
|
711 |
'''
|
|
734
by jf
UF-846 [DEV] Stock refactoring |
712 |
if default is None: |
713 |
default = {} |
|
714 |
default.update({'already_confirmed':False}) |
|
639.3.10
by Quentin THEURET
UF-846 [IMP] Remove already_confirmed flag on stock move copy |
715 |
|
734
by jf
UF-846 [DEV] Stock refactoring |
716 |
return super(stock_move, self).copy(cr, uid, id, default, context=context) |
639.3.10
by Quentin THEURET
UF-846 [IMP] Remove already_confirmed flag on stock move copy |
717 |
|
734
by jf
UF-846 [DEV] Stock refactoring |
718 |
def action_confirm(self, cr, uid, ids, context=None): |
639.3.8
by Quentin THEURET
UF-846 [FIX] FIx creation of chaining move coming from a waiting move |
719 |
'''
|
720 |
Set the bool already confirmed to True
|
|
721 |
'''
|
|
722 |
res = super(stock_move, self).action_confirm(cr, uid, ids, context=context) |
|
723 |
||
724 |
self.write(cr, uid, ids, {'already_confirmed': True}, context=context) |
|
725 |
||
726 |
return res |
|
727 |
||
728 |
def _hook_confirmed_move(self, cr, uid, *args, **kwargs): |
|
729 |
'''
|
|
730 |
Always return True
|
|
731 |
'''
|
|
732 |
move = kwargs['move'] |
|
733 |
if not move.already_confirmed: |
|
734 |
self.action_confirm(cr, uid, [move.id]) |
|
735 |
return True |
|
736 |
||
639.3.5
by Quentin THEURET
UF-846 [IMP] Add a hook to cancel all chained move |
737 |
def _hook_move_cancel_state(self, cr, uid, *args, **kwargs): |
738 |
'''
|
|
739 |
Change the state of the chained move
|
|
740 |
'''
|
|
734
by jf
UF-846 [DEV] Stock refactoring |
741 |
if kwargs.get('context'): |
742 |
kwargs['context'].update({'call_unlink': True}) |
|
743 |
return {'state': 'cancel'}, kwargs.get('context', {}) |
|
878.4.3
by pierre-marie
UF-1060 - General picking documents modifications - End of second an third part |
744 |
|
745 |
def _hook_write_state_stock_move(self, cr, uid, done, notdone, count): |
|
746 |
if done: |
|
747 |
count += len(done) |
|
1182.2.1
by pierre-marie
UF-1421 Stock move is done when source = dest |
748 |
|
749 |
#If source location == dest location THEN stock move is done.
|
|
750 |
for line in self.read(cr,uid,done,['location_id','location_dest_id']): |
|
751 |
if line.get('location_id') and line.get('location_dest_id') and line.get('location_id') == line.get('location_dest_id'): |
|
752 |
self.write(cr, uid, [line['id']], {'state': 'done'}) |
|
753 |
else: |
|
754 |
self.write(cr, uid, [line['id']], {'state': 'assigned'}) |
|
755 |
||
878.4.3
by pierre-marie
UF-1060 - General picking documents modifications - End of second an third part |
756 |
if notdone: |
757 |
self.write(cr, uid, notdone, {'state': 'confirmed'}) |
|
758 |
return count |
|
1041.1.4
by Quentin THEURET
UF-1040 [IMP] Add hooks to manage non-stockable products like normal products |
759 |
|
760 |
def _hook_check_assign(self, cr, uid, *args, **kwargs): |
|
761 |
'''
|
|
762 |
kwargs['move'] is the current move
|
|
763 |
'''
|
|
764 |
move = kwargs['move'] |
|
765 |
return move.location_id.usage == 'supplier' |
|
878.4.3
by pierre-marie
UF-1060 - General picking documents modifications - End of second an third part |
766 |
|
767 |
def _hook_copy_stock_move(self, cr, uid, res, move, done, notdone): |
|
768 |
while res: |
|
769 |
r = res.pop(0) |
|
770 |
move_id = self.copy(cr, uid, move.id, {'product_qty': r[0],'product_uos_qty': r[0] * move.product_id.uos_coeff,'location_id': r[1]}) |
|
771 |
if r[2]: |
|
772 |
done.append(move_id) |
|
773 |
else: |
|
774 |
notdone.append(move_id) |
|
775 |
return done, notdone |
|
374.5.1
by Quentin THEURET
UF-402 [IMP] Modified states values according to the naming convention |
776 |
|
93.9.1
by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking |
777 |
def _do_partial_hook(self, cr, uid, ids, context, *args, **kwargs): |
778 |
'''
|
|
779 |
hook to update defaults data
|
|
780 |
'''
|
|
781 |
defaults = kwargs.get('defaults') |
|
782 |
assert defaults is not None, 'missing defaults' |
|
783 |
||
784 |
return defaults |
|
785 |
||
786 |
||
787 |
# @@@override stock>stock.py>stock_move>do_partial
|
|
788 |
def do_partial(self, cr, uid, ids, partial_datas, context=None): |
|
789 |
""" Makes partial pickings and moves done.
|
|
790 |
@param partial_datas: Dictionary containing details of partial picking
|
|
791 |
like partner_id, address_id, delivery_date, delivery
|
|
792 |
moves with product_id, product_qty, uom
|
|
793 |
"""
|
|
794 |
res = {} |
|
795 |
picking_obj = self.pool.get('stock.picking') |
|
796 |
product_obj = self.pool.get('product.product') |
|
797 |
currency_obj = self.pool.get('res.currency') |
|
798 |
uom_obj = self.pool.get('product.uom') |
|
799 |
wf_service = netsvc.LocalService("workflow") |
|
800 |
||
801 |
if context is None: |
|
802 |
context = {} |
|
803 |
||
804 |
complete, too_many, too_few = [], [], [] |
|
805 |
move_product_qty = {} |
|
806 |
prodlot_ids = {} |
|
947.3.4
by Quentin THEURET
UF-1067 [IMP] Product average cost computation : Don't compute with products qty in cross docking locations |
807 |
internal_loc_ids = self.pool.get('stock.location').search(cr, uid, [('usage','=','internal'), ('cross_docking_location_ok', '=', False)]) |
820.2.1
by jf
UF-1020 Avg cost price |
808 |
ctx_avg = context.copy() |
809 |
ctx_avg['location'] = internal_loc_ids |
|
93.9.1
by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking |
810 |
for move in self.browse(cr, uid, ids, context=context): |
811 |
if move.state in ('done', 'cancel'): |
|
812 |
continue
|
|
813 |
partial_data = partial_datas.get('move%s'%(move.id), False) |
|
814 |
assert partial_data, _('Missing partial picking data for move #%s') % (move.id) |
|
815 |
product_qty = partial_data.get('product_qty',0.0) |
|
816 |
move_product_qty[move.id] = product_qty |
|
817 |
product_uom = partial_data.get('product_uom',False) |
|
818 |
product_price = partial_data.get('product_price',0.0) |
|
819 |
product_currency = partial_data.get('product_currency',False) |
|
820 |
prodlot_ids[move.id] = partial_data.get('prodlot_id') |
|
821 |
if move.product_qty == product_qty: |
|
822 |
complete.append(move) |
|
823 |
elif move.product_qty > product_qty: |
|
824 |
too_few.append(move) |
|
825 |
else: |
|
826 |
too_many.append(move) |
|
827 |
||
828 |
# Average price computation
|
|
947.3.2
by Quentin THEURET
UF-1067 [IMP] Average cost price : Don't recompute cost price if the destination location is a cross-docking location |
829 |
if (move.picking_id.type == 'in') and (move.product_id.cost_method == 'average') and not move.location_dest_id.cross_docking_location_ok: |
820.2.1
by jf
UF-1020 Avg cost price |
830 |
product = product_obj.browse(cr, uid, move.product_id.id, context=ctx_avg) |
93.9.1
by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking |
831 |
move_currency_id = move.company_id.currency_id.id |
832 |
context['currency_id'] = move_currency_id |
|
833 |
qty = uom_obj._compute_qty(cr, uid, product_uom, product_qty, product.uom_id.id) |
|
834 |
if qty > 0: |
|
835 |
new_price = currency_obj.compute(cr, uid, product_currency, |
|
836 |
move_currency_id, product_price) |
|
837 |
new_price = uom_obj._compute_price(cr, uid, product_uom, new_price, |
|
838 |
product.uom_id.id) |
|
839 |
if product.qty_available <= 0: |
|
840 |
new_std_price = new_price |
|
841 |
else: |
|
842 |
# Get the standard price
|
|
843 |
amount_unit = product.price_get('standard_price', context)[product.id] |
|
844 |
new_std_price = ((amount_unit * product.qty_available)\ |
|
845 |
+ (new_price * qty))/(product.qty_available + qty) |
|
846 |
||
847 |
product_obj.write(cr, uid, [product.id],{'standard_price': new_std_price}) |
|
848 |
||
849 |
# Record the values that were chosen in the wizard, so they can be
|
|
850 |
# used for inventory valuation if real-time valuation is enabled.
|
|
851 |
self.write(cr, uid, [move.id], |
|
852 |
{'price_unit': product_price, |
|
853 |
'price_currency_id': product_currency, |
|
854 |
})
|
|
855 |
||
856 |
for move in too_few: |
|
857 |
product_qty = move_product_qty[move.id] |
|
858 |
if product_qty != 0: |
|
859 |
defaults = { |
|
860 |
'product_qty' : product_qty, |
|
861 |
'product_uos_qty': product_qty, |
|
862 |
'picking_id' : move.picking_id.id, |
|
863 |
'state': 'assigned', |
|
864 |
'move_dest_id': False, |
|
865 |
'price_unit': move.price_unit, |
|
866 |
}
|
|
867 |
prodlot_id = prodlot_ids[move.id] |
|
868 |
if prodlot_id: |
|
869 |
defaults.update(prodlot_id=prodlot_id) |
|
870 |
# override : call to hook added
|
|
871 |
defaults = self._do_partial_hook(cr, uid, ids, context, move=move, partial_datas=partial_datas, defaults=defaults) |
|
872 |
new_move = self.copy(cr, uid, move.id, defaults) |
|
873 |
complete.append(self.browse(cr, uid, new_move)) |
|
874 |
self.write(cr, uid, [move.id], |
|
875 |
{
|
|
876 |
'product_qty' : move.product_qty - product_qty, |
|
877 |
'product_uos_qty':move.product_qty - product_qty, |
|
878 |
})
|
|
879 |
||
880 |
||
881 |
for move in too_many: |
|
882 |
self.write(cr, uid, [move.id], |
|
883 |
{
|
|
884 |
'product_qty': move.product_qty, |
|
885 |
'product_uos_qty': move.product_qty, |
|
886 |
})
|
|
887 |
complete.append(move) |
|
888 |
||
889 |
for move in complete: |
|
890 |
# override : refactoring
|
|
891 |
defaults = {} |
|
892 |
prodlot_id = prodlot_ids.get(move.id) |
|
893 |
if prodlot_id: |
|
894 |
defaults.update(prodlot_id=prodlot_id) |
|
895 |
defaults = self._do_partial_hook(cr, uid, ids, context, move=move, partial_datas=partial_datas, defaults=defaults) |
|
896 |
self.write(cr, uid, [move.id], defaults) |
|
897 |
# override : end
|
|
898 |
self.action_done(cr, uid, [move.id], context=context) |
|
899 |
if move.picking_id.id : |
|
900 |
# TOCHECK : Done picking if all moves are done
|
|
901 |
cr.execute(""" |
|
902 |
SELECT move.id FROM stock_picking pick
|
|
903 |
RIGHT JOIN stock_move move ON move.picking_id = pick.id AND move.state = %s |
|
904 |
WHERE pick.id = %s""", |
|
905 |
('done', move.picking_id.id)) |
|
906 |
res = cr.fetchall() |
|
907 |
if len(res) == len(move.picking_id.move_lines): |
|
908 |
picking_obj.action_move(cr, uid, [move.picking_id.id]) |
|
909 |
wf_service.trg_validate(uid, 'stock.picking', move.picking_id.id, 'button_done', cr) |
|
910 |
||
911 |
return [move.id for move in complete] |
|
912 |
# @@@override end
|
|
913 |
||
475.1.1
by duy.vo at msf
[ADD] uf-580: Added the destruction location report |
914 |
def _get_destruction_products(self, cr, uid, ids, product_ids=False, context=None, recursive=False): |
915 |
""" Finds the product quantity and price for particular location.
|
|
916 |
"""
|
|
917 |
if context is None: |
|
918 |
context = {} |
|
919 |
||
475.1.2
by duy.vo at msf
[FIX] uf-580: Minor fixed |
920 |
result = [] |
475.1.1
by duy.vo at msf
[ADD] uf-580: Added the destruction location report |
921 |
for move in self.browse(cr, uid, ids, context=context): |
922 |
# add this move into the list of result
|
|
923 |
dg_check_flag = '' |
|
924 |
if move.dg_check: |
|
925 |
dg_check_flag = 'x' |
|
926 |
||
927 |
np_check_flag = '' |
|
928 |
if move.np_check: |
|
929 |
np_check_flag = 'x' |
|
930 |
sub_total = move.product_qty * move.product_id.standard_price |
|
931 |
||
932 |
currency = '' |
|
933 |
if move.purchase_line_id and move.purchase_line_id.currency_id: |
|
934 |
currency = move.purchase_line_id.currency_id.name |
|
935 |
elif move.sale_line_id and move.sale_line_id.currency_id: |
|
936 |
currency = move.sale_line_id.currency_id.name |
|
937 |
||
938 |
result.append({ |
|
939 |
'prod_name': move.product_id.name, |
|
940 |
'prod_code': move.product_id.code, |
|
941 |
'prod_price': move.product_id.standard_price, |
|
942 |
'sub_total': sub_total, |
|
943 |
'currency': currency, |
|
475.1.4
by duy.vo at msf
[FIX] uf-580: Some minor changes |
944 |
'origin': move.origin, |
475.1.1
by duy.vo at msf
[ADD] uf-580: Added the destruction location report |
945 |
'expired_date': move.expired_date, |
946 |
'prodlot_id': move.prodlot_id.name, |
|
947 |
'dg_check': dg_check_flag, |
|
948 |
'np_check': np_check_flag, |
|
949 |
'uom': move.product_uom.name, |
|
950 |
'prod_qty': move.product_qty, |
|
951 |
})
|
|
952 |
return result |
|
953 |
||
1074.5.2
by jf
UF-1336 [IMP] Picking / moves |
954 |
def in_action_confirm(self, cr, uid, ids, context=None): |
955 |
"""
|
|
956 |
Incoming: draft or confirmed: validate and assign
|
|
957 |
"""
|
|
958 |
if isinstance(ids, (int, long)): |
|
959 |
ids = [ids] |
|
960 |
self.action_confirm(cr, uid, ids, context) |
|
961 |
self.action_assign(cr, uid, ids, context) |
|
962 |
return True |
|
963 |
||
93.9.1
by chloups208
[UF-33] correction of asset which is now linked to stock.move in a wizard when processing the stock.picking |
964 |
stock_move() |
431.10.1
by Quentin THEURET
UF-697 [IMP] Added a new chaining type based on product nomenclature |
965 |
|
639.3.1
by Quentin THEURET
UF-846 [IMP] Add a new report in tree architecture to see the view locations with a total of their children |
966 |
#-----------------------------------------
|
967 |
# Stock location
|
|
968 |
#-----------------------------------------
|
|
431.10.1
by Quentin THEURET
UF-697 [IMP] Added a new chaining type based on product nomenclature |
969 |
class stock_location(osv.osv): |
970 |
_name = 'stock.location' |
|
971 |
_inherit = 'stock.location' |
|
639.3.1
by Quentin THEURET
UF-846 [IMP] Add a new report in tree architecture to see the view locations with a total of their children |
972 |
|
778.8.1
by jf
Data: loading order for yml test |
973 |
def init(self, cr): |
974 |
"""
|
|
975 |
Load data.xml asap
|
|
976 |
"""
|
|
977 |
if hasattr(super(stock_location, self), 'init'): |
|
978 |
super(stock_location, self).init(cr) |
|
979 |
||
980 |
mod_obj = self.pool.get('ir.module.module') |
|
981 |
logging.getLogger('init').info('HOOK: module stock_override: loading stock_data.xml') |
|
982 |
pathname = path.join('stock_override', 'stock_data.xml') |
|
983 |
file = tools.file_open(pathname) |
|
984 |
tools.convert_xml_import(cr, 'stock_override', file, {}, mode='init', noupdate=False) |
|
985 |
||
639.3.1
by Quentin THEURET
UF-846 [IMP] Add a new report in tree architecture to see the view locations with a total of their children |
986 |
def _product_value(self, cr, uid, ids, field_names, arg, context=None): |
987 |
"""Computes stock value (real and virtual) for a product, as well as stock qty (real and virtual).
|
|
988 |
@param field_names: Name of field
|
|
989 |
@return: Dictionary of values
|
|
990 |
"""
|
|
991 |
result = super(stock_location, self)._product_value(cr, uid, ids, field_names, arg, context=context) |
|
992 |
||
993 |
product_product_obj = self.pool.get('product.product') |
|
994 |
currency_id = self.pool.get('res.users').browse(cr, uid, uid).company_id.currency_id.id |
|
995 |
currency_obj = self.pool.get('res.currency') |
|
996 |
currency = currency_obj.browse(cr, uid, currency_id, context=context) |
|
997 |
if context.get('product_id'): |
|
998 |
view_ids = self.search(cr, uid, [('usage', '=', 'view')], context=context) |
|
999 |
result.update(dict([(i, {}.fromkeys(field_names, 0.0)) for i in list(set([aaa for aaa in view_ids]))])) |
|
1000 |
for loc_id in view_ids: |
|
1001 |
c = (context or {}).copy() |
|
1002 |
c['location'] = loc_id |
|
1003 |
c['compute_child'] = True |
|
1004 |
for prod in product_product_obj.browse(cr, uid, [context.get('product_id')], context=c): |
|
1005 |
for f in field_names: |
|
1006 |
if f == 'stock_real': |
|
1007 |
if loc_id not in result: |
|
1008 |
result[loc_id] = {} |
|
1009 |
result[loc_id][f] += prod.qty_available |
|
1010 |
elif f == 'stock_virtual': |
|
1011 |
result[loc_id][f] += prod.virtual_available |
|
1012 |
elif f == 'stock_real_value': |
|
1013 |
amount = prod.qty_available * prod.standard_price |
|
1014 |
amount = currency_obj.round(cr, uid, currency, amount) |
|
1015 |
result[loc_id][f] += amount |
|
1016 |
elif f == 'stock_virtual_value': |
|
1017 |
amount = prod.virtual_available * prod.standard_price |
|
1018 |
amount = currency_obj.round(cr, uid, currency, amount) |
|
1019 |
result[loc_id][f] += amount |
|
639.3.14
by Quentin THEURET
UF-846 [IMP] Reorganize the stock location view |
1020 |
|
1021 |
return result |
|
431.10.1
by Quentin THEURET
UF-697 [IMP] Added a new chaining type based on product nomenclature |
1022 |
|
840.1.3
by pierre-marie
UF-1040 - Non stockable product management - Correction |
1023 |
def _fake_get(self, cr, uid, ids, fields, arg, context=None): |
1024 |
result = {} |
|
1041.1.1
by jf
[MERGE] |
1025 |
if isinstance(ids, (int, long)): |
1026 |
ids = [ids] |
|
1027 |
for id in ids: |
|
1028 |
result[id] = False |
|
840.1.3
by pierre-marie
UF-1040 - Non stockable product management - Correction |
1029 |
return result |
1030 |
||
1031 |
def _prod_loc_search(self, cr, uid, ids, fields, arg, context=None): |
|
1041.1.1
by jf
[MERGE] |
1032 |
if not arg or not arg[0] or not arg[0][2] or not arg[0][2][0]: |
840.1.7
by pierre-marie
UF 1040 - Correction bug sur les OUT |
1033 |
return [] |
840.1.3
by pierre-marie
UF-1040 - Non stockable product management - Correction |
1034 |
if context is None: |
1035 |
context = {} |
|
1041.1.30
by Quentin THEURET
Move declaration of the non-stockable locations to stock_override to be loaded at stock_override loading |
1036 |
id_nonstock = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'stock_override', 'stock_location_non_stockable')[1] |
1041.1.1
by jf
[MERGE] |
1037 |
id_cross = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'msf_cross_docking', 'stock_location_cross_docking')[1] |
1038 |
prod_obj = self.pool.get('product.product').browse(cr, uid, arg[0][2][0]) |
|
840.1.7
by pierre-marie
UF 1040 - Correction bug sur les OUT |
1039 |
if prod_obj and prod_obj.type == 'consu': |
840.1.11
by pierre-marie
Correction bug on INT location |
1040 |
if arg[0][2][1] == 'in': |
1041 |
id_virt = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'stock','stock_location_locations_virtual')[1] |
|
1041.1.1
by jf
[MERGE] |
1042 |
ids_child = self.pool.get('stock.location').search(cr,uid,[('location_id', 'child_of', id_virt)]) |
1043 |
return [('id', 'in', [id_nonstock, id_cross]+ids_child)] |
|
840.1.11
by pierre-marie
Correction bug on INT location |
1044 |
else: |
840.1.9
by pierre-marie
Correction du merge |
1045 |
return [('id', 'in', [id_cross])] |
840.1.11
by pierre-marie
Correction bug on INT location |
1046 |
|
840.1.7
by pierre-marie
UF 1040 - Correction bug sur les OUT |
1047 |
elif prod_obj and prod_obj.type != 'consu': |
840.1.11
by pierre-marie
Correction bug on INT location |
1048 |
if arg[0][2][1] == 'in': |
1041.1.23
by Quentin THEURET
UF-1040 [FIX] Fix non initialized variable |
1049 |
return [('id', 'in', ids_child)] |
840.1.11
by pierre-marie
Correction bug on INT location |
1050 |
else: |
1041.1.1
by jf
[MERGE] |
1051 |
return [('id', 'not in', [id_nonstock]), ('usage', '=', 'internal')] |
840.1.11
by pierre-marie
Correction bug on INT location |
1052 |
|
1041.1.1
by jf
[MERGE] |
1053 |
return [('id', 'in', [])] |
840.1.3
by pierre-marie
UF-1040 - Non stockable product management - Correction |
1054 |
|
1055 |
def _cd_search(self, cr, uid, ids, fields, arg, context=None): |
|
1041.1.1
by jf
[MERGE] |
1056 |
id_cross = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'msf_cross_docking', 'stock_location_cross_docking')[1] |
840.1.3
by pierre-marie
UF-1040 - Non stockable product management - Correction |
1057 |
if context is None: |
1058 |
context = {} |
|
1059 |
if arg[0][2]: |
|
1041.1.1
by jf
[MERGE] |
1060 |
obj_pol = arg[0][2][0] and self.pool.get('purchase.order.line').browse(cr, uid, arg[0][2][0]) or False |
1061 |
if (obj_pol and obj_pol.order_id.cross_docking_ok) or arg[0][2][1]: |
|
840.1.3
by pierre-marie
UF-1040 - Non stockable product management - Correction |
1062 |
return [('id', 'in', [id_cross])] |
1063 |
return [] |
|
1064 |
||
840.1.9
by pierre-marie
Correction du merge |
1065 |
def _check_usage(self, cr, uid, ids, fields, arg, context=None): |
1041.1.1
by jf
[MERGE] |
1066 |
if not arg or not arg[0][2]: |
840.1.9
by pierre-marie
Correction du merge |
1067 |
return [] |
1068 |
if context is None: |
|
1069 |
context = {} |
|
1041.1.1
by jf
[MERGE] |
1070 |
prod_obj = self.pool.get('product.product').browse(cr, uid, arg[0][2]) |
1071 |
if prod_obj.type == 'service_recep': |
|
1072 |
ids = self.pool.get('stock.location').search(cr, uid, [('usage','=', 'inventory')]) |
|
840.1.9
by pierre-marie
Correction du merge |
1073 |
return [('id', 'in', ids)] |
1041.1.1
by jf
[MERGE] |
1074 |
elif prod_obj.type == 'consu': |
840.1.9
by pierre-marie
Correction du merge |
1075 |
return [] |
1076 |
else: |
|
1041.1.1
by jf
[MERGE] |
1077 |
ids = self.pool.get('stock.location').search(cr, uid, [('usage','=', 'internal')]) |
840.1.9
by pierre-marie
Correction du merge |
1078 |
return [('id', 'in', ids)] |
1079 |
return [] |
|
1080 |
||
1081 |
||
431.10.1
by Quentin THEURET
UF-697 [IMP] Added a new chaining type based on product nomenclature |
1082 |
_columns = { |
1083 |
'chained_location_type': fields.selection([('none', 'None'), ('customer', 'Customer'), ('fixed', 'Fixed Location'), ('nomenclature', 'Nomenclature')], |
|
1084 |
'Chained Location Type', required=True, |
|
1085 |
help="Determines whether this location is chained to another location, i.e. any incoming product in this location \n" \ |
|
1086 |
"should next go to the chained location. The chained location is determined according to the type :"\
|
|
1087 |
"\n* None: No chaining at all"\ |
|
1088 |
"\n* Customer: The chained location will be taken from the Customer Location field on the Partner form of the Partner that is specified in the Picking list of the incoming products." \ |
|
1089 |
"\n* Fixed Location: The chained location is taken from the next field: Chained Location if Fixed." \ |
|
1090 |
"\n* Nomenclature: The chained location is taken from the options field: Chained Location is according to the nomenclature level of product."\ |
|
1091 |
),
|
|
1092 |
'chained_options_ids': fields.one2many('stock.location.chained.options', 'location_id', string='Chained options'), |
|
431.10.8
by qt-tempo-consulting
UF-697 [IMP] Remove the location : See all documents which generates error on deletion |
1093 |
'optional_loc': fields.boolean(string='Is an optional location ?'), |
639.3.1
by Quentin THEURET
UF-846 [IMP] Add a new report in tree architecture to see the view locations with a total of their children |
1094 |
'stock_real': fields.function(_product_value, method=True, type='float', string='Real Stock', multi="stock"), |
1095 |
'stock_virtual': fields.function(_product_value, method=True, type='float', string='Virtual Stock', multi="stock"), |
|
1096 |
'stock_real_value': fields.function(_product_value, method=True, type='float', string='Real Stock Value', multi="stock", digits_compute=dp.get_precision('Account')), |
|
1097 |
'stock_virtual_value': fields.function(_product_value, method=True, type='float', string='Virtual Stock Value', multi="stock", digits_compute=dp.get_precision('Account')), |
|
840.1.3
by pierre-marie
UF-1040 - Non stockable product management - Correction |
1098 |
'check_prod_loc': fields.function(_fake_get, method=True, type='many2one', string='zz', fnct_search=_prod_loc_search), |
1099 |
'check_cd': fields.function(_fake_get, method=True, type='many2one', string='zz', fnct_search=_cd_search), |
|
840.1.9
by pierre-marie
Correction du merge |
1100 |
'check_usage': fields.function(_fake_get, method=True, type='many2one', string='zz', fnct_search=_check_usage), |
840.1.6
by pierre-marie
UF-1040 - Non stockable product mana - Correction |
1101 |
'virtual_location': fields.boolean(string='Virtual location'), |
840.1.3
by pierre-marie
UF-1040 - Non stockable product management - Correction |
1102 |
|
431.10.1
by Quentin THEURET
UF-697 [IMP] Added a new chaining type based on product nomenclature |
1103 |
}
|
1104 |
||
1105 |
#####
|
|
1106 |
# Chained location on nomenclature level
|
|
1107 |
#####
|
|
734
by jf
UF-846 [DEV] Stock refactoring |
1108 |
def _hook_chained_location_get(self, cr, uid, context=None, *args, **kwargs): |
431.10.1
by Quentin THEURET
UF-697 [IMP] Added a new chaining type based on product nomenclature |
1109 |
'''
|
1110 |
Return the location according to nomenclature level
|
|
1111 |
'''
|
|
1112 |
location = kwargs['location'] |
|
1113 |
product = kwargs['product'] |
|
1114 |
result = kwargs['result'] |
|
1115 |
||
1116 |
if location.chained_location_type == 'nomenclature': |
|
1117 |
for opt in location.chained_options_ids: |
|
1118 |
if opt.nomen_id.id == product.nomen_manda_0.id: |
|
1119 |
return opt.dest_location_id |
|
1120 |
||
1121 |
return result |
|
1122 |
||
878.4.7
by pierre-marie
UF-1060 - General picking documents modifications - Correction on the Check Avaibility split |
1123 |
def _hook_proct_reserve(self, cr, uid, product_qty, result, amount, id, ids ): |
878.4.3
by pierre-marie
UF-1060 - General picking documents modifications - End of second an third part |
1124 |
result.append((amount, id, True)) |
1125 |
product_qty -= amount |
|
1126 |
if product_qty <= 0.0: |
|
1127 |
return result |
|
1128 |
else: |
|
1129 |
result = [] |
|
1130 |
result.append((amount, id, True)) |
|
878.4.7
by pierre-marie
UF-1060 - General picking documents modifications - Correction on the Check Avaibility split |
1131 |
if len(ids) >= 1: |
1132 |
result.append((product_qty, ids[0], False)) |
|
1133 |
else: |
|
1134 |
result.append((product_qty, id, False)) |
|
878.4.3
by pierre-marie
UF-1060 - General picking documents modifications - End of second an third part |
1135 |
return result |
1136 |
return [] |
|
431.10.1
by Quentin THEURET
UF-697 [IMP] Added a new chaining type based on product nomenclature |
1137 |
|
734
by jf
UF-846 [DEV] Stock refactoring |
1138 |
def on_change_location_type(self, cr, uid, ids, chained_location_type, context=None): |
431.10.1
by Quentin THEURET
UF-697 [IMP] Added a new chaining type based on product nomenclature |
1139 |
'''
|
1140 |
If the location type is changed to 'Nomenclature', set some other fields values
|
|
1141 |
'''
|
|
1142 |
if chained_location_type and chained_location_type == 'nomenclature': |
|
1143 |
return {'value': {'chained_auto_packing': 'transparent', |
|
1144 |
'chained_picking_type': 'internal', |
|
1145 |
'chained_delay': 0}} |
|
1146 |
||
1147 |
return {} |
|
1148 |
||
1149 |
||
1150 |
stock_location() |
|
1151 |
||
1152 |
class stock_location_chained_options(osv.osv): |
|
1153 |
_name = 'stock.location.chained.options' |
|
1154 |
_rec_name = 'location_id' |
|
1155 |
||
1156 |
_columns = { |
|
1157 |
'dest_location_id': fields.many2one('stock.location', string='Destination Location', required=True), |
|
1158 |
'nomen_id': fields.many2one('product.nomenclature', string='Nomenclature Level', required=True), |
|
1159 |
'location_id': fields.many2one('stock.location', string='Location', required=True), |
|
1160 |
}
|
|
1161 |
||
1162 |
stock_location_chained_options() |
|
892.5.9
by Quentin THEURET
UF-1152 Update |
1163 |
|
1016.9.1
by Quentin THEURET
UF-1066 [IMP] Start dev on initial inventory |
1164 |
|
892.5.9
by Quentin THEURET
UF-1152 Update |
1165 |
class ir_values(osv.osv): |
1166 |
_name = 'ir.values' |
|
1167 |
_inherit = 'ir.values' |
|
1168 |
||
1169 |
def get(self, cr, uid, key, key2, models, meta=False, context=None, res_id_req=False, without_user=True, key2_req=True): |
|
1170 |
if context is None: |
|
1171 |
context = {} |
|
1172 |
values = super(ir_values, self).get(cr, uid, key, key2, models, meta, context, res_id_req, without_user, key2_req) |
|
1173 |
new_values = values |
|
1174 |
||
1175 |
move_accepted_values = {'client_action_multi': [], |
|
1176 |
'client_print_multi': [], |
|
1177 |
'client_action_relate': ['act_relate_picking'], |
|
1178 |
'tree_but_action': [], |
|
1179 |
'tree_but_open': []} |
|
892.5.19
by Quentin THEURET
UF-1152 [IMP] Stock moves view : Rename 'Reference' by 'Picking Ref.' |
1180 |
|
892.5.30
by Quentin THEURET
UF-1152 [FIX] Incoming shipment: screen a bit wide. |
1181 |
incoming_accepted_values = {'client_action_multi': ['act_stock_return_picking', 'action_stock_invoice_onshipping'], |
967.3.1
by pierre-marie
New branch Report Reception |
1182 |
'client_print_multi': ['Reception'], |
892.5.19
by Quentin THEURET
UF-1152 [IMP] Stock moves view : Rename 'Reference' by 'Picking Ref.' |
1183 |
'client_action_relate': ['View_log_stock.picking'], |
1184 |
'tree_but_action': [], |
|
1185 |
'tree_but_open': []} |
|
1186 |
||
1187 |
internal_accepted_values = {'client_action_multi': [], |
|
1188 |
'client_print_multi': ['Labels'], |
|
1189 |
'client_action_relate': [], |
|
1190 |
'tree_but_action': [], |
|
1191 |
'tree_but_open': []} |
|
1192 |
||
1193 |
delivery_accepted_values = {'client_action_multi': [], |
|
1194 |
'client_print_multi': ['Labels'], |
|
1195 |
'client_action_relate': [''], |
|
1196 |
'tree_but_action': [], |
|
1197 |
'tree_but_open': []} |
|
1198 |
||
1199 |
picking_accepted_values = {'client_action_multi': [], |
|
1200 |
'client_print_multi': ['Picking Ticket', 'Pre-Packing List', 'Labels'], |
|
1201 |
'client_action_relate': [''], |
|
1202 |
'tree_but_action': [], |
|
1203 |
'tree_but_open': []} |
|
1204 |
||
892.5.9
by Quentin THEURET
UF-1152 Update |
1205 |
if 'stock.move' in [x[0] for x in models]: |
1206 |
new_values = [] |
|
1207 |
for v in values: |
|
1208 |
if key == 'action' and v[1] in move_accepted_values[key2]: |
|
892.5.19
by Quentin THEURET
UF-1152 [IMP] Stock moves view : Rename 'Reference' by 'Picking Ref.' |
1209 |
new_values.append(v) |
1282.11.1
by matthieu.choplin at msf
[uf-1558][FIX] the link to desctruction report was missing because it wasn't taken into account in the ir.values |
1210 |
elif context.get('_terp_view_name', False) == 'Destruction Report': |
1211 |
new_values.append(v) |
|
892.5.19
by Quentin THEURET
UF-1152 [IMP] Stock moves view : Rename 'Reference' by 'Picking Ref.' |
1212 |
elif context.get('picking_type', False) == 'incoming_shipment' and 'stock.picking' in [x[0] for x in models]: |
1213 |
new_values = [] |
|
1214 |
for v in values: |
|
1215 |
if key == 'action' and v[1] in incoming_accepted_values[key2]: |
|
1216 |
new_values.append(v) |
|
1217 |
elif context.get('picking_type', False) == 'internal_move' and 'stock.picking' in [x[0] for x in models]: |
|
1218 |
new_values = [] |
|
1219 |
for v in values: |
|
1220 |
if key == 'action' and v[1] in internal_accepted_values[key2]: |
|
1221 |
new_values.append(v) |
|
1222 |
elif context.get('picking_type', False) == 'delivery_order' and 'stock.picking' in [x[0] for x in models]: |
|
1223 |
new_values = [] |
|
1224 |
for v in values: |
|
1225 |
if key == 'action' and v[1] in delivery_accepted_values[key2]: |
|
1226 |
new_values.append(v) |
|
1227 |
elif context.get('picking_type', False) == 'picking_ticket' and 'stock.picking' in [x[0] for x in models]: |
|
1228 |
new_values = [] |
|
1229 |
for v in values: |
|
1230 |
if key == 'action' and v[1] in picking_accepted_values[key2]: |
|
892.5.9
by Quentin THEURET
UF-1152 Update |
1231 |
new_values.append(v) |
1232 |
||
1233 |
return new_values |
|
1234 |
||
892.14.37
by Olivier DOSSMANN
UF-1091 [ADD] Update context for invoice log() method for inkind, intermission and debit note |
1235 |
ir_values() |