1
# -*- coding: utf-8 -*-
2
##############################################################################
4
# Copyright (C) 2011 MSF, TeMPO Consulting
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.
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.
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/>.
19
##############################################################################
22
from osv import fields
24
from tools.translate import _
25
import decimal_precision as dp
29
class initial_stock_inventory(osv.osv):
30
_name = 'initial.stock.inventory'
31
_description = "Initial Stock Inventory"
32
_inherit = 'stock.inventory'
34
def unlink(self, cr, uid, ids, context=None):
36
Prevent the deletion of a non-draft/cancel initial inventory
38
for inv in self.browse(cr, uid, ids, context=context):
39
if inv.state not in ('draft', 'cancel'):
40
raise osv.except_osv(_('Error'), _('You cannot remove an initial inventory which is done'))
42
return super(initial_stock_inventory, self).unlink(cr, uid, ids, context=context)
45
'inventory_line_id': fields.one2many('initial.stock.inventory.line', 'inventory_id', string='Inventory lines'),
46
'move_ids': fields.many2many('stock.move', 'initial_stock_inventory_move_rel', 'inventory_id', 'move_id', 'Created Moves'),
47
'sublist_id': fields.many2one('product.list', string='List/Sublist', ondelete='set null'),
48
'nomen_manda_0': fields.many2one('product.nomenclature', 'Main Type', ondelete='set null'),
49
'nomen_manda_1': fields.many2one('product.nomenclature', 'Group', ondelete='set null'),
50
'nomen_manda_2': fields.many2one('product.nomenclature', 'Family', ondelete='set null'),
51
'nomen_manda_3': fields.many2one('product.nomenclature', 'Root', ondelete='set null'),
54
def _inventory_line_hook(self, cr, uid, inventory_line, move_vals):
56
Add the price in the stock move
58
move_vals['price_unit'] = inventory_line.average_cost
59
return super(initial_stock_inventory, self)._inventory_line_hook(cr, uid, inventory_line, move_vals)
61
def action_confirm(self, cr, uid, ids, context=None):
63
Override the action_confirm method to check the batch mgmt/perishable data
65
if isinstance(ids, (int, long)):
69
prodlot_obj = self.pool.get('stock.production.lot')
70
product_obj = self.pool.get('product.product')
72
self.check_integrity(cr, uid, ids, context=context)
74
for inventory in self.browse(cr, uid, ids, context=context):
75
# Prevent confirmation with no lines
76
if len(inventory.inventory_line_id) == 0:
77
raise osv.except_osv(_('Error'), _('Please enter at least one line in stock inventory before confirm it.'))
79
for inventory_line in inventory.inventory_line_id:
80
if inventory_line.product_id:
81
# Check product constrainsts
82
product_obj._get_restriction_error(cr, uid, [inventory_line.product_id.id], {'location_id': inventory_line.location_id.id}, context=context)
84
# Don't check integrity on line with no quantity
85
if inventory_line.product_qty == 0.0:
86
inventory_line.write({'dont_move': True})
89
# Check if there is two lines with the same product and with difference average cost
90
if inventory_line.product_id.id not in product_dict:
91
product_dict.update({inventory_line.product_id.id: inventory_line.average_cost})
92
elif product_dict[inventory_line.product_id.id] != inventory_line.average_cost:
93
raise osv.except_osv(_('Error'), _('You cannot have two lines for the product %s with different average cost.') % product_obj.name_get(cr, uid, [inventory_line.product_id.id], context=context)[0][1])
95
# Returns error if the line is batch mandatory or perishable without prodlot
96
if inventory_line.product_id.batch_management and not inventory_line.prodlot_name:
97
raise osv.except_osv(_('Error'), _('You must assign a Batch Number on the product %s.') % product_obj.name_get(cr, uid, [inventory_line.product_id.id])[0][1])
98
elif inventory_line.product_id.perishable and not inventory_line.expiry_date:
99
raise osv.except_osv(_('Error'), _('You must assign an Expiry Date on the product %s.') % product_obj.name_get(cr, uid, [inventory_line.product_id.id])[0][1])
101
if inventory_line.product_id.batch_management:
102
# if no production lot, we create a new one
103
prodlot_ids = prodlot_obj.search(cr, uid, [('name', '=', inventory_line.prodlot_name),
104
('type', '=', 'standard'),
105
('product_id', '=', inventory_line.product_id.id)], context=context)
107
# Prevent creation of two batch with the same name/product but different expiry date
108
prodlot = prodlot_obj.browse(cr, uid, prodlot_ids[0])
109
if prodlot.life_date != inventory_line.expiry_date:
110
life_date = self.pool.get('date.tools').get_date_formatted(cr, uid, datetime=prodlot.life_date)
111
raise osv.except_osv(_('Error'), _('The batch number \'%s\' is already in the system but its expiry date is %s') % (prodlot.name, life_date))
112
prodlot_id = prodlot_ids and prodlot_ids[0] or False
113
# no prodlot, create a new one
115
prodlot_id = prodlot_obj.create(cr, uid, {'name': inventory_line.prodlot_name,
117
'life_date': inventory_line.expiry_date,
118
'product_id': inventory_line.product_id.id}, context=context)
120
self.pool.get('initial.stock.inventory.line').write(cr, uid, [inventory_line.id], {'prod_lot_id': prodlot_id}, context=context)
122
if inventory_line.product_id.perishable and not inventory_line.product_id.batch_management:
123
if not inventory_line.prodlot_name and inventory_line.expiry_date:
124
prodlot_ids = prodlot_obj.search(cr, uid, [
125
('type', '=', 'internal'),
126
('product_id', '=', inventory_line.product_id.id),
127
('life_date', '=', inventory_line.expiry_date),
130
self.pool.get('initial.stock.inventory.line').write(cr, uid, [inventory_line.id], {
131
'prodlot_name': prodlot_obj.read(cr, uid, prodlot_ids[0], ['name'], context=context)['name'],
134
return super(initial_stock_inventory, self).action_confirm(cr, uid, ids, context=context)
136
def action_done(self, cr, uid, ids, context=None):
137
""" Finish the inventory
143
if isinstance(ids, (int, long)):
146
self.check_integrity(cr, uid, ids, context=context)
148
move_obj = self.pool.get('stock.move')
149
prod_obj = self.pool.get('product.product')
150
sptc_obj = self.pool.get('standard.price.track.changes')
151
for inv in self.browse(cr, uid, ids, context=context):
152
# Set the cost price on product form with the new value, and process the stock move
153
for move in inv.move_ids:
154
new_std_price = move.price_unit
155
sptc_obj.track_change(cr,
158
_('Initial stock inventory %s') % inv.name,
160
'standard_price': new_std_price,
161
'old_price': move.product_id.standard_price,
164
prod_obj.write(cr, uid, move.product_id.id, {'standard_price': new_std_price}, context=context)
165
move_obj.action_done(cr, uid, move.id, context=context)
167
self.write(cr, uid, [inv.id], {'state':'done', 'date_done': time.strftime('%Y-%m-%d %H:%M:%S')}, context=context)
169
self.infolog(cr, uid, 'The Initial stock inventory id:%s has been validated' % inv.id)
173
def fill_lines(self, cr, uid, ids, context=None):
175
Fill all lines according to defined nomenclature level and sublist
180
if isinstance(ids, (int, long)):
184
wh_ids = self.pool.get('stock.warehouse').search(cr, uid, [])
186
location_id = self.pool.get('stock.warehouse').browse(cr, uid, wh_ids[0]).lot_stock_id.id
187
for inventory in self.browse(cr, uid, ids, context=context):
192
# Get all products for the defined nomenclature
193
if inventory.nomen_manda_3:
194
nom = inventory.nomen_manda_3.id
195
field = 'nomen_manda_3'
196
elif inventory.nomen_manda_2:
197
nom = inventory.nomen_manda_2.id
198
field = 'nomen_manda_2'
199
elif inventory.nomen_manda_1:
200
nom = inventory.nomen_manda_1.id
201
field = 'nomen_manda_1'
202
elif inventory.nomen_manda_0:
203
nom = inventory.nomen_manda_0.id
204
field = 'nomen_manda_0'
206
product_ids.extend(self.pool.get('product.product').search(cr, uid, [(field, '=', nom)], context=context))
208
# Get all products for the defined list
209
if inventory.sublist_id:
210
for line in inventory.sublist_id.product_ids:
211
product_ids.append(line.name.id)
213
# Check if products in already existing lines are in domain
215
for line in inventory.inventory_line_id:
216
if line.product_id.id in product_ids:
217
products.append(line.product_id.id)
219
self.pool.get('initial.stock.inventory.line').unlink(cr, uid, line.id, context=context)
222
c.update({'location': location_id, 'compute_child': False, 'to_date': inventory.date})
223
for product in self.pool.get('product.product').browse(cr, uid, product_ids, context=c):
224
# Check if the product is not already on the report
225
if product.type not in ('consu', 'service', 'service_recep') and product.id not in products:
226
batch_mandatory = product.batch_management
227
date_mandatory = product.perishable
228
values = {'product_id': product.id,
229
'uom_id': product.uom_id.id,
231
'average_cost': product.standard_price,
232
'hidden_batch_management_mandatory': batch_mandatory,
233
'hidden_perishable_mandatory': date_mandatory,
234
'inventory_id': inventory.id, }
235
v = self.pool.get('initial.stock.inventory.line').on_change_product_id(cr, uid, [], location_id, product.id, product.uom_id.id, False)['value']
236
# Remove product_qty from values because it has been computed before
240
values.update({'err_msg': 'You must assign a batch number'})
242
values.update({'err_msg': 'You must assign an expiry date'})
243
self.pool.get('initial.stock.inventory.line').create(cr, uid, values)
245
return {'type': 'ir.actions.act_window',
246
'res_model': 'initial.stock.inventory',
248
'view_mode': 'form,tree',
253
def get_nomen(self, cr, uid, id, field):
254
return self.pool.get('product.nomenclature').get_nomen(cr, uid, self, id, field, context={'withnum': 1})
256
def onChangeSearchNomenclature(self, cr, uid, id, position, type, nomen_manda_0, nomen_manda_1, nomen_manda_2, nomen_manda_3, num=True, context=None):
257
return self.pool.get('product.product').onChangeSearchNomenclature(cr, uid, 0, position, type, nomen_manda_0, nomen_manda_1, nomen_manda_2, nomen_manda_3, False, context={'withnum': 1})
259
initial_stock_inventory()
262
class initial_stock_inventory_line(osv.osv):
263
_name = 'initial.stock.inventory.line'
264
_description = "Initial Stock Inventory Line"
265
_inherit = 'stock.inventory.line'
267
def _get_error_msg(self, cr, uid, ids, field_name, args, context=None):
268
prodlot_obj = self.pool.get('stock.production.lot')
269
dt_obj = self.pool.get('date.tools')
272
for line in self.browse(cr, uid, ids, context=context):
274
if not line.location_id:
275
res[line.id] = _('You must define a stock location')
276
if line.hidden_batch_management_mandatory and not line.prodlot_name:
277
res[line.id] = _('You must define a batch number')
278
elif line.hidden_perishable_mandatory and not line.expiry_date:
279
res[line.id] = _('You must define an expiry date')
280
elif line.prodlot_name and line.expiry_date and line.product_id:
281
prodlot_ids = prodlot_obj.search(cr, uid, [
282
('name', '=', line.prodlot_name),
283
('product_id', '=', line.product_id.id),
286
prodlot = prodlot_obj.browse(cr, uid, prodlot_ids[0], context=context)
287
life_date = dt_obj.get_date_formatted(cr, uid, datetime=prodlot.life_date)
288
if prodlot.life_date != line.expiry_date:
289
res[line.id] = _('The batch number \'%s\' is already in the system but its expiry date is %s') % (line.prodlot_name, life_date)
293
def _get_bm_perishable(self, cr, uid, ids, field_name, args, context=None):
296
for line in self.browse(cr, uid, ids, context=context):
298
'hidden_batch_management_mandatory': line.product_id.batch_management,
299
'hidden_perishable_mandatory': line.product_id.perishable,
304
def _get_products(self, cr, uid, ids, context=None):
305
inv_ids = self.pool.get('initial.stock.inventory').search(cr, uid, [
306
('state', 'not in', ['done', 'cancel']),
308
return self.pool.get('initial.stock.inventory.line').search(cr, uid, [
309
('inventory_id', 'in', inv_ids),
310
('product_id', 'in', ids),
314
'inventory_id': fields.many2one('initial.stock.inventory', string='Inventory', ondelete='cascade'),
315
'prodlot_name': fields.char(size=64, string='Batch'),
316
'average_cost': fields.float(string='Initial average cost', digits_compute=dp.get_precision('Sale Price Computation'), required=True),
317
'currency_id': fields.many2one('res.currency', string='Functional currency', readonly=True),
318
'err_msg': fields.function(_get_error_msg, method=True, type='char', string='Message', store=False),
319
'hidden_perishable_mandatory': fields.function(
323
string='Hidden Flag for Perishable product',
324
multi='bm_perishable',
326
'initial.stock.inventory.line': (lambda self, cr, uid, ids, c=None: ids, ['product_id'], 10),
327
'product.product': (_get_products, ['perishable'], 20),
330
'hidden_batch_management_mandatory': fields.function(
334
string='Hidden Flag for Perishable product',
335
multi='bm_perishable',
337
'initial.stock.inventory.line': (lambda self, cr, uid, ids, c=None: ids, ['product_id'], 10),
338
'product.product': (_get_products, ['batch_management'], 20),
344
'currency_id': lambda obj, cr, uid, c: obj.pool.get('res.users').browse(cr, uid, uid).company_id.currency_id.id,
345
'average_cost': lambda *a: 0.00,
346
'product_qty': lambda *a: 0.00,
347
'reason_type_id': lambda obj, cr, uid, c: obj.pool.get('ir.model.data').get_object_reference(cr, uid, 'reason_types_moves', 'reason_type_stock_initialization')[1],
350
def _check_batch_management(self, cr, uid, ids, context=None):
352
check for batch management
354
for obj in self.browse(cr, uid, ids, context=context):
355
if obj.product_id.batch_management and obj.inventory_id.state not in ('draft', 'cancel'):
356
if not obj.prod_lot_id or obj.prod_lot_id.type != 'standard':
360
def _check_perishable(self, cr, uid, ids, context=None):
362
check for perishable ONLY
364
for obj in self.browse(cr, uid, ids, context=context):
365
if obj.product_id.perishable and not obj.product_id.batch_management and obj.inventory_id.state not in ('draft', 'cancel'):
366
if (not obj.prod_lot_id and not obj.expiry_date) or (obj.prod_lot_id and obj.prod_lot_id.type != 'internal'):
370
def _check_prodlot_need(self, cr, uid, ids, context=None):
372
If the inv line has a prodlot but does not need one, return False.
374
for obj in self.browse(cr, uid, ids, context=context):
375
if obj.prod_lot_id and obj.inventory_id.state not in ('draft', 'cancel'):
376
if not obj.product_id.perishable and not obj.product_id.batch_management:
380
def _check_same_cost(self, cr, uid, ids, context=None):
382
If the inv line has a different average cost than the other lines with the same product
384
for obj in self.browse(cr, uid, ids, context=context):
385
other_lines = self.search(cr, uid, [('product_qty', '!=', 0.00), ('inventory_id', '=', obj.inventory_id.id), ('product_id', '=', obj.product_id.id)], context=context)
386
if other_lines and obj.product_qty != 0.00:
387
cost = self.browse(cr, uid, other_lines[0], context=context).average_cost
388
if cost != obj.average_cost:
389
raise osv.except_osv(_('Error'), _('You cannot have two lines with the product %s and different average cost.') % self.pool.get('product.product').name_get(cr, uid, [obj.product_id.id])[0][1])
394
_constraints = [(_check_batch_management,
395
'You must assign a Batch Number which corresponds to Batch Number Mandatory Products.',
398
'You must assign a Batch Numbre which corresponds to Expiry Date Mandatory Products.',
400
(_check_prodlot_need,
401
'The selected product is neither Batch Number Mandatory nor Expiry Date Mandatory',
404
'You cannot have two lines with the same product and different average cost.',
405
['product_id', 'average_cost'])
408
def product_change(self, cr, uid, ids, product_id, location_id, field_change, change_price=False, prodlot_id=False):
410
Set the UoM with the default UoM of the product
412
value = {'product_uom': False,
413
'hidden_perishable_mandatory': False,
414
'hidden_batch_management_mandatory': False,}
417
product_obj = self.pool.get('product.product')
420
context = {'location': location_id, 'compute_child': False}
421
# Test the compatibility of the product with the location
422
value, test = product_obj._on_change_restriction_error(cr, uid, product_id, field_name=field_change, values=value, vals={'location_id': location_id})
426
context.update({'prodlot_id': prodlot_id})
427
product = product_obj.browse(cr, uid, product_id, context=context)
428
value.update({'product_uom': product.uom_id.id,
429
'hidden_perishable_mandatory': product.perishable,
430
'hidden_batch_management_mandatory': product.batch_management})
432
value.update({'average_cost': product.standard_price,})
434
# Don't recompute the product qty according to batch because no selection of batch
436
# value.update({'product_qty': product.qty_available})
438
return {'value': value}
440
def change_lot(self, cr, uid, ids, location_id, product, prod_lot_id, uom=False, to_date=False,):
441
res = super(initial_stock_inventory_line, self).change_lot(cr, uid, ids, location_id, product, prod_lot_id, uom=uom, to_date=to_date)
442
if 'warning' not in res:
443
if 'value' not in res:
444
res.update({'value': {}})
446
res['value'].update({'err_msg': ''})
450
def change_expiry(self, cr, uid, id, expiry_date, product_id, type_check, context=None):
451
res = super(initial_stock_inventory_line, self).change_expiry(cr, uid, id, expiry_date, product_id, type_check, context=None)
452
if 'warning' not in res:
453
if 'value' not in res:
454
res.udptae({'value': {}})
456
res['value'].update({'err_msg': ''})
460
def create(self, cr, uid, vals, context=None):
462
Set the UoM with the default UoM of the product
464
if vals.get('product_id', False):
465
product = self.pool.get('product.product').browse(cr, uid, vals['product_id'], context=context)
466
vals['product_uom'] = product.uom_id.id
468
return super(initial_stock_inventory_line, self).create(cr, uid, vals, context=context)
470
def write(self, cr, uid, ids, vals, context=None):
472
Set the UoM with the default UoM of the product
474
if vals.get('product_id', False):
475
vals['product_uom'] = self.pool.get('product.product').browse(cr, uid, vals['product_id'], context=context).uom_id.id
477
return super(initial_stock_inventory_line, self).write(cr, uid, ids, vals, context=context)
479
initial_stock_inventory_line()
481
class stock_cost_reevaluation(osv.osv):
482
_name = 'stock.cost.reevaluation'
483
_description = 'Cost reevaluation'
486
'name': fields.char(size=64, string='Reference', required=True, readonly=True, states={'draft': [('readonly', False)]}),
487
'date': fields.date(string='Creation date', required=True, readonly=True, states={'draft': [('readonly', False)]}),
488
'reevaluation_line_ids': fields.one2many('stock.cost.reevaluation.line', 'reevaluation_id', string='Lines',
489
readonly=True, states={'draft': [('readonly', False)]}),
490
'state': fields.selection([('draft', 'Draft'), ('confirm', 'Confirmed'), ('done', 'Done'), ('cancel', 'Cancel')],
491
string='State', readonly=True, required=True),
492
'sublist_id': fields.many2one('product.list', string='List/Sublist', ondelete='set null'),
493
'nomen_manda_0': fields.many2one('product.nomenclature', 'Main Type', ondelete='set null'),
494
'nomen_manda_1': fields.many2one('product.nomenclature', 'Group', ondelete='set null'),
495
'nomen_manda_2': fields.many2one('product.nomenclature', 'Family', ondelete='set null'),
496
'nomen_manda_3': fields.many2one('product.nomenclature', 'Root', ondelete='set null'),
500
'state': lambda *a: 'draft',
501
'date': lambda *a: time.strftime('%Y-%m-%d'),
505
('name_unique', "unique(name)", 'The Reference of the Product Cost Revaluation must be unique'),
508
def copy(self, cr, uid, ids, default=None, context=None):
510
Set the state to 'draft' and the creation date to the current date
514
name = self.read(cr, uid, ids, ['name'])['name']
516
new_name = '%s (copy %s)' % (name, i)
517
while self.search_count(cr, uid, [('name', '=', new_name)]):
519
new_name = '%s (copy %s)' % (name, i)
521
if not 'state' in default:
522
default.update({'state': 'draft'})
524
default.update({'date': time.strftime('%Y-%m-%d'),
527
return super(stock_cost_reevaluation, self).copy(cr, uid, ids, default=default, context=context)
529
def action_confirm(self, cr, uid, ids, context=None):
531
Confirm the cost reevaluation (don't change the price at this time)
533
if isinstance(ids, (int, long)):
536
for obj in self.browse(cr, uid, ids, context=context):
537
# Prevent confirmation without lines
538
if len(obj.reevaluation_line_ids) == 0:
539
raise osv.except_osv(_('Error'), _('Please enter at least one revaluation line before confirm it.'))
541
# Check if there are two lines with the same product
543
for line in obj.reevaluation_line_ids:
544
if line.product_id.id not in products:
545
products.append(line.product_id.id)
547
raise osv.except_osv(_('Error'), _('You cannot have two lines with the same product. (Product : [%s] %s)') % (line.product_id.default_code, line.product_id.name))
549
return self.write(cr, uid, ids, {'state': 'confirm'}, context=context)
551
def action_done(self, cr, uid, ids, context=None):
553
Change the price of the products in the lines
555
sptc_obj = self.pool.get('standard.price.track.changes')
557
if isinstance(ids, (int, long)):
560
for obj in self.browse(cr, uid, ids, context=context):
561
for line in obj.reevaluation_line_ids:
562
sptc_obj.track_change(cr,
565
_('Product cost reevaluation %s') % obj.name,
567
'standard_price': line.average_cost,
568
'old_price': line.product_id.standard_price,
570
self.pool.get('product.product').write(cr, uid, line.product_id.id, {'standard_price': line.average_cost})
572
return self.write(cr, uid, ids, {'state': 'done'}, context=context)
574
def action_cancel(self, cr, uid, ids, context=None):
576
Change the state of the document to cancel
578
if isinstance(ids, (int, long)):
581
return self.write(cr, uid, ids, {'state': 'cancel'}, context=context)
583
def action_cancel_draft(self, cr, uid, ids, context=None):
585
Change the state of the document to draft
587
if isinstance(ids, (int, long)):
590
return self.write(cr, uid, ids, {'state': 'draft'}, context=context)
592
def fill_lines(self, cr, uid, ids, context=None):
594
Fill all lines according to defined nomenclature level and sublist
599
if isinstance(ids, (int, long)):
602
for inventory in self.browse(cr, uid, ids, context=context):
607
# Get all products for the defined nomenclature
608
if inventory.nomen_manda_3:
609
nom = inventory.nomen_manda_3.id
610
field = 'nomen_manda_3'
611
elif inventory.nomen_manda_2:
612
nom = inventory.nomen_manda_2.id
613
field = 'nomen_manda_2'
614
elif inventory.nomen_manda_1:
615
nom = inventory.nomen_manda_1.id
616
field = 'nomen_manda_1'
617
elif inventory.nomen_manda_0:
618
nom = inventory.nomen_manda_0.id
619
field = 'nomen_manda_0'
621
product_ids.extend(self.pool.get('product.product').search(cr, uid, [(field, '=', nom)], context=context))
623
# Get all products for the defined list
624
if inventory.sublist_id:
625
for line in inventory.sublist_id.product_ids:
626
product_ids.append(line.name.id)
628
# Check if products in already existing lines are in domain
630
for line in inventory.reevaluation_line_ids:
631
if line.product_id.id in product_ids:
632
products.append(line.product_id.id)
634
self.pool.get('stock.cost.reevaluation.line').unlink(cr, uid, line.id, context=context)
636
for product in self.pool.get('product.product').browse(cr, uid, product_ids):
637
# Check if the product is not already on the report
638
if product.id not in products:
639
values = {'product_id': product.id,
640
'average_cost': product.standard_price,
641
'reevaluation_id': inventory.id, }
642
self.pool.get('stock.cost.reevaluation.line').create(cr, uid, values)
644
return {'type': 'ir.actions.act_window',
645
'res_model': 'stock.cost.reevaluation',
647
'view_mode': 'form,tree',
652
def get_nomen(self, cr, uid, id, field):
653
return self.pool.get('product.nomenclature').get_nomen(cr, uid, self, id, field, context={'withnum': 1})
655
def onChangeSearchNomenclature(self, cr, uid, id, position, type, nomen_manda_0, nomen_manda_1, nomen_manda_2, nomen_manda_3, num=True, context=None):
656
return self.pool.get('product.product').onChangeSearchNomenclature(cr, uid, 0, position, type, nomen_manda_0, nomen_manda_1, nomen_manda_2, nomen_manda_3, False, context={'withnum': 1})
658
stock_cost_reevaluation()
660
class stock_cost_reevaluation_line(osv.osv):
661
_name = 'stock.cost.reevaluation.line'
662
_description = 'Cost reevaluation line'
663
_rec_name = 'product_id'
666
'product_id': fields.many2one('product.product', string='Product', required=True),
667
'average_cost': fields.float(string='Average cost', digits_compute=dp.get_precision('Sale Price Computation'), required=True),
668
'currency_id': fields.many2one('res.currency', string='Currency', readonly=True),
669
'reevaluation_id': fields.many2one('stock.cost.reevaluation', string='Header'),
673
'currency_id': lambda obj, cr, uid, c = {}: obj.pool.get('res.users').browse(cr, uid, uid).company_id.currency_id.id,
676
def product_id_change(self, cr, uid, ids, product_id, context=None):
678
Change the average price with the cost price of the product
681
cost_price = self.pool.get('product.product').browse(cr, uid, product_id, context=context).standard_price
682
return {'value': {'average_cost': cost_price}}
684
return {'value': {'average_cost': 0.00}}
686
stock_cost_reevaluation_line()
688
class stock_move(osv.osv):
689
_inherit = 'stock.move'
692
'init_inv_ids': fields.many2many('initial.stock.inventory', 'initial_stock_inventory_move_rel', 'move_id', 'inventory_id', 'Created Moves'),