diff --git a/addons/mrp/security/ir.model.access.csv b/addons/mrp/security/ir.model.access.csv index 4b8ffc13d7b..dcbf6c866b4 100644 --- a/addons/mrp/security/ir.model.access.csv +++ b/addons/mrp/security/ir.model.access.csv @@ -67,4 +67,4 @@ "access_stock_picking_mrp_manager","stock.picking mrp_manager","stock.model_stock_picking","mrp.group_mrp_manager",1,0,0,0 "access_report_mrp_inout_user","report.mrp.inout user","model_report_mrp_inout","mrp.group_mrp_user",1,0,0,0 "access_report_workcenter_load_user","report.workcenter.load.user","model_report_workcenter_load","mrp.group_mrp_user",1,0,0,0 -"access_mrp_production","mrp.production user","model_mrp_production","purchase.group_purchase_user",1,0,0,0 +"access_mrp_bom","mrp.bom","model_mrp_bom","base.group_sale_salesman",1,0,0,0 diff --git a/addons/mrp/wizard/mrp_product_produce.py b/addons/mrp/wizard/mrp_product_produce.py index aea6fb41bc0..16729b7eccf 100644 --- a/addons/mrp/wizard/mrp_product_produce.py +++ b/addons/mrp/wizard/mrp_product_produce.py @@ -26,7 +26,7 @@ class mrp_product_produce(osv.osv_memory): _description = "Product Produce" _columns = { - 'product_qty': fields.float('Quantity', required=True), + 'product_qty': fields.float('Select Quantity', required=True), 'mode': fields.selection([('consume_produce', 'Consume & Produce'), ('consume', 'Consume Only')], 'Mode', required=True, help="'Consume only' mode will only consume the products with the quantity selected.\n" diff --git a/addons/product/product.py b/addons/product/product.py index 5e3834b6f56..f37f3aefaa4 100644 --- a/addons/product/product.py +++ b/addons/product/product.py @@ -69,7 +69,7 @@ class product_uom(osv.osv): 'name': fields.char('Name', size=64, required=True, translate=True), 'category_id': fields.many2one('product.uom.categ', 'UoM Category', required=True, ondelete='cascade', help="Quantity conversions may happen automatically between Units of Measure in the same category, according to their respective ratios."), - 'factor': fields.float('Ratio', required=True,digits=(12, 6), + 'factor': fields.float('Ratio', required=True,digits=(12, 12), help='How many times this UoM is smaller than the reference UoM in this category:\n'\ '1 * (reference unit) = ratio * (this unit)'), 'factor_inv': fields.function(_factor_inv, digits_compute=dp.get_precision('Product UoM'), @@ -347,7 +347,7 @@ class product_product(osv.osv): def _product_price(self, cr, uid, ids, name, arg, context={}): res = {} - quantity = context.get('quantity', 1) + quantity = context.get('quantity') or 1.0 pricelist = context.get('pricelist', False) if pricelist: for id in ids: diff --git a/addons/product_expiry/product_expiry.py b/addons/product_expiry/product_expiry.py index 01ce50dead8..fb53d9d0c03 100644 --- a/addons/product_expiry/product_expiry.py +++ b/addons/product_expiry/product_expiry.py @@ -45,19 +45,19 @@ class stock_production_lot(osv.osv): _columns = { 'life_date': fields.datetime('End of Life Date', - help='The date the lot may become dangerous and should not be consumed.'), + help='The date on which the lot may become dangerous and should not be consumed.'), 'use_date': fields.datetime('Best before Date', - help='The date the lot starts deteriorating without becoming dangerous.'), + help='The date on which the lot starts deteriorating without becoming dangerous.'), 'removal_date': fields.datetime('Removal Date', - help='The date the lot should be removed.'), - 'alert_date': fields.datetime('Alert Date', help="The date signifying an alert to notify about the production lot."), + help='The date on which the lot should be removed.'), + 'alert_date': fields.datetime('Alert Date', help="The date on which an alert should be notified about the production lot."), } # Assign dates according to products data def create(self, cr, uid, vals, context=None): newid = super(stock_production_lot, self).create(cr, uid, vals, context=context) obj = self.browse(cr, uid, newid, context=context) towrite = [] - for f in ('life_date','use_date','removal_date','alert_date'): + for f in ('life_date', 'use_date', 'removal_date', 'alert_date'): if not getattr(obj, f): towrite.append(f) context = context or {} @@ -82,8 +82,7 @@ class product_product(osv.osv): help='The number of days before a production lot starts deteriorating without becoming dangerous.'), 'removal_time': fields.integer('Product Removal Time', help='The number of days before a production lot should be removed.'), - 'alert_time': fields.integer('Product Alert Time', help="The number of days after which, needs an alert to notify about the production lot."), + 'alert_time': fields.integer('Product Alert Time', help="The number of days after which an alert should be notified about the production lot."), } product_product() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/addons/product_visible_discount/product_visible_discount.py b/addons/product_visible_discount/product_visible_discount.py index 6b1c60ca516..9e8c8f55643 100644 --- a/addons/product_visible_discount/product_visible_discount.py +++ b/addons/product_visible_discount/product_visible_discount.py @@ -43,7 +43,7 @@ class sale_order_line(osv.osv): uom=False, qty_uos=0, uos=False, name='', partner_id=False, lang=False, update_tax=True,date_order=False,packaging=False,fiscal_position=False, flag=False): - def get_real_price(res_dict, product_id, pricelist): + def get_real_price(res_dict, product_id, qty, uom, pricelist): item_obj = self.pool.get('product.pricelist.item') price_type_obj = self.pool.get('product.price.type') product_obj = self.pool.get('product.product') @@ -56,10 +56,17 @@ class sale_order_line(osv.osv): if item_base > 0: field_name = price_type_obj.browse(cr, uid, item_base).field - product_tmpl_id = product_obj.browse(cr, uid, product_id, context).product_tmpl_id.id + product = product_obj.browse(cr, uid, product_id, context) + product_tmpl_id = product.product_tmpl_id.id product_read = template_obj.read(cr, uid, product_tmpl_id, [field_name], context) - return product_read[field_name] + + factor = 1.0 + if uom and uom != product.uom_id.id: + product_uom_obj = self.pool.get('product.uom') + uom_data = product_uom_obj.browse(cr, uid, product.uom_id.id) + factor = uom_data.factor + return product_read[field_name] * factor res=super(sale_order_line, self).product_id_change(cr, uid, ids, pricelist, product, qty, @@ -84,7 +91,7 @@ class sale_order_line(osv.osv): pricelists = pricelist_obj.read(cr,uid,[pricelist],['visible_discount']) old_uom = product.uos_id or product.uom_id - new_list_price = get_real_price(list_price, product.id, pricelist) + new_list_price = get_real_price(list_price, product.id, qty, uom, pricelist) if(len(pricelists)>0 and pricelists[0]['visible_discount'] and list_price[pricelist] != 0): discount = (new_list_price - price) / new_list_price * 100 result['price_unit'] = new_list_price @@ -101,7 +108,7 @@ class account_invoice_line(osv.osv): def product_id_change(self, cr, uid, ids, product, uom, qty=0, name='', type='out_invoice', partner_id=False, fposition_id=False, price_unit=False, address_invoice_id=False, currency_id=False, context={}): res = super(account_invoice_line, self).product_id_change(cr, uid, ids, product, uom, qty, name, type, partner_id, fposition_id, price_unit, address_invoice_id, currency_id, context) - def get_real_price(res_dict, product_id, pricelist): + def get_real_price(res_dict, product_id, qty, uom, pricelist): item_obj = self.pool.get('product.pricelist.item') price_type_obj = self.pool.get('product.price.type') product_obj = self.pool.get('product.product') @@ -114,10 +121,17 @@ class account_invoice_line(osv.osv): if item_base > 0: field_name = price_type_obj.browse(cr, uid, item_base).field - product_tmpl_id = product_obj.browse(cr, uid, product_id, context).product_tmpl_id.id + product = product_obj.browse(cr, uid, product_id, context) + product_tmpl_id = product.product_tmpl_id.id product_read = template_obj.read(cr, uid, product_tmpl_id, [field_name], context) - return product_read[field_name] + + factor = 1.0 + if uom and uom != product.uom_id.id: + product_uom_obj = self.pool.get('product.uom') + uom_data = product_uom_obj.browse(cr, uid, product.uom_id.id) + factor = uom_data.factor + return product_read[field_name] * factor if product: pricelist_obj = self.pool.get('product.pricelist') @@ -133,7 +147,7 @@ class account_invoice_line(osv.osv): raise osv.except_osv(_('No Purchase Pricelist Found !'),_("You must first define a pricelist for Supplier !")) price_unit_res = pricelist_obj.price_get(cr, uid, [pricelist], product.id, qty or 1.0, partner_id, {'uom': uom})[pricelist] price_unit = price_unit_res[pricelist] - real_price = get_real_price(price_unit_res, product.id, pricelist) + real_price = get_real_price(price_unit_res, product.id, qty, uom, pricelist) else: if partner_id: pricelist = partner_obj.browse(cr, uid, partner_id).property_product_pricelist.id @@ -142,7 +156,7 @@ class account_invoice_line(osv.osv): price_unit_res = pricelist_obj.price_get(cr, uid, [pricelist], product.id, qty or 1.0, partner_id, {'uom': uom}) price_unit = price_unit_res[pricelist] - real_price = get_real_price(price_unit_res, product.id, pricelist) + real_price = get_real_price(price_unit_res, product.id, qty, uom, pricelist) if pricelist: pricelists=pricelist_obj.read(cr,uid,[pricelist],['visible_discount']) if(len(pricelists)>0 and pricelists[0]['visible_discount'] and real_price != 0): diff --git a/addons/purchase/test/purchase_from_picking.yml b/addons/purchase/test/purchase_from_picking.yml index 20dd3f0f907..5ef3058cdc2 100644 --- a/addons/purchase/test/purchase_from_picking.yml +++ b/addons/purchase/test/purchase_from_picking.yml @@ -138,7 +138,7 @@ pick_ids = [x.id for x in pur_id1.picking_ids] id = self.create(cr, uid, {'invoice_date': '2010-05-11', 'journal_id': ref('account.expenses_journal')}, {'active_ids': pick_ids}) - self.create_invoice(cr, uid, [id], {"active_ids": pick_ids}) + self.create_invoice(cr, uid, [id], {"active_ids": pick_ids, "active_id": pick_ids[0]}) - I check that an invoice_id field of Delivery&Invoices gets bind with the value. - diff --git a/addons/sale/security/ir.model.access.csv b/addons/sale/security/ir.model.access.csv index 11718051d04..39b1996ee88 100644 --- a/addons/sale/security/ir.model.access.csv +++ b/addons/sale/security/ir.model.access.csv @@ -1,5 +1,5 @@ "id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" -"access_sale_shop","sale.shop","model_sale_shop","base.group_user",1,0,0,0 +"access_sale_shop","sale.shop","model_sale_shop","base.group_user",1,1,0,0 "access_sale_order","sale.order","model_sale_order","base.group_sale_salesman",1,1,1,0 "access_sale_order_line","sale.order.line","model_sale_order_line","base.group_sale_salesman",1,1,1,1 "access_account_invoice_tax_salesman","account_invoice_tax salesman","account.model_account_invoice_tax","base.group_sale_salesman",1,1,1,0 diff --git a/addons/sale/test/invoice_on_shipped_qty.yml b/addons/sale/test/invoice_on_shipped_qty.yml index 3ed4387067a..fb217302ce4 100644 --- a/addons/sale/test/invoice_on_shipped_qty.yml +++ b/addons/sale/test/invoice_on_shipped_qty.yml @@ -74,7 +74,7 @@ ids = [x.id for x in sale_id.picking_ids] wiz_id = self.create(cr, uid, {'invoice_date': '2010-07-17', 'journal_id': ref('account.sales_journal')}, {'active_ids': ids}) - self.create_invoice(cr, uid, [wiz_id], {"active_ids": ids}) + self.create_invoice(cr, uid, [wiz_id], {"active_ids": ids, "active_id": ids[0]}) - I verify whether the invoice has been generated for SO - diff --git a/addons/sale/test/picking_order_policy.yml b/addons/sale/test/picking_order_policy.yml index b12bddd7ecc..de18c1c4426 100644 --- a/addons/sale/test/picking_order_policy.yml +++ b/addons/sale/test/picking_order_policy.yml @@ -67,7 +67,7 @@ ids = [x.id for x in sale_id.picking_ids] wiz_id = self.create(cr, uid, {'invoice_date': '2010-07-15', 'journal_id': ref('account.sales_journal')}, {'active_ids': ids}) - self.create_invoice(cr, uid, [wiz_id], {"active_ids": ids}) + self.create_invoice(cr, uid, [wiz_id], {"active_ids": ids, "active_id": ids[0]}) - I check that an invoice has been created. - diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 7473de0adc1..b57106b54ea 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -930,6 +930,25 @@ class stock_picking(osv.osv): '''Call after the creation of the invoice''' return + def _get_invoice_type(self, pick): + src_usage = dest_usage = None + inv_type = None + if pick.invoice_state == '2binvoiced': + if pick.move_lines: + src_usage = pick.move_lines[0].location_id.usage + dest_usage = pick.move_lines[0].location_dest_id.usage + if pick.type == 'out' and dest_usage == 'supplier': + inv_type = 'in_refund' + elif pick.type == 'out' and dest_usage == 'customer': + inv_type = 'out_invoice' + elif pick.type == 'in' and src_usage == 'supplier': + inv_type = 'in_invoice' + elif pick.type == 'in' and src_usage == 'customer': + inv_type = 'out_refund' + else: + inv_type = 'out_invoice' + return inv_type + def action_invoice_create(self, cr, uid, ids, journal_id=False, group=False, type='out_invoice', context=None): """ Creates invoice based on the invoice state selected for picking. @@ -945,7 +964,7 @@ class stock_picking(osv.osv): invoice_line_obj = self.pool.get('account.invoice.line') invoices_group = {} res = {} - + inv_type = type for picking in self.browse(cr, uid, ids, context=context): if picking.invoice_state != '2binvoiced': continue @@ -954,8 +973,11 @@ 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) - if type in ('out_invoice', 'out_refund'): + if inv_type in ('out_invoice', 'out_refund'): account_id = partner.property_account_receivable.id payment_term_id = self._get_payment_term(cr, uid, picking) else: @@ -980,7 +1002,7 @@ class stock_picking(osv.osv): invoice_vals = { 'name': picking.name, 'origin': (picking.name or '') + (picking.origin and (':' + picking.origin) or ''), - 'type': type, + 'type': inv_type, 'account_id': account_id, 'partner_id': partner.id, 'address_invoice_id': address_invoice_id, @@ -1012,7 +1034,7 @@ class stock_picking(osv.osv): else: name = move_line.name - if type in ('out_invoice', 'out_refund'): + if inv_type in ('out_invoice', 'out_refund'): account_id = move_line.product_id.product_tmpl_id.\ property_account_income.id if not account_id: @@ -1026,14 +1048,14 @@ class stock_picking(osv.osv): property_account_expense_categ.id price_unit = self._get_price_unit_invoice(cr, uid, - move_line, type) + move_line, inv_type) discount = self._get_discount_invoice(cr, uid, move_line) - tax_ids = self._get_taxes_invoice(cr, uid, move_line, type) + tax_ids = self._get_taxes_invoice(cr, uid, move_line, inv_type) account_analytic_id = self._get_account_analytic_invoice(cr, uid, picking, move_line) #set UoS if it's a sale and the picking doesn't have one uos_id = move_line.product_uos and move_line.product_uos.id or False - if not uos_id and type in ('out_invoice', 'out_refund'): + if not uos_id and inv_type in ('out_invoice', 'out_refund'): uos_id = move_line.product_uom.id account_id = self.pool.get('account.fiscal.position').map_account(cr, uid, partner.property_account_position, account_id) @@ -1053,7 +1075,7 @@ class stock_picking(osv.osv): self._invoice_line_hook(cr, uid, move_line, invoice_line_id) invoice_obj.button_compute(cr, uid, [invoice_id], context=context, - set_total=(type in ('in_invoice', 'in_refund'))) + set_total=(inv_type in ('in_invoice', 'in_refund'))) self.write(cr, uid, [picking.id], { 'invoice_state': 'invoiced', }, context=context) @@ -1353,7 +1375,7 @@ class stock_production_lot(osv.osv): 'name': fields.char('Serial Number', size=64, required=True, help="Unique serial number, will be displayed as: PREFIX/SERIAL [INT_REF]"), 'ref': fields.char('Internal Reference', size=256, help="Internal reference number in case it differs from the manufacturer's serial number"), 'prefix': fields.char('Prefix', size=64, help="Optional prefix to prepend when displaying this serial number: PREFIX/SERIAL [INT_REF]"), - 'product_id': fields.many2one('product.product', 'Product', required=True), + 'product_id': fields.many2one('product.product', 'Product', required=True, domain=[('type', '<>', 'service')]), 'date': fields.datetime('Creation Date', required=True), 'stock_available': fields.function(_get_stock, fnct_search=_stock_search, method=True, type="float", string="Available", select=True, help="Current quantity of products with this Production Lot Number available in company warehouses", @@ -1480,7 +1502,7 @@ class stock_move(osv.osv): 'move_dest_id': fields.many2one('stock.move', 'Destination Move', help="Optional: next stock move when chaining them", select=True), 'move_history_ids': fields.many2many('stock.move', 'stock_move_history_ids', 'parent_id', 'child_id', 'Move History (child moves)'), 'move_history_ids2': fields.many2many('stock.move', 'stock_move_history_ids', 'child_id', 'parent_id', 'Move History (parent moves)'), - 'picking_id': fields.many2one('stock.picking', 'Picking List', select=True,states={'done': [('readonly', True)]}), + 'picking_id': fields.many2one('stock.picking', 'Reference', select=True,states={'done': [('readonly', True)]}), 'note': fields.text('Notes'), 'state': fields.selection([('draft', 'Draft'), ('waiting', 'Waiting'), ('confirmed', 'Confirmed'), ('assigned', 'Available'), ('done', 'Done'), ('cancel', 'Cancelled')], 'State', readonly=True, select=True, help='When the stock move is created it is in the \'Draft\' state.\n After that it is set to \'Confirmed\' state.\n If stock is available state is set to \'Available\'.\n When the picking is done the state is \'Done\'.\ @@ -2231,7 +2253,7 @@ class stock_move(osv.osv): quantity_rest = quantity uos_qty_rest = uos_qty if move.product_id.track_production and location_id: - res += self.split_lines(cr, uid, [move.id], quantity_rest, split_by_qty=1, context=context) + res += self.action_split(cr, uid, [move.id], quantity_rest, split_by_qty=1, context=context) else: res += [move.id] update_val = { diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml index ec3082a1611..5f5206a5647 100644 --- a/addons/stock/stock_view.xml +++ b/addons/stock/stock_view.xml @@ -465,7 +465,7 @@ - + @@ -746,7 +746,7 @@