Merge lp:~syleam/wms/5.0-jean-sebastien-suzanne into lp:~syleam/wms/5.0-christophe-chauvet
- 5.0-jean-sebastien-suzanne
- Merge into 5.0-christophe-chauvet
Proposed by
Jean-Sebastien SUZANNE - http://www.Syleam.fr
Status: | Merged |
---|---|
Merged at revision: | 245 |
Proposed branch: | lp:~syleam/wms/5.0-jean-sebastien-suzanne |
Merge into: | lp:~syleam/wms/5.0-christophe-chauvet |
Diff against target: |
539 lines (+246/-56) 9 files modified
wms/object/warehouse.py (+2/-0) wms/view/warehouse.xml (+3/-0) wms/wizard/wizard_partial_picking.py (+5/-1) wms_location/data/location.xml (+9/-0) wms_sale/object/__init__.py (+1/-0) wms_sale/object/common.py (+33/-0) wms_sale/object/move.py (+100/-46) wms_sale/object/picking.py (+34/-9) wms_sale/object/product.py (+59/-0) |
To merge this branch: | bzr merge lp:~syleam/wms/5.0-jean-sebastien-suzanne |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Christophe CHAUVET | Approve | ||
Review via email: mp+52709@code.launchpad.net |
Commit message
Description of the change
- Merge with branch of Sébastien LANGE
- FIX P.U.M.P. compute
To post a comment you must log in.
Revision history for this message
Christophe CHAUVET (christophe-chauvet) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'wms/object/warehouse.py' |
2 | --- wms/object/warehouse.py 2011-02-27 21:11:57 +0000 |
3 | +++ wms/object/warehouse.py 2011-03-09 16:12:14 +0000 |
4 | @@ -39,6 +39,8 @@ |
5 | 'parent_id': fields.many2one('stock.warehouse', 'Parent warehouse', help='Define the parent warehouse'), |
6 | 'crossdock_location_id': fields.many2one('stock.location', 'Crossdock location', |
7 | help='Choose the crossdock location on this warehouse'), |
8 | + 'return_location_id': fields.many2one('stock.location', 'Return location', |
9 | + help='Choose the return location on this warehouse'), |
10 | 'check_tracking_burst': fields.boolean('check tracking', help='Check tracking on burst out'), |
11 | 'keep_missing_product_in': fields.boolean('Keep product in', help='If check, missing product line on receipt order stay with quantity = 0'), |
12 | } |
13 | |
14 | === modified file 'wms/view/warehouse.xml' |
15 | --- wms/view/warehouse.xml 2011-03-02 22:37:03 +0000 |
16 | +++ wms/view/warehouse.xml 2011-03-09 16:12:14 +0000 |
17 | @@ -51,6 +51,9 @@ |
18 | <xpath expr="/form/field[@name='lot_output_id']" position="after"> |
19 | <field name="crossdock_location_id" domain="[('warehouse_id','=', active_id),('usage','=', 'internal')]"/> |
20 | </xpath> |
21 | + <xpath expr="/form/field[@name='lot_output_id']" position="after"> |
22 | + <field name="return_location_id" domain="[('warehouse_id','=', active_id),('usage','=', 'internal')]"/> |
23 | + </xpath> |
24 | <xpath expr="/form/field[@name='partner_address_id']" position="after"> |
25 | <notebook colspan="4"> |
26 | <page string="Information"> |
27 | |
28 | === modified file 'wms/wizard/wizard_partial_picking.py' |
29 | --- wms/wizard/wizard_partial_picking.py 2010-11-23 19:06:08 +0000 |
30 | +++ wms/wizard/wizard_partial_picking.py 2011-03-09 16:12:14 +0000 |
31 | @@ -77,7 +77,11 @@ |
32 | |
33 | currency=0 |
34 | if hasattr(pick, 'purchase_id') and pick.purchase_id: |
35 | - currency=pick.purchase_id.pricelist_id.currency_id.id |
36 | + currency = pick.purchase_id.pricelist_id.currency_id.id |
37 | + elif hasattr(pick, 'address_id') and pick.address_id: |
38 | + currency = pick.address_id.partner_id.property_product_pricelist.currency_id.id |
39 | + else: |
40 | + currency = pooler.get_pool(cr.dbname).get('res.users').browse(cr, uid, uid, context=context).company_id.currency_id.id |
41 | |
42 | _moves_arch_lst.append('<group col="6" invisible="1"><field name="uom%s" nolabel="1"/>\ |
43 | <field name="price%s"/>' % (m.id,m.id,)) |
44 | |
45 | === modified file 'wms_location/data/location.xml' |
46 | --- wms_location/data/location.xml 2011-03-02 22:37:03 +0000 |
47 | +++ wms_location/data/location.xml 2011-03-09 16:12:14 +0000 |
48 | @@ -69,5 +69,14 @@ |
49 | <field name="active" eval="True"/> |
50 | </record> |
51 | |
52 | + <!-- ************************************************************* --> |
53 | + <!-- ** Add Return location as category ******* --> |
54 | + <!-- ************************************************************* --> |
55 | + <record id="location_category_return" model="stock.location.category"> |
56 | + <field name="name">Return</field> |
57 | + <field name="code">RETURN</field> |
58 | + <field name="active" eval="True"/> |
59 | + </record> |
60 | + |
61 | </data> |
62 | </openerp> |
63 | |
64 | === modified file 'wms_sale/object/__init__.py' |
65 | --- wms_sale/object/__init__.py 2011-02-20 16:05:05 +0000 |
66 | +++ wms_sale/object/__init__.py 2011-03-09 16:12:14 +0000 |
67 | @@ -26,5 +26,6 @@ |
68 | import company |
69 | import picking |
70 | import sale |
71 | +import product |
72 | |
73 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
74 | |
75 | === added file 'wms_sale/object/common.py' |
76 | --- wms_sale/object/common.py 1970-01-01 00:00:00 +0000 |
77 | +++ wms_sale/object/common.py 2011-03-09 16:12:14 +0000 |
78 | @@ -0,0 +1,33 @@ |
79 | +# -*- coding: utf-8 -*- |
80 | +############################################################################## |
81 | +# |
82 | +# wms_sale module for OpenERP, Module to extended sale with WMS |
83 | +# Copyright (C) 2011 SYLEAM Info Services (<http://www.syleam.fr/>) |
84 | +# Jean-Sébastien SUZANNE <jean-sebastien.suzanne@syleam.fr> |
85 | +# |
86 | +# This file is a part of wms_sale |
87 | +# |
88 | +# wms_sale is free software: you can redistribute it and/or modify |
89 | +# it under the terms of the GNU General Public License as published by |
90 | +# the Free Software Foundation, either version 3 of the License, or |
91 | +# (at your option) any later version. |
92 | +# |
93 | +# wms_sale is distributed in the hope that it will be useful, |
94 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
95 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
96 | +# GNU General Public License for more details. |
97 | +# |
98 | +# You should have received a copy of the GNU General Public License |
99 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
100 | +# |
101 | +############################################################################## |
102 | + |
103 | +import time |
104 | + |
105 | +def log_message(fic, section, message): |
106 | + """ |
107 | + Format the content of the logfile |
108 | + """ |
109 | + fic.write('[%s] %s: %s\n' % (time.strftime('%Y-%m-%d %H:%M:%S'), section.encode('utf-8'), message.encode('utf-8'))) |
110 | + |
111 | +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
112 | |
113 | === modified file 'wms_sale/object/move.py' |
114 | --- wms_sale/object/move.py 2011-03-04 09:52:11 +0000 |
115 | +++ wms_sale/object/move.py 2011-03-09 16:12:14 +0000 |
116 | @@ -26,6 +26,7 @@ |
117 | from osv import fields |
118 | from datetime import datetime, timedelta |
119 | from tools.translate import _ |
120 | +from common import log_message |
121 | |
122 | |
123 | class StockMove(osv.osv): |
124 | @@ -52,6 +53,11 @@ |
125 | _columns = { |
126 | 'partner': fields.function(_order_partner, method=True, type='char', multi='sums', string='Partner'), |
127 | 'order': fields.function(_order_partner, method=True, type='char', multi='sums', string='Order'), |
128 | + 'average_uom_id': fields.many2one('product.uom', 'Average UOM Unit', help="is the UOM of the average price" ), |
129 | + } |
130 | + |
131 | + _defaults = { |
132 | + 'average_uom_id': lambda *a: False, |
133 | } |
134 | |
135 | def action_done(self, cr, uid, ids, context=None): |
136 | @@ -94,6 +100,52 @@ |
137 | raise osv.except_osv(_('ERROR'), _('More move to compute without the same picking or the product')) |
138 | return (picking_id, product_id) |
139 | |
140 | + def _get_qty(self, cr, uid, id, context=None): |
141 | + """ |
142 | + return the real qty in move in function of location_id and location_dest_id |
143 | + __________________________________________________________________________________________________ |
144 | + | qty in/dest | supplier | view | internal | customer | inventory | procurement | production | |
145 | + -------------------------------------------------------------------------------------------------- |
146 | + | supplier | error | error | + | 0 | error | 0 | error | |
147 | + -------------------------------------------------------------------------------------------------- |
148 | + | view | error | error | error | error | error | error | error | |
149 | + -------------------------------------------------------------------------------------------------- |
150 | + | internal | - | error | 0 | - | - | 0 | - | |
151 | + -------------------------------------------------------------------------------------------------- |
152 | + | customer | 0 | error | + | error | error | 0 | error | |
153 | + -------------------------------------------------------------------------------------------------- |
154 | + | inventory | error | error | + | error | error | error | error | |
155 | + -------------------------------------------------------------------------------------------------- |
156 | + | procurement | 0 | error | 0 | 0 | error | 0 | 0 | |
157 | + -------------------------------------------------------------------------------------------------- |
158 | + | production | error | error | + | error | error | 0 | error | |
159 | + -------------------------------------------------------------------------------------------------- |
160 | + """ |
161 | + if not id: |
162 | + raise osv.except_osv(_('Move ERROR'), _('No move ID define to get quantity')) |
163 | + move = self.browse(cr, uid, id, context=context) |
164 | + loc_usage = move.location_id.usage |
165 | + loc_dest_usage = move.location_dest_id.usage |
166 | + if loc_usage == 'internal' and loc_dest_usage in ['supplier', 'customer', 'inventary', 'production']: |
167 | + return - move.product_qty |
168 | + elif loc_dest_usage == 'internal' and loc_usage in ['supplier', 'customer', 'inventary', 'production']: |
169 | + return move.product_qty |
170 | + elif loc_usage == 'procurement' and loc_dest_usage in ['supplier', 'customer', 'internal', 'production', 'procurement']: |
171 | + return 0.0 |
172 | + elif loc_dest_usage == 'procurement' and loc_usage in ['supplier', 'customer', 'internal', 'production']: |
173 | + return 0.0 |
174 | + elif loc_usage == 'supplier' and loc_dest_usage == 'customer': |
175 | + return 0.0 |
176 | + elif loc_dest_usage == 'supplier' and loc_usage == 'customer': |
177 | + return 0.0 |
178 | + elif loc_usage == 'internal' and loc_dest_usage == 'internal': |
179 | + return 0.0 |
180 | + else: |
181 | + raise osv.except_osv(_('Get move quantity error'), |
182 | + _('the move %s(%d) with mouvement %s(%d) usage %s ==> %s(%d) usage %s is not allowed') \ |
183 | + % (move.name, move.id, move.location_id.name, move.location_id.id, loc_usage, move.location_dest_id.name, move.location_dest_id.id, loc_dest_usage) |
184 | + ) |
185 | + |
186 | def get_previous_pump(self, cr, uid, id, date_planned, product_id, context=None): |
187 | """ |
188 | find the move linked with a picking type in before the current move |
189 | @@ -102,6 +154,7 @@ |
190 | if context is None: |
191 | context = {} |
192 | # make domain to find move |
193 | + product_obj = self.pool.get('product.product') |
194 | domain = [ |
195 | ('state', '=', 'done'), # the move must be done |
196 | ('date_planned', '<', date_planned), # the date planned must be after the current move |
197 | @@ -118,10 +171,16 @@ |
198 | pump = 0.0 |
199 | if not move_ids: |
200 | #No receiving picking found, we take the standard_price of the product |
201 | - pump = self.pool.get('product.product').read(cr, uid, product_id, ['standard_price'], context=context)['standard_price'] |
202 | + pump = product_obj.read(cr, uid, product_id, ['standard_price'], context=context).get('standard_price', 0.0) |
203 | else: |
204 | # they are only one value so take the average_price(pump) of this move |
205 | - pump = self.read(cr, uid, move_ids[0], ['average_price'], context=context)['average_price'] |
206 | + move_rd = self.read(cr, uid, move_ids[0], ['average_price', 'average_uom_id'], context=context) |
207 | + if move_rd.get('average_uom_id', False): |
208 | + uom_id = move_rd.get('average_uom_id')[0] |
209 | + average_price = move_rd.get('average_price', 0.0) |
210 | + pump = product_obj.convert_price_in_default_unit(cr, uid, product_id, average_price, uom_id,context=context) |
211 | + else: |
212 | + pump = move_rd.get('standard_price', 0.0) |
213 | return pump |
214 | |
215 | def get_qty_at_previous_time(self, cr, uid, product_id, date_planned, context=None): |
216 | @@ -154,17 +213,20 @@ |
217 | """ |
218 | if context is None: |
219 | context = {} |
220 | + outfp = context.get('log_message', False) |
221 | + product_obj = self.pool.get('product.product') |
222 | #the move ids must have the same picking and the same product |
223 | picking_id, product_id = self.get_picking_and_product_from_moves(cr, uid, ids, context=context) |
224 | # get move_ids[0] data |
225 | move_rd = self.read(cr, uid, ids[0], ['date_planned', 'price_unit'], context=context) |
226 | # get the pump |
227 | + # already in good unit |
228 | pump = self.get_previous_pump(cr, uid, move_rd.get('id'), move_rd.get('date_planned'), product_id, context=context) |
229 | + log_message(outfp, 'wms_sale.stock_move.compute_pump', 'The Start P.U.M.P. is %s' % repr(pump)) |
230 | # get the qantity after this moves |
231 | stock_qty = self.get_qty_at_previous_time(cr, uid, product_id, move_rd.get('date_planned'), context=context) |
232 | |
233 | # list of move already compute |
234 | - computed = [] |
235 | # define the type of picking looked for |
236 | company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id |
237 | picking_type = ['in'] |
238 | @@ -172,76 +234,68 @@ |
239 | picking_type.append('internal') |
240 | if company.average_price_stock_picking_out: |
241 | picking_type.append('out') |
242 | + log_message(outfp, 'wms_sale.stock_move.compute_pump', 'List of picking to save PUMP %s (delivery is never here he is computed after)' % repr(picking_type)) |
243 | |
244 | # make domain for search |
245 | domain = [ |
246 | ('state', '=', 'done'), # only the move in state done |
247 | ('date_planned', '>=', move_rd.get('date_planned')), # only the move after or equal the current |
248 | ('product_id', '=', product_id), # on this product |
249 | - '|', # make an 'or' |
250 | - ('picking_id', '=', False), # no picking |
251 | - '&', ('picking_id.state', '=', 'done'), ('picking_id.type', 'in', picking_type), # or picking with done and type in picking_type define in company |
252 | + ('location_id.usage', 'not in', ['view', 'procurement']), # we dont want view |
253 | + ('location_dest_id.usage', 'not in', ['view', 'procurement']), # we dont want view |
254 | ] |
255 | order_by = 'date_planned, id' |
256 | |
257 | move_ids = self.search(cr, uid, domain, order=order_by, context=context) |
258 | - to_compute = list(move_ids) |
259 | + |
260 | + delivery_ids = [] |
261 | for move_id in move_ids: |
262 | - # test if the compute alredy exist |
263 | - if move_id in computed: |
264 | - continue |
265 | - # group move this same date_planned, same picking in ids search |
266 | + #get new qty at the date_planned |
267 | + qty = self._get_qty(cr, uid, move_id, context=context) |
268 | move = self.browse(cr, uid, move_id, context=context) |
269 | - group_domain = [ |
270 | - ('date_planned', '=', move.date_planned), # the same date |
271 | - ('picking_id', '=', move.picking_id and move.picking_id.id or False), # the same picking |
272 | - ('id', 'in', to_compute), # in the compute found |
273 | - ] |
274 | - group_move_ids = self.search(cr, uid, group_domain, context=context) |
275 | - |
276 | - #get new qty at the date_planned |
277 | - qty = self.get_qty_at_time(cr, uid, product_id, move.date_planned, context=context) |
278 | + log_message(outfp, 'wms_sale.stock_move.compute_pump', 'compute the move %s(%d) with picking type %s' % (move.name, move.id, move.picking_id and move.picking_id.type or 'None')) |
279 | if move.picking_id and move.picking_id.type == 'in': |
280 | + # get the price of the move |
281 | + price_unit = product_obj.convert_price_in_default_unit(cr, uid, product_id, move.price_unit, move.product_uom and move.product_uom.id or False, context=context) |
282 | + # the pump uom is not the same that sale uom |
283 | #calcul new pump |
284 | # new pump = [ (pump * stock_qty) + ( price_unit * received qty ) ] / (stock qty + received qty ) |
285 | # only if stock_qty |
286 | - if stock_qty > 0: |
287 | - pump = ((pump * stock_qty) + (move.price_unit * (qty - stock_qty))) / qty |
288 | + log_message(outfp, 'wms_sale.stock_move.compute_pump', 'Compute the new P.U.M.P. = ((%s * %s) + (%s * %s)) / %s'\ |
289 | + % (repr(pump), repr(stock_qty), repr(price_unit), repr(qty), repr(stock_qty + qty))) |
290 | + if stock_qty + qty > 0: |
291 | + pump = ((pump * stock_qty) + (price_unit * qty)) / (stock_qty + qty) |
292 | else: |
293 | # if stock_qty == 0 => pump = (price_unit * qty) / qty => pump = price_unit |
294 | # if stock_qty < 0 (example -1) => pump = ( -pump + ( price_unit * qty) ) / (qty - 1) |
295 | ## error cause if qty = stock_qty => division by zero |
296 | ## qty < stock_qty => pump < 0 forbiden |
297 | ## qty > stock_qty => pump wrong the good pump is the price_unit |
298 | - pump = move.price_unit |
299 | - # write the pump in average_price |
300 | - self.write(cr, uid, group_move_ids, {'average_price': pump}, context=context) |
301 | + pump = price_unit |
302 | + log_message(outfp, 'wms_sale.stock_move.compute_pump', 'Compute the new P.U.M.P. = %s' % repr(pump)) |
303 | + if move.picking_id and move.picking_id.type in picking_type: |
304 | + # write the pump in average_price |
305 | + average_uom_id = move.product_id.list_price_uom_id and move.product_id.list_price_uom_id.id or move.product_uom.id |
306 | + self.write(cr, uid, move_id, {'average_price': pump, 'average_uom_id': average_uom_id}, context=context) |
307 | + elif company.average_price_stock_picking_delivery and move.picking_id.type == 'delivery': |
308 | + delivery_ids.append(move_id) |
309 | # save new stock_qty and compute list |
310 | - stock_qty = qty |
311 | - computed.extend(group_move_ids) |
312 | - # remove the id computed |
313 | - for m in group_move_ids: |
314 | - to_compute.remove(m) |
315 | - |
316 | - self.pool.get('product.product').write(cr, uid, [product_id], {'standard_price': pump}, context=context) |
317 | - |
318 | + stock_qty = (stock_qty + qty) |
319 | + |
320 | + log_message(outfp, 'wms_sale.stock_move.compute_pump', 'save the P.U.M.P. %s on product %d' % (repr(pump), product_id)) |
321 | + product_obj.write(cr, uid, [product_id], {'standard_price': pump}, context=context) |
322 | # only for the delivery |
323 | - if company.average_price_stock_picking_delivery: |
324 | - domain = [ |
325 | - ('state', '=', 'done'), # only the move in state done |
326 | - ('date_planned', '>=', move_rd.get('date_planned')), # only the move after or equal the current |
327 | - ('product_id', '=', product_id), # on this product |
328 | - ('picking_id.state', '=', 'done'), # pickinf is done |
329 | - ('picking_id.type', '=', 'delivery'), # type in picking_type must be a delivery |
330 | - ] |
331 | - move_delivery_ids = self.search(cr, uid, domain, order=order_by, context=context) |
332 | - for move in self.browse(cr, uid, move_delivery_ids, context=context): |
333 | + if delivery_ids and company.average_price_stock_picking_out: |
334 | + log_message(outfp, 'wms_sale.stock_move.compute_pump', 'save the P.U.M.P. On delivery with method %s' % company.average_price_stock_picking_delivery_method) |
335 | + for move in self.browse(cr, uid, delivery_ids, context=context): |
336 | + log_message(outfp, 'wms_sale.stock_move.compute_pump', 'for move %s(%d)'% (move.name, move.id)) |
337 | # they are three mode: |
338 | # 1 : the sale order is invoiced so we dont touch of the pump |
339 | # 2 : the pump of the delivery is on the product (average_price_stock_picking_delivery_method == product on company) use the pump in the product |
340 | # 3 : the pump of the delivery is on the out picking (average_price_stock_picking_delivery_method == out on company) use the pump in the move in delivery out |
341 | if move.sale_line_id.order_id.invoiced: |
342 | # the sale order is invoiced |
343 | + log_message(outfp, 'wms_sale.stock_move.compute_pump', 'Already Invoiced') |
344 | continue |
345 | elif company.average_price_stock_picking_delivery_method == 'product': |
346 | # take the pump of the product. we have already the pump because the saved is make before and the value is in pump variable |
347 | @@ -256,11 +310,11 @@ |
348 | ('name', '=', move.name), # the same name |
349 | ] |
350 | move_out_id = self.search(cr, uid, domain, context=context)[0] |
351 | - move_out_average_price = self.read(cr, uid, move_out_id, ['average_price'], context=context)['average_price'] |
352 | - self.write(cr, uid, move.id, {'average_price': move_out_average_price}, context=context) |
353 | + move_out_average = self.read(cr, uid, move_out_id, ['average_price', 'average_uom_id', 'product_uom'], context=context) |
354 | + average_uom_id = move_out_average.get('average_uom_id', move_out_average.get('product_uom', [False]))[0] |
355 | + self.write(cr, uid, move.id, {'average_price': move_out_average.get('average_price', 0.0), 'average_uom_id': average_uom_id}, context=context) |
356 | else: |
357 | raise osv.except_osv(_('WARNING'), _('No delivery mode found for the compute of the P.U.M.P. on delivery move')) |
358 | - |
359 | return True |
360 | |
361 | StockMove() |
362 | |
363 | === modified file 'wms_sale/object/picking.py' |
364 | --- wms_sale/object/picking.py 2011-02-20 16:05:05 +0000 |
365 | +++ wms_sale/object/picking.py 2011-03-09 16:12:14 +0000 |
366 | @@ -1,18 +1,18 @@ |
367 | # -*- coding: utf-8 -*- |
368 | ############################################################################## |
369 | # |
370 | -# wms_purchase module for OpenERP, Inherite purcharge for wms |
371 | +# wms_sale module for OpenERP, Inherite purcharge for wms |
372 | # Copyright (C) 2010 SYLEAM Info Services (<http://www.syleam.fr/>) |
373 | # Jean-Sébastien SUZANNE <jean-sebastien.suzanne@syleam.fr> |
374 | # |
375 | -# This file is a part of wms_purchase |
376 | +# This file is a part of wms_sale |
377 | # |
378 | -# wms_purchase is free software: you can redistribute it and/or modify |
379 | +# wms_sale is free software: you can redistribute it and/or modify |
380 | # it under the terms of the GNU General Public License as published by |
381 | # the Free Software Foundation, either version 3 of the License, or |
382 | # (at your option) any later version. |
383 | # |
384 | -# wms_purchase is distributed in the hope that it will be useful, |
385 | +# wms_sale is distributed in the hope that it will be useful, |
386 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
387 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
388 | # GNU General Public License for more details. |
389 | @@ -26,6 +26,9 @@ |
390 | import pooler |
391 | import thread |
392 | from tools.translate import _ |
393 | +import tempfile |
394 | +from common import log_message |
395 | +import base64 |
396 | import netsvc |
397 | logger = netsvc.Logger() |
398 | |
399 | @@ -90,18 +93,24 @@ |
400 | request_obj = self.pool.get('res.request') |
401 | product_obj = self.pool.get('product.product') |
402 | move_obj = self.pool.get('stock.move') |
403 | - logger.notifyChannel('wms_purchase.stock_picking.compute_pump', netsvc.LOG_DEBUG, 'COMPUTE_PUMP START(id=%d, product_linked=%s, context=%s)' % (id, repr(product_linked), repr(context))) |
404 | + logger.notifyChannel('wms_sale.stock_picking.compute_pump', netsvc.LOG_DEBUG, 'COMPUTE_PUMP START(id=%d, product_linked=%s, context=%s)' % (id, repr(product_linked), repr(context))) |
405 | + outfp = tempfile.NamedTemporaryFile(prefix='openerp', suffix='pump') |
406 | + ctx = context.copy() |
407 | + ctx['log_message'] = outfp |
408 | + log_message(outfp, 'wms_sale.stock_picking.compute_pump', 'COMPUTE_PUMP START(id=%d, product_linked=%s, context=%s)' % (id, repr(product_linked), repr(context))) |
409 | |
410 | def thread_compute_pump(self, cr, uid, id, product_linked, context): |
411 | """ |
412 | this method is a threadind method |
413 | """ |
414 | cr = pooler.get_db(cr.dbname).cursor() |
415 | + outfp = context.get('log_message', False) |
416 | # get information to display in message |
417 | picking = self.browse(cr, uid, id, context) |
418 | #for each move who have a product with a new price_unit compute_pump else make nothing |
419 | for product_id in product_linked.keys(): |
420 | product = product_obj.browse(cr, uid, product_id, context=context) |
421 | + log_message(outfp, 'wms_sale.stock_picking.compute_pump', 'COMPUTE_PUMP with the product %s(%s)[%d] ::> cost method is %s' % (product.name, product.code, product.id, product.cost_method)) |
422 | if product.cost_method != 'average': |
423 | continue |
424 | try: |
425 | @@ -113,9 +122,11 @@ |
426 | if move.price_unit != product_linked[product.id]: |
427 | # save the new price unit one the move_ids |
428 | move_obj.write(cr, uid, move_ids, {'price_unit': product_linked[product.id]}, context=context) |
429 | + log_message(outfp, 'wms_sale.stock_picking.compute_pump', 'the new price unit is %s' % (repr(product_linked[product.id]))) |
430 | # compute the move |
431 | move_obj.compute_pump(cr, uid, move_ids, context=context) |
432 | else: |
433 | + log_message(outfp, 'wms_sale.stock_picking.compute_pump', 'keep the price unit ') |
434 | continue |
435 | else: |
436 | raise osv.except_osv(_('ERROR'), _('No move found this picking(%s) and product(%s)')) % (picking.name, product.name) |
437 | @@ -124,7 +135,7 @@ |
438 | except Exception, err: |
439 | # make a rollback because the transaction is wrong |
440 | cr.rollback() |
441 | - logger.notifyChannel('wms_purchase.stock_picking.thread_compute_pump', netsvc.LOG_ERROR, repr(err)) |
442 | + logger.notifyChannel('wms_sale.stock_picking.thread_compute_pump', netsvc.LOG_ERROR, repr(err)) |
443 | # make a request |
444 | val_request = { |
445 | 'act_to': uid, |
446 | @@ -136,12 +147,26 @@ |
447 | #'ref_doc1':'stock.picking,%d' % picking.id, |
448 | #'ref_doc2':'product.product,%d' % product.id, |
449 | } |
450 | - request_obj.create(cr, uid, val_request, context=context) |
451 | + req_id = request_obj.create(cr, uid, val_request, context=context) |
452 | + log_message(outfp, 'wms_sale.stock_picking.compute_pump', 'The error be signal in the request %d' % (req_id)) |
453 | cr.commit() |
454 | - logger.notifyChannel('wms_purchase.stock_picking.compute_pump', netsvc.LOG_INFO, 'COMPUTE_PUMP ENDED ....') |
455 | + logger.notifyChannel('wms_sale.stock_picking.compute_pump', netsvc.LOG_INFO, 'COMPUTE_PUMP ENDED ....') |
456 | + log_message(outfp, 'wms_sale.stock_picking.compute_pump', 'COMPUTE_PUMP ENDED ....') |
457 | + outfp.flush() |
458 | + outfp.seek(0) |
459 | + vals = { |
460 | + 'datas': base64.encodestring(outfp.read()), |
461 | + 'datas_fname': 'pump_%s' % picking.origin, |
462 | + 'name': 'PUMP %s' % picking.origin, |
463 | + 'res_model': 'stock.picking', |
464 | + 'res_id': 0, |
465 | + } |
466 | + self.pool.get('ir.attachment').create(cr, uid, vals, context=context) |
467 | + cr.commit() |
468 | + outfp.close() |
469 | cr.close() |
470 | |
471 | - thread.start_new_thread(thread_compute_pump, (self, cr, uid, id, product_linked.copy(), context.copy())) |
472 | + thread.start_new_thread(thread_compute_pump, (self, cr, uid, id, product_linked.copy(), ctx)) |
473 | return True |
474 | |
475 | stock_picking() |
476 | |
477 | === added file 'wms_sale/object/product.py' |
478 | --- wms_sale/object/product.py 1970-01-01 00:00:00 +0000 |
479 | +++ wms_sale/object/product.py 2011-03-09 16:12:14 +0000 |
480 | @@ -0,0 +1,59 @@ |
481 | +# -*- coding: utf-8 -*- |
482 | +############################################################################## |
483 | +# |
484 | +# wms_sale module for OpenERP, Module to extended sale with WMS |
485 | +# Copyright (C) 2011 SYLEAM Info Services (<http://www.syleam.fr/>) |
486 | +# Jean-Sébastien SUZANNE <jean-sebastien.suzanne@syleam.fr> |
487 | +# |
488 | +# This file is a part of wms_sale |
489 | +# |
490 | +# wms_sale is free software: you can redistribute it and/or modify |
491 | +# it under the terms of the GNU General Public License as published by |
492 | +# the Free Software Foundation, either version 3 of the License, or |
493 | +# (at your option) any later version. |
494 | +# |
495 | +# wms_sale is distributed in the hope that it will be useful, |
496 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
497 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
498 | +# GNU General Public License for more details. |
499 | +# |
500 | +# You should have received a copy of the GNU General Public License |
501 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
502 | +# |
503 | +############################################################################## |
504 | + |
505 | +from osv import osv |
506 | +from tools.translate import _ |
507 | + |
508 | + |
509 | +class product_product(osv.osv): |
510 | + _inherit = 'product.product' |
511 | + |
512 | + def convert_price_in_default_unit(self, cr, uid, id, price, uom_id, context=None): |
513 | + """ |
514 | + :param id : id of the product |
515 | + :type id: int |
516 | + :param price: the origin price to convert |
517 | + :type price: float |
518 | + :param uom_id: the unit of the product for this price |
519 | + :type uom_id : int |
520 | + convert the price in fonction of unit |
521 | + - uom_id.category == product.uom_category => price = price * uom_id.factor / product.uom_id.factor |
522 | + - uom_id.category == product.uos_category => price = price * product.uos_coeff * uom_id.factor / product.uos_id.factor |
523 | + """ |
524 | + if not id: |
525 | + raise osv.except_osv(_('Convert Unit Error'), _('No product defined to convert unit')) |
526 | + if not uom_id: |
527 | + raise osv.except_osv(_('Convert Unit Error'), _('No UOM defined to convert unit')) |
528 | + uom_obj = self.pool.get('product.uom') |
529 | + product = self.pool.get('product.product').browse(cr, uid, id, context=context) |
530 | + uom = uom_obj.browse(cr, uid, uom_id, context=context) |
531 | + if product.uos_id and product.uos_id.category_id.id == uom.category_id.id: |
532 | + return uom_obj._compute_price(cr, uid, product.uos_id.id, price * product.uos_coeff or 1.0, product.uom_id.id) |
533 | + elif product.uom_id.category_id.id == uom.category_id.id: |
534 | + return uom_obj._compute_price(cr, uid, uom_id, price, product.uom_id.id) |
535 | + |
536 | +product_product() |
537 | + |
538 | + |
539 | +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |