diff --git a/addons/mrp/mrp.py b/addons/mrp/mrp.py index c71565442e5..7ba22270866 100644 --- a/addons/mrp/mrp.py +++ b/addons/mrp/mrp.py @@ -446,18 +446,18 @@ class mrp_production(osv.osv): 'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'mrp.production', context=c), } _order = 'priority desc, date_planned asc'; - + def _check_qty(self, cr, uid, ids): orders = self.browse(cr, uid, ids) for order in orders: if order.product_qty <= 0: return False return True - + _constraints = [ (_check_qty, 'Order quantity cannot be negative or zero !', ['product_qty']), ] - + def unlink(self, cr, uid, ids, context=None): productions = self.read(cr, uid, ids, ['state']) unlink_ids = [] @@ -639,16 +639,16 @@ class mrp_production(osv.osv): @param production_mode: specify production mode (consume/consume&produce). @return: True """ - + stock_mov_obj = self.pool.get('stock.move') production = self.browse(cr, uid, production_id) - + final_product_todo = [] produced_qty = 0 if production_mode == 'consume_produce': produced_qty = production_qty - + for produced_product in production.move_created_ids2: if (produced_product.scrapped) or (produced_product.product_id.id<>production.product_id.id): continue @@ -658,7 +658,7 @@ class mrp_production(osv.osv): consumed_products = {} check = {} scrapped = map(lambda x:x.scrapped,production.move_lines2).count(True) - + for consumed_product in production.move_lines2: consumed = consumed_product.product_qty if consumed_product.scrapped: @@ -671,9 +671,9 @@ class mrp_production(osv.osv): if (len(production.move_lines2) - scrapped) > len(production.product_lines): check[consumed_product.product_id.id] += consumed_product.product_qty consumed = check[consumed_product.product_id.id] - rest_consumed = produced_qty * f.product_qty / production.product_qty - consumed + rest_consumed = produced_qty * f.product_qty / production.product_qty - consumed consumed_products[consumed_product.product_id.id] = rest_consumed - + for raw_product in production.move_lines: for f in production.product_lines: if f.product_id.id == raw_product.product_id.id: @@ -712,7 +712,7 @@ class mrp_production(osv.osv): new_parent_ids.append(final_product.id) for new_parent_id in new_parent_ids: stock_mov_obj.write(cr, uid, [raw_product.id], {'move_history_ids': [(4,new_parent_id)]}) - + wf_service = netsvc.LocalService("workflow") wf_service.trg_validate(uid, 'mrp.production', production_id, 'button_produce_done', cr) return True @@ -750,7 +750,7 @@ class mrp_production(osv.osv): 'account_id': account, 'general_account_id': wc.costs_general_account_id.id, 'journal_id': wc.costs_journal_id.id, - 'code': wc.code + 'code': wc.code, } ) return amount @@ -827,7 +827,7 @@ class mrp_production(osv.osv): 'company_id': production.company_id.id, } res_final_id = move_obj.create(cr, uid, data) - + self.write(cr, uid, [production.id], {'move_created_ids': [(6, 0, [res_final_id])]}) moves = [] for line in production.product_lines: @@ -879,7 +879,7 @@ class mrp_production(osv.osv): 'company_id': production.company_id.id, }) wf_service.trg_validate(uid, 'procurement.order', proc_id, 'button_confirm', cr) - proc_ids.append(proc_id) + proc_ids.append(proc_id) wf_service.trg_validate(uid, 'stock.picking', picking_id, 'button_confirm', cr) self.write(cr, uid, [production.id], {'picking_id': picking_id, 'move_lines': [(6,0,moves)], 'state':'confirmed'}) message = _("Manufacturing order '%s' is scheduled for the %s.") % ( diff --git a/addons/procurement/procurement.py b/addons/procurement/procurement.py index 359586fae7e..3ac5ac2632f 100644 --- a/addons/procurement/procurement.py +++ b/addons/procurement/procurement.py @@ -62,11 +62,11 @@ mrp_property() class StockMove(osv.osv): _inherit = 'stock.move' - + _columns= { 'procurements': fields.one2many('procurement.order', 'move_id', 'Procurements'), } - + def copy(self, cr, uid, id, default=None, context=None): default = default or {} default['procurements'] = [] @@ -134,7 +134,7 @@ class procurement_order(osv.osv): if s['state'] in ['draft','cancel']: unlink_ids.append(s['id']) else: - raise osv.except_osv(_('Invalid action !'), + raise osv.except_osv(_('Invalid action !'), _('Cannot delete Procurement Order(s) which are in %s State!') % \ s['state']) return osv.osv.unlink(self, cr, uid, unlink_ids, context=context) @@ -169,7 +169,12 @@ class procurement_order(osv.osv): """ Checks if move is done or not. @return: True or False. """ - return all(procurement.move_id.state == 'done' for procurement in self.browse(cr, uid, ids)) + res = True + for proc in self.browse(cr, uid, ids, context): + if proc.move_id: + if not proc.move_id.state=='done': + res = False + return res # # This method may be overrided by objects that override procurement.order @@ -283,7 +288,7 @@ class procurement_order(osv.osv): if procurement.product_id.product_tmpl_id.supply_method <> 'buy': return False if not procurement.product_id.seller_ids: - cr.execute('update procurement_order set message=%s where id=%s', + cr.execute('update procurement_order set message=%s where id=%s', (_('No supplier defined for this product !'), procurement.id)) return False partner = procurement.product_id.seller_id #Taken Main Supplier of Product of Procurement. @@ -293,7 +298,7 @@ class procurement_order(osv.osv): return False address_id = partner_obj.address_get(cr, uid, [partner.id], ['delivery'])['delivery'] if not address_id: - cr.execute('update procurement_order set message=%s where id=%s', + cr.execute('update procurement_order set message=%s where id=%s', (_('No address defined for the supplier'), procurement.id)) return False return True @@ -314,7 +319,7 @@ class procurement_order(osv.osv): move_obj = self.pool.get('stock.move') for procurement in self.browse(cr, uid, ids): if procurement.product_qty <= 0.00: - raise osv.except_osv(_('Data Insufficient !'), + raise osv.except_osv(_('Data Insufficient !'), _('Please check the Quantity in Procurement Order(s), it should not be less than 1!')) if procurement.product_id.type in ('product', 'consu'): if not procurement.move_id: @@ -342,7 +347,7 @@ class procurement_order(osv.osv): """ Changes procurement state to Running and writes message. @return: True """ - self.write(cr, uid, ids, {'state': 'running', + self.write(cr, uid, ids, {'state': 'running', 'message': _('from stock: products assigned.')}) return True @@ -365,8 +370,8 @@ class procurement_order(osv.osv): ok = ok and self.pool.get('stock.move').action_assign(cr, uid, [id]) cr.execute('select count(id) from stock_warehouse_orderpoint where product_id=%s', (procurement.product_id.id,)) if not cr.fetchone()[0]: - cr.execute('update procurement_order set message=%s where id=%s', - (_('Not enough stock and no minimum orderpoint rule defined.'), + cr.execute('update procurement_order set message=%s where id=%s', + (_('Not enough stock and no minimum orderpoint rule defined.'), procurement.id)) message = _("Procurement '%s' is in exception: not enough stock.") % \ (procurement.name,) @@ -479,7 +484,7 @@ class StockPicking(osv.osv): wf_service.trg_validate(user, 'procurement.order', procurement.id, 'button_check', cursor) return res - + StockPicking() class stock_warehouse_orderpoint(osv.osv): @@ -517,7 +522,7 @@ class stock_warehouse_orderpoint(osv.osv): 'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'stock.warehouse.orderpoint', context=c) } _sql_constraints = [ - ('qty_multiple_check', 'CHECK( qty_multiple > 0 )', + ('qty_multiple_check', 'CHECK( qty_multiple > 0 )', _('Qty Multiple must be greater than zero.')), ] @@ -531,7 +536,7 @@ class stock_warehouse_orderpoint(osv.osv): v = {'location_id': w.lot_stock_id.id} return {'value': v} return {} - + def onchange_product_id(self, cr, uid, ids, product_id, context={}): """ Finds UoM for changed product. @param product_id: Changed id of product. @@ -542,7 +547,7 @@ class stock_warehouse_orderpoint(osv.osv): v = {'product_uom': prod.uom_id.id} return {'value': v} return {} - + def copy(self, cr, uid, id, default=None,context={}): if not default: default = {} @@ -550,6 +555,6 @@ class stock_warehouse_orderpoint(osv.osv): 'name': self.pool.get('ir.sequence').get(cr, uid, 'stock.orderpoint') or '', }) return super(stock_warehouse_orderpoint, self).copy(cr, uid, id, default, context) - + stock_warehouse_orderpoint() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/product/product.py b/addons/product/product.py index a3266070903..f37f3aefaa4 100644 --- a/addons/product/product.py +++ b/addons/product/product.py @@ -24,7 +24,7 @@ import decimal_precision as dp import math from _common import rounding -import re +import re from tools.translate import _ def is_pair(x): @@ -106,9 +106,14 @@ class product_uom(osv.osv): from_unit, to_unit = uoms[-1], uoms[0] return self._compute_qty_obj(cr, uid, from_unit, qty, to_unit) - def _compute_qty_obj(self, cr, uid, from_unit, qty, to_unit, context={}): + def _compute_qty_obj(self, cr, uid, from_unit, qty, to_unit, context=None): + if context is None: + context = {} if from_unit.category_id.id <> to_unit.category_id.id: - return qty + if context.get('raise-exception', True): + raise osv.except_osv(_('Error !'), _('Conversion from Product UoM m to Default UoM PCE is not possible as they both belong to different Category!.')) + else: + return qty amount = qty / from_unit.factor if to_unit: amount = rounding(amount * to_unit.factor, to_unit.rounding) diff --git a/addons/purchase/security/ir.model.access.csv b/addons/purchase/security/ir.model.access.csv index ef854f8f038..693452d4e09 100644 --- a/addons/purchase/security/ir.model.access.csv +++ b/addons/purchase/security/ir.model.access.csv @@ -7,8 +7,8 @@ "access_stock_warehouse_purchase_user","stock.warehouse","stock.model_stock_warehouse","group_purchase_user",1,0,0,0 "access_stock_picking_purchase_user","stock.picking","stock.model_stock_picking","group_purchase_user",1,1,1,1 "access_stock_move_purchase_user","stock.move","stock.model_stock_move","group_purchase_user",1,1,1,1 -"access_purchase_order_stock_worker","purchase.order","model_purchase_order","stock.group_stock_user",1,0,0,0 -"access_purchase_order_line_stock_worker","purchase.order.line","model_purchase_order_line","stock.group_stock_user",1,0,0,0 +"access_purchase_order_stock_worker","purchase.order","model_purchase_order","stock.group_stock_user",1,1,1,0 +"access_purchase_order_line_stock_worker","purchase.order.line","model_purchase_order_line","stock.group_stock_user",1,0,1,0 "access_account_tax_purchase_user","account.tax","account.model_account_tax","group_purchase_user",1,0,0,0 "access_report_purchase_order","purchase.report","model_purchase_report","group_purchase_manager",1,1,1,1 "access_report_purchase_order_user","purchase.report user","model_purchase_report","group_purchase_user",1,0,0,0 @@ -42,3 +42,5 @@ "access_account_move_reconcile","account.move.reconcile","account.model_account_move_reconcile","group_purchase_user",1,1,1,1 "access_report_stock_move","report.stock.move.manager","stock.model_report_stock_move","group_purchase_manager",1,1,1,1 "access_report_stock_move_user","report.stock.move.user","stock.model_report_stock_move","group_purchase_user",1,0,0,0 +"access_stock_production_lot_user","stock.production.lot user","stock.model_stock_production_lot","group_purchase_user",1,0,1,0 +"access_stock_production_lot_revision","stock.production.lot.revision","stock.model_stock_production_lot_revision","group_purchase_user",1,0,1,0 diff --git a/addons/purchase/stock.py b/addons/purchase/stock.py index ea9cacd7979..987c76e372d 100644 --- a/addons/purchase/stock.py +++ b/addons/purchase/stock.py @@ -37,7 +37,7 @@ class stock_move(osv.osv): """ reference_amount, reference_currency_id = super(stock_move, self)._get_reference_accounting_values_for_valuation(cr, uid, move, context=context) if move.product_id.cost_method != 'average' or not move.price_unit: - # no average price costing or cost not specified during picking validation, we will + # no average price costing or cost not specified during picking validation, we will # plug the purchase line values if they are found. if move.purchase_line_id and move.picking_id.purchase_id.pricelist_id: reference_amount, reference_currency_id = move.purchase_line_id.price_unit, move.picking_id.purchase_id.pricelist_id.currency_id.id @@ -123,6 +123,8 @@ class stock_partial_picking(osv.osv_memory): for pick in pick_obj.browse(cr, uid, context.get('active_ids', [])): has_product_cost = (pick.type == 'in' and pick.purchase_id) for m in pick.move_lines: + if m.state in ('done','cancel') : + continue if has_product_cost and m.product_id.cost_method == 'average' and m.purchase_line_id: # We use the original PO unit purchase price as the basis for the cost, expressed # in the currency of the PO (i.e the PO's pricelist currency) diff --git a/addons/purchase_requisition/security/ir.model.access.csv b/addons/purchase_requisition/security/ir.model.access.csv index d3c6b66de92..4e14688ecc5 100644 --- a/addons/purchase_requisition/security/ir.model.access.csv +++ b/addons/purchase_requisition/security/ir.model.access.csv @@ -3,3 +3,5 @@ "access_purchase_requisition_line","purchase.requisition.line","model_purchase_requisition_line","purchase.group_purchase_user",1,1,1,1 "access_purchase_requisition_manager","purchase.requisition manager","model_purchase_requisition","purchase.group_purchase_manager",1,0,0,0 "access_purchase_requisition_line_manager","purchase.requisition.line manager","model_purchase_requisition_line","purchase.group_purchase_manager",1,0,0,0 +"access_purchase_requisition","purchase.requisition","model_purchase_requisition","stock.group_stock_manager",1,0,1,0 +"access_purchase_requisition_line","purchase.requisition.line","model_purchase_requisition_line","stock.group_stock_manager",1,0,1,0 diff --git a/addons/stock/product.py b/addons/stock/product.py index ddb582f4a3c..67c6d7c8448 100644 --- a/addons/stock/product.py +++ b/addons/stock/product.py @@ -241,12 +241,12 @@ class product_product(osv.osv): where.append(tuple([to_date])) elif from_date: date_str = "date>=%s" - date_values = [from_date] + date_values = [from_date] elif to_date: date_str = "date<=%s" date_values = [to_date] - + # TODO: perhaps merge in one query. if date_values: where.append(tuple(date_values)) @@ -282,13 +282,14 @@ class product_product(osv.osv): uoms = uom_obj.browse(cr, uid, list(set(uoms)), context=context) for o in uoms: uoms_o[o.id] = o + ctx = {'raise-exception': False} #TOCHECK: before change uom of product, stock move line are in old uom. for amount, prod_id, prod_uom in results: amount = uom_obj._compute_qty_obj(cr, uid, uoms_o[prod_uom], amount, - uoms_o[context.get('uom', False) or product2uom[prod_id]]) + uoms_o[context.get('uom', False) or product2uom[prod_id]], context=ctx) res[prod_id] += amount for amount, prod_id, prod_uom in results2: amount = uom_obj._compute_qty_obj(cr, uid, uoms_o[prod_uom], amount, - uoms_o[context.get('uom', False) or product2uom[prod_id]]) + uoms_o[context.get('uom', False) or product2uom[prod_id]], context=ctx) res[prod_id] -= amount return res @@ -328,7 +329,7 @@ class product_product(osv.osv): 'track_outgoing': fields.boolean('Track Outgoing Lots', help="Forces to specify a Production Lot for all moves containing this product and going to a Customer Location"), 'location_id': fields.dummy(string='Stock Location', relation='stock.location', type='many2one'), 'valuation':fields.selection([('manual_periodic', 'Periodical (manual)'), - ('real_time','Real Time (automated)'),], 'Inventory Valuation', + ('real_time','Real Time (automated)'),], 'Inventory Valuation', help="If real-time valuation is enabled for a product, the system will automatically write journal entries corresponding to stock moves." \ "The inventory variation account set on the product category will represent the current inventory value, and the stock input and stock output account will hold the counterpart moves for incoming and outgoing products." , required=True), diff --git a/addons/stock/report/report_stock_move.py b/addons/stock/report/report_stock_move.py index 49c3f8fb327..15e430d0599 100644 --- a/addons/stock/report/report_stock_move.py +++ b/addons/stock/report/report_stock_move.py @@ -62,7 +62,7 @@ class report_stock_move(osv.osv): CREATE OR REPLACE view report_stock_move AS ( SELECT min(sm_id) as id, - al.dp as date, + date_trunc('day',al.dp) as date, al.curr_year as year, al.curr_month as month, al.curr_day as day, diff --git a/addons/stock/security/ir.model.access.csv b/addons/stock/security/ir.model.access.csv index 4d9c44edd79..e1a22e9fb69 100644 --- a/addons/stock/security/ir.model.access.csv +++ b/addons/stock/security/ir.model.access.csv @@ -10,11 +10,11 @@ "access_stock_tracking_user","stock.tracking user","model_stock_tracking","stock.group_stock_user",1,1,1,1 "access_stock_tracking_manager","stock.tracking manager","model_stock_tracking","stock.group_stock_manager",1,0,0,0 "access_stock_picking_user","stock.picking user","model_stock_picking","stock.group_stock_user",1,1,1,1 -"access_stock_picking_manager","stock.picking manager","model_stock_picking","stock.group_stock_manager",1,0,0,0 +"access_stock_picking_manager","stock.picking manager","model_stock_picking","stock.group_stock_manager",1,1,0,0 "access_stock_production_lot_manager","stock.production.lot manager","model_stock_production_lot","stock.group_stock_manager",1,0,0,0 "access_stock_production_lot_user","stock.production.lot user","model_stock_production_lot","stock.group_stock_user",1,1,1,1 "access_stock_production_lot_revision","stock.production.lot.revision","model_stock_production_lot_revision","stock.group_stock_user",1,1,1,1 -"access_stock_move_manager","stock.move manager","model_stock_move","stock.group_stock_manager",1,0,0,0 +"access_stock_move_manager","stock.move manager","model_stock_move","stock.group_stock_manager",1,1,0,0 "access_stock_move_user","stock.move user","model_stock_move","stock.group_stock_user",1,1,1,1 "access_stock_inventory_user","stock.inventory user","model_stock_inventory","stock.group_stock_user",1,1,1,1 "access_stock_inventory_manager","stock.inventory manager","model_stock_inventory","stock.group_stock_manager",1,0,0,0 diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 5b89bfd78c5..bc87ec7cfe6 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -577,8 +577,8 @@ class stock_picking(osv.osv): return res cr.execute("""select picking_id, - min(date), - max(date) + min(date_expected), + max(date_expected) from stock_move where @@ -586,8 +586,8 @@ class stock_picking(osv.osv): group by picking_id""",(tuple(ids),)) for pick, dt1, dt2 in cr.fetchall(): - res[pick]['min_date'] = dt1 - res[pick]['max_date'] = dt2 + res[pick]['min_date'] = dt1 + res[pick]['max_date'] = dt2 return res def create(self, cr, user, vals, context=None): @@ -973,7 +973,7 @@ class stock_picking(osv.osv): if not partner: raise osv.except_osv(_('Error, no partner !'), _('Please put a partner on the picking list if you want to generate invoice.')) - + if not inv_type: inv_type = self._get_invoice_type(picking) @@ -1610,7 +1610,7 @@ class stock_move(osv.osv): warning = {} if (location.usage == 'internal') and (product_qty > (prodlot.stock_available or 0.0)): warning = { - 'title': _('Bad Lot Assignation !'), + 'title': _('Insufficient Stock in Lot !'), 'message': _('You are moving %.2f products but only %.2f available in this lot.') % (product_qty, prodlot.stock_available or 0.0) } return {'warning': warning} @@ -2398,7 +2398,7 @@ class stock_inventory(osv.osv): 'date_done': fields.datetime('Date done'), 'inventory_line_id': fields.one2many('stock.inventory.line', 'inventory_id', 'Inventories', states={'done': [('readonly', True)]}), 'move_ids': fields.many2many('stock.move', 'stock_inventory_move_rel', 'inventory_id', 'move_id', 'Created Moves'), - 'state': fields.selection( (('draft', 'Draft'), ('done', 'Done'), ('cancel','Cancelled')), 'State', readonly=True, select=True), + 'state': fields.selection( (('draft', 'Draft'), ('done', 'Done'), ('confirm','Confirmed'),('cancel','Cancelled')), 'State', readonly=True, select=True), 'company_id': fields.many2one('res.company','Company',required=True,select=True), } _defaults = { @@ -2416,6 +2416,13 @@ class stock_inventory(osv.osv): return self.pool.get('stock.move').create(cr, uid, move_vals) def action_done(self, cr, uid, ids, context=None): + move_obj = self.pool.get('stock.move') + for inv in self.browse(cr, uid, ids, context=context): + move_obj.action_done(cr, uid, [x.id for x in inv.move_ids], context=context) + self.write(cr, uid, [inv.id], {'state':'done'}, context=context) + return True + + def action_confirm(self, cr, uid, ids, context=None): """ Finishes the inventory and writes its finished date @return: True """ @@ -2444,7 +2451,6 @@ class stock_inventory(osv.osv): 'prodlot_id': lot_id, 'date': inv.date, 'date': inv.date, - 'state': 'done' } if change > 0: value.update( { @@ -2466,7 +2472,7 @@ class stock_inventory(osv.osv): move_ids.append(self._inventory_line_hook(cr, uid, line, value)) message = _('Inventory') + " '" + inv.name + "' "+ _("is done.") self.log(cr, uid, inv.id, message) - self.write(cr, uid, [inv.id], {'state': 'done', 'date_done': time.strftime('%Y-%m-%d %H:%M:%S'), 'move_ids': [(6, 0, move_ids)]}) + self.write(cr, uid, [inv.id], {'state': 'confirm', 'date_done': time.strftime('%Y-%m-%d %H:%M:%S'), 'move_ids': [(6, 0, move_ids)]}) return True def action_cancel(self, cr, uid, ids, context=None): diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml index 61bc8b887de..3e708843927 100644 --- a/addons/stock/stock_view.xml +++ b/addons/stock/stock_view.xml @@ -118,12 +118,27 @@ - + +