diff --git a/addons/mrp/mrp_view.xml b/addons/mrp/mrp_view.xml index 8aae0062a331e..52e0f539b803f 100644 --- a/addons/mrp/mrp_view.xml +++ b/addons/mrp/mrp_view.xml @@ -746,7 +746,7 @@ <field name="move_lines2" nolabel="1" options="{'reload_on_button': true}"> <tree colors="red:scrapped==True;blue:state == 'draft';black:state in ('confirmed','ready','in_production');gray:state == 'cancel' " string="Consumed Products" editable="bottom"> <field name="product_id" readonly="1"/> - <field name="restrict_lot_id" context="{'product_id': product_id}" groups="stock.group_tracking_lot"/> + <field name="restrict_lot_id" context="{'product_id': product_id}" groups="stock.group_production_lot"/> <field name="product_qty" readonly="1"/> <field name="product_uom" readonly="1" string="Unit of Measure" groups="product.group_uom"/> <field name="state" invisible="1"/> @@ -774,7 +774,7 @@ <tree colors="red:scrapped==True;blue:state == 'draft';black:state in('confirmed','ready','in_production');gray:state in('cancel','done') " string="Finished Products"> <field name="product_id" readonly="1"/> <field name="product_qty" readonly="1"/> - <field name="restrict_lot_id" groups="stock.group_tracking_lot"/> + <field name="restrict_lot_id" groups="stock.group_production_lot"/> <field name="product_uom" readonly="1" string="Unit of Measure" groups="product.group_uom"/> <field name="location_dest_id" readonly="1" string="Destination Loc." widget="selection" groups="stock.group_locations"/> <field name="scrapped" invisible="1"/> diff --git a/addons/mrp/wizard/mrp_product_produce_view.xml b/addons/mrp/wizard/mrp_product_produce_view.xml index 666be7d5114a0..859bebc2b43af 100644 --- a/addons/mrp/wizard/mrp_product_produce_view.xml +++ b/addons/mrp/wizard/mrp_product_produce_view.xml @@ -18,16 +18,16 @@ <field name="lot_id" domain="[('product_id', '=', product_id)]" context="{'default_product_id':product_id}" attrs="{'required': [('track_production', '=', True), ('mode', '=', 'consume_produce')]}" - groups="stock.group_tracking_lot"/> + groups="stock.group_production_lot"/> </group> <group string="To Consume"> - <field name="consume_lines"> + <field name="consume_lines" nolabel="1"> <tree string="Consume Lines" editable="top"> <field name="product_id"/> <field name="product_qty"/> <field name="lot_id" domain="[('product_id', '=', product_id)]" context="{'default_product_id':product_id}" - groups="stock.group_tracking_lot"/> + groups="stock.group_production_lot"/> </tree> </field> </group> diff --git a/addons/mrp/wizard/stock_move_view.xml b/addons/mrp/wizard/stock_move_view.xml index ebd948633c29d..86588927c5788 100644 --- a/addons/mrp/wizard/stock_move_view.xml +++ b/addons/mrp/wizard/stock_move_view.xml @@ -15,7 +15,7 @@ <field name="product_qty" class="oe_inline"/> <field name="product_uom" class="oe_inline" readonly="1" groups="product.group_uom"/> </div> - <field name="restrict_lot_id" domain="[('product_id','=',product_id)]" groups="stock.group_tracking_lot" + <field name="restrict_lot_id" domain="[('product_id','=',product_id)]" groups="stock.group_production_lot" context="{'default_product_id': product_id}"/> <field name="location_id" groups="stock.group_locations"/> </group> diff --git a/addons/mrp_repair/views/report_mrprepairorder.xml b/addons/mrp_repair/views/report_mrprepairorder.xml index 2897fee1fd92f..a6d00ba5b15fd 100644 --- a/addons/mrp_repair/views/report_mrprepairorder.xml +++ b/addons/mrp_repair/views/report_mrprepairorder.xml @@ -30,7 +30,7 @@ <h2> <span t-if="o.state != 'draft'">Repair Order N°:</span> - <span t-if="o.state == 'draft'">Repair Quotation N°:</span> + <span t-if="o.state == 'draft'">Repair Quotation N°:</span> <span t-field="o.name"/> </h2> @@ -41,7 +41,9 @@ </div> <div class="col-xs-3" groups="stock.group_production_lot"> <strong>Lot Number</strong> - <span t-field="o.prodlot_id.name"/> + <t t-if="o.lot_id"> + <span t-field="o.lot_id.name"/> + </t> </div> <div t-if="o.guarantee_limit" class="col-xs-3"> <strong>Guarantee Limit:</strong> diff --git a/addons/procurement/procurement.py b/addons/procurement/procurement.py index 2ebc800ec04b9..e45651a30a22a 100644 --- a/addons/procurement/procurement.py +++ b/addons/procurement/procurement.py @@ -64,7 +64,7 @@ class procurement_group(osv.osv): } _defaults = { 'name': lambda self, cr, uid, c: self.pool.get('ir.sequence').get(cr, uid, 'procurement.group') or '', - 'move_type': lambda self, cr, uid, c: 'one' + 'move_type': lambda self, cr, uid, c: 'direct' } class procurement_rule(osv.osv): @@ -267,7 +267,7 @@ def _check(self, cr, uid, procurement, context=None): # # Scheduler # - def run_scheduler(self, cr, uid, use_new_cursor=False, context=None): + def run_scheduler(self, cr, uid, use_new_cursor=False, company_id = False, context=None): ''' Call the scheduler to check the procurement order. This is intented to be done for all existing companies at the same time, so we're running all the methods as SUPERUSER to avoid intercompany and access rights issues. @@ -288,8 +288,11 @@ def run_scheduler(self, cr, uid, use_new_cursor=False, context=None): cr = openerp.registry(cr.dbname).cursor() # Run confirmed procurements + dom = [('state', '=', 'confirmed')] + if company_id: + dom += [('company_id', '=', company_id)] while True: - ids = self.search(cr, SUPERUSER_ID, [('state', '=', 'confirmed')], context=context) + ids = self.search(cr, SUPERUSER_ID, dom, context=context) if not ids: break self.run(cr, SUPERUSER_ID, ids, context=context) @@ -298,8 +301,11 @@ def run_scheduler(self, cr, uid, use_new_cursor=False, context=None): # Check if running procurements are done offset = 0 + dom = [('state', '=', 'running')] + if company_id: + dom += [('company_id', '=', company_id)] while True: - ids = self.search(cr, SUPERUSER_ID, [('state', '=', 'running')], offset=offset, context=context) + ids = self.search(cr, SUPERUSER_ID, dom, offset=offset, context=context) if not ids: break done = self.check(cr, SUPERUSER_ID, ids, context=context) diff --git a/addons/procurement/wizard/schedulers_all.py b/addons/procurement/wizard/schedulers_all.py index 5c712b3af38dd..34d4758c5d5da 100644 --- a/addons/procurement/wizard/schedulers_all.py +++ b/addons/procurement/wizard/schedulers_all.py @@ -37,8 +37,12 @@ def _procure_calculation_all(self, cr, uid, ids, context=None): """ proc_obj = self.pool.get('procurement.order') #As this function is in a new thread, i need to open a new cursor, because the old one may be closed + new_cr = self.pool.cursor() - proc_obj.run_scheduler(new_cr, uid, use_new_cursor=new_cr.dbname, context=context) + user = self.pool.get('res.users').browse(new_cr, uid, uid, context=context) + comps = [x.id for x in user.company_ids] + for comp in comps: + proc_obj.run_scheduler(new_cr, uid, use_new_cursor=new_cr.dbname, company_id = comp, context=context) #close the new cursor new_cr.close() return {} diff --git a/addons/product_expiry/product_expiry.py b/addons/product_expiry/product_expiry.py index e311356dbbd38..6979344bbccfb 100644 --- a/addons/product_expiry/product_expiry.py +++ b/addons/product_expiry/product_expiry.py @@ -92,7 +92,7 @@ def _get_quants(self, cr, uid, ids, context=None): def apply_removal_strategy(self, cr, uid, location, product, qty, domain, removal_strategy, context=None): if removal_strategy == 'fefo': - order = 'removal_date, id' + order = 'removal_date, in_date, id' return self._quants_get_order(cr, uid, location, product, qty, domain, order, context=context) return super(stock_quant, self).apply_removal_strategy(cr, uid, location, product, qty, domain, removal_strategy, context=context) diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index bfdd83e087214..09cc4c301a42b 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -700,6 +700,7 @@ def _prepare_order_line_move(self, cr, uid, order, order_line, picking_id, group 'origin': order.name, 'route_ids': order.picking_type_id.warehouse_id and [(6, 0, [x.id for x in order.picking_type_id.warehouse_id.route_ids])] or [], 'warehouse_id':order.picking_type_id.warehouse_id.id, + 'invoice_state': order.invoice_method == 'picking' and '2binvoiced' or 'none' } diff_quantity = order_line.product_qty @@ -709,9 +710,10 @@ def _prepare_order_line_move(self, cr, uid, order, order_line, picking_id, group tmp.update({ 'product_uom_qty': min(procurement_qty, diff_quantity), 'product_uos_qty': min(procurement_qty, diff_quantity), - 'move_dest_id': procurement.move_dest_id.id, # blabla - 'group_id': procurement.group_id.id or group_id, # blabla to check ca devrait etre bon et groupé dans le meme picking qd meme + 'move_dest_id': procurement.move_dest_id.id, #move destination is same as procurement destination + 'group_id': procurement.group_id.id or group_id, #move group is same as group of procurements if it exists, otherwise take another group 'procurement_id': procurement.id, + 'invoice_state': procurement.rule_id.invoice_state or (procurement.location_id and procurement.location_id.usage == 'customer' and procurement.invoice_state) or (order.invoice_method == 'picking' and '2binvoiced') or 'none', #dropship case takes from sale }) diff_quantity -= min(procurement_qty, diff_quantity) res.append(tmp) @@ -1299,6 +1301,7 @@ def make_po(self, cr, uid, ids, context=None): res[procurement.id] = False else: schedule_date = self._get_purchase_schedule_date(cr, uid, procurement, company, context=context) + purchase_date = self._get_purchase_order_date(cr, uid, procurement, company, schedule_date, context=context) line_vals = self._get_po_line_values_from_proc(cr, uid, procurement, partner, company, schedule_date, context=context) #look for any other draft PO for the same supplier, to attach the new line on instead of creating a new draft one available_draft_po_ids = po_obj.search(cr, uid, [ @@ -1306,6 +1309,10 @@ def make_po(self, cr, uid, ids, context=None): ('location_id', '=', procurement.location_id.id), ('company_id', '=', procurement.company_id.id), ('dest_address_id', '=', procurement.partner_dest_id.id)], context=context) if available_draft_po_ids: po_id = available_draft_po_ids[0] + po_rec = po_obj.browse(cr, uid, po_id, context=context) + #if the product has to be ordered earlier those in the existing PO, we replace the purchase date on the order to avoid ordering it too late + if datetime.strptime(po_rec.date_order, DEFAULT_SERVER_DATE_FORMAT) > purchase_date: + po_obj.write(cr, uid, [po_id], {'date_order': purchase_date}, context=context) #look for any other PO line in the selected PO with same product and UoM to sum quantities instead of creating a new po line available_po_line_ids = po_line_obj.search(cr, uid, [('order_id', '=', po_id), ('product_id', '=', line_vals['product_id']), ('product_uom', '=', line_vals['product_uom'])], context=context) if available_po_line_ids: @@ -1318,7 +1325,6 @@ def make_po(self, cr, uid, ids, context=None): po_line_id = po_line_obj.create(cr, SUPERUSER_ID, line_vals, context=context) linked_po_ids.append(procurement.id) else: - purchase_date = self._get_purchase_order_date(cr, uid, procurement, company, schedule_date, context=context) name = seq_obj.get(cr, uid, 'purchase.order') or _('PO: %s') % procurement.name po_vals = { 'name': name, @@ -1363,6 +1369,13 @@ class product_template(osv.Model): _name = 'product.template' _inherit = 'product.template' + def _get_buy_route(self, cr, uid, context=None): + + buy_route = self.pool.get('ir.model.data').xmlid_to_res_id(cr, uid, 'purchase.route_warehouse0_buy') + if buy_route: + return [buy_route] + return [] + def _purchase_count(self, cr, uid, ids, field_name, arg, context=None): res = dict.fromkeys(ids, 0) for template in self.browse(cr, uid, ids, context=context): @@ -1374,6 +1387,7 @@ def _purchase_count(self, cr, uid, ids, field_name, arg, context=None): } _defaults = { 'purchase_ok': 1, + 'route_ids': _get_buy_route, } class product_product(osv.Model): @@ -1451,15 +1465,9 @@ class account_invoice_line(osv.Model): readonly=True), } -class product_product(osv.osv): - _inherit = "product.product" +class product_template(osv.osv): + _inherit = "product.template" - def _get_buy_route(self, cr, uid, context=None): - buy_route = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'purchase', 'route_warehouse0_buy')[1] - return [buy_route] - _defaults = { - 'route_ids': _get_buy_route, - } # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/purchase/stock.py b/addons/purchase/stock.py index 69d970b7be6b5..26d2ff1002f42 100644 --- a/addons/purchase/stock.py +++ b/addons/purchase/stock.py @@ -55,6 +55,33 @@ def copy(self, cr, uid, id, default=None, context=None): }) return super(stock_move, self).copy(cr, uid, id, default, context) + + def _create_invoice_line_from_vals(self, cr, uid, move, invoice_line_vals, context=None): + invoice_line_id = super(stock_move, self)._create_invoice_line_from_vals(cr, uid, move, invoice_line_vals, context=context) + if move.purchase_line_id: + purchase_line = move.purchase_line_id + self.pool.get('purchase.order.line').write(cr, uid, [purchase_line.id], { + 'invoice_lines': [(4, invoice_line_id)] + }, context=context) + self.pool.get('purchase.order').write(cr, uid, [purchase_line.order_id.id], { + 'invoice_ids': [(4, invoice_line_vals['invoice_id'])], + }) + return invoice_line_id + + def _get_master_data(self, cr, uid, move, company, context=None): + if move.purchase_line_id: + purchase_order = move.purchase_line_id.order_id + return purchase_order.partner_id, purchase_order.create_uid.id, purchase_order.pricelist_id.currency_id.id + return super(stock_move, self)._get_master_data(cr, uid, move, company, context=context) + + def _get_invoice_line_vals(self, cr, uid, move, partner, inv_type, context=None): + res = super(stock_move, self)._get_invoice_line_vals(cr, uid, move, partner, inv_type, context=context) + if move.purchase_line_id: + purchase_line = move.purchase_line_id + res['invoice_line_tax_id'] = [(6, 0, [x.id for x in purchase_line.taxes_id])] + res['price_unit'] = purchase_line.price_unit + return res + class stock_picking(osv.osv): _inherit = 'stock.picking' diff --git a/addons/sale_stock/sale_stock.py b/addons/sale_stock/sale_stock.py index b3bbd25339224..63f6068f3c224 100644 --- a/addons/sale_stock/sale_stock.py +++ b/addons/sale_stock/sale_stock.py @@ -388,7 +388,7 @@ def action_cancel(self, cr, uid, ids, context=None): return super(stock_move, self).action_cancel(cr, uid, ids, context=context) def _create_invoice_line_from_vals(self, cr, uid, move, invoice_line_vals, context=None): - invoice_line_id = self.pool.get('account.invoice.line').create(cr, uid, invoice_line_vals, context=context) + invoice_line_id = super(stock_move, self)._create_invoice_line_from_vals(cr, uid, move, invoice_line_vals, context=context) if move.procurement_id and move.procurement_id.sale_line_id: sale_line = move.procurement_id.sale_line_id self.pool.get('sale.order.line').write(cr, uid, [sale_line.id], { diff --git a/addons/stock/procurement.py b/addons/stock/procurement.py index a8fc778f2e659..b8d7a03c9f298 100644 --- a/addons/stock/procurement.py +++ b/addons/stock/procurement.py @@ -261,7 +261,7 @@ def do_view_pickings(self, cr, uid, ids, context=None): result['domain'] = "[('group_id','in',[" + ','.join(map(str, list(group_ids))) + "])]" return result - def run_scheduler(self, cr, uid, use_new_cursor=False, context=None): + def run_scheduler(self, cr, uid, use_new_cursor=False, company_id=False, context=None): ''' Call the scheduler in order to check the running procurements (super method), to check the minimum stock rules and the availability of moves. This function is intended to be run for all the companies at the same time, so @@ -286,8 +286,7 @@ def run_scheduler(self, cr, uid, use_new_cursor=False, context=None): move_obj = self.pool.get('stock.move') #Minimum stock rules - company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id - self._procure_orderpoint_confirm(cr, SUPERUSER_ID, use_new_cursor=False, company_id=company.id, context=context) + self._procure_orderpoint_confirm(cr, SUPERUSER_ID, use_new_cursor=False, company_id=company_id, context=context) #Search all confirmed stock_moves and try to assign them confirmed_ids = move_obj.search(cr, uid, [('state', '=', 'confirmed')], limit=None, order='priority desc, date_expected asc', context=context) @@ -331,7 +330,7 @@ def _product_virtual_get(self, cr, uid, order_point): [order_point.product_id.id], context={'location': order_point.location_id.id})[order_point.product_id.id]['virtual_available'] - def _procure_orderpoint_confirm(self, cr, uid, use_new_cursor=False, company_id=False, context=None): + def _procure_orderpoint_confirm(self, cr, uid, use_new_cursor=False, company_id = False, context=None): ''' Create procurement based on Orderpoint @@ -341,14 +340,15 @@ def _procure_orderpoint_confirm(self, cr, uid, use_new_cursor=False, company_id= if context is None: context = {} if use_new_cursor: - cr = openerp.registry(cr.dbname).db.cursor() + cr = openerp.registry(cr.dbname).cursor() orderpoint_obj = self.pool.get('stock.warehouse.orderpoint') procurement_obj = self.pool.get('procurement.order') offset = 0 ids = [1] + dom = company_id and [('company_id', '=', company_id)] or [] while ids: - ids = orderpoint_obj.search(cr, uid, [('company_id', '=', company_id)], offset=offset, limit=100) + ids = orderpoint_obj.search(cr, uid, dom, offset=offset, limit=100) for op in orderpoint_obj.browse(cr, uid, ids, context=context): prods = self._product_virtual_get(cr, uid, op) if prods is None: diff --git a/addons/stock/product.py b/addons/stock/product.py index 0cf7df5e83604..1cd677706f655 100644 --- a/addons/stock/product.py +++ b/addons/stock/product.py @@ -171,13 +171,13 @@ def _search_product_quantity(self, cr, uid, obj, name, domain, context): def _product_available_text(self, cr, uid, ids, field_names=None, arg=False, context=None): res = {} for product in self.browse(cr, uid, ids, context=context): - res[product.id] = str(product.qty_available) + _(" In Stock") + res[product.id] = str(product.qty_available) + _(" On Hand") return res _columns = { 'reception_count': fields.function(_stock_move_count, string="Reception", type='integer', multi='pickings'), 'delivery_count': fields.function(_stock_move_count, string="Delivery", type='integer', multi='pickings'), - 'qty_in_stock': fields.function(_product_available_text, type='char'), + 'qty_available_text': fields.function(_product_available_text, type='char'), 'qty_available': fields.function(_product_available, multi='qty_available', type='float', digits_compute=dp.get_precision('Product Unit of Measure'), string='Quantity On Hand', @@ -277,6 +277,12 @@ def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, res['fields']['qty_available']['string'] = _('Produced Qty') return res + + def action_view_routes(self, cr, uid, ids, context=None): + template_obj = self.pool.get("product.template") + templ_ids = list(set([x.product_tmpl_id.id for x in self.browse(cr, uid, ids, context=context)])) + return template_obj.action_view_routes(cr, uid, templ_ids, context=context) + class product_template(osv.osv): _name = 'product.template' _inherit = 'product.template' diff --git a/addons/stock/product_view.xml b/addons/stock/product_view.xml index 2a7ad044fbc2a..c3941eb188706 100644 --- a/addons/stock/product_view.xml +++ b/addons/stock/product_view.xml @@ -193,7 +193,7 @@ <field name="inherit_id" ref="product.product_normal_form_view"/> <field name="arch" type="xml"> <group name="status" position="before"> - <group name="lot" groups="stock.group_tracking_lot,stock.group_production_lot" string="Lots"> + <group name="lot" groups="stock.group_production_lot" string="Lots"> <field name="track_all" groups="stock.group_production_lot"/> <field name="track_incoming" groups="stock.group_production_lot" attrs="{'invisible': [('track_all', '=', True)]}"/> <field name="track_outgoing" groups="stock.group_production_lot" attrs="{'invisible': [('track_all', '=', True)]}"/> @@ -202,13 +202,13 @@ <xpath expr="//div[@name='buttons']" position="inside"> <button class="oe_stat_button" name="%(product_open_quants)d" - icon="fa-bank" + icon="fa-building-o" type="action" attrs="{'invisible':[('type', '=', 'service')]}" groups="stock.group_locations"> - <div><field name="qty_in_stock"/></div> + <div><field name="qty_available_text"/></div> </button> <button class="oe_inline oe_stat_button" string="Moves" name= "%(act_product_stock_move_open)d" type="action" attrs="{'invisible':[('type', '=', 'service')]}" groups="stock.group_stock_user" icon="fa-arrows-v"/> <button class="oe_inline oe_stat_button" name="%(product_open_orderpoint)d" type="action" - attrs="{'invisible':[('type', '=', 'service')]}" icon="fa-pinterest" string="Reordering Rules"/> + attrs="{'invisible':[('type', '=', 'service')]}" icon="fa-refresh" string="Reordering Rules"/> </xpath> </field> </record> diff --git a/addons/stock/security/ir.model.access.csv b/addons/stock/security/ir.model.access.csv index 9ce558781be2c..8a94f0274083c 100644 --- a/addons/stock/security/ir.model.access.csv +++ b/addons/stock/security/ir.model.access.csv @@ -60,7 +60,7 @@ access_stock_location_path_internal_user,stock location path internal user,model access_stock_location_path_sale_manager,stock.location.path partner salemanager,model_stock_location_path,base.group_sale_manager,1,1,1,1 access_stock_location_path_stock_user,stock.location.path stock user,model_stock_location_path,stock.group_stock_user,1,1,1,1 access_stock_location_path,stock.location.path,model_stock_location_path,base.group_sale_salesman,1,0,0,0 -access_stock_location_route,stock.location.route,model_stock_location_route,stock.group_stock_manager,1,1,1,1 +access_stock_location_route_stock_manager,stock.location.route,model_stock_location_route,stock.group_stock_manager,1,1,1,1 access_stock_location_route,stock.location.route,model_stock_location_route,base.group_user,1,0,0,0 access_procurement_rule,procurement.rule.flow,model_procurement_rule,base.group_sale_salesman,1,0,0,0 access_procurement_rule_internal,procurement.rule.flow internal,model_procurement_rule,base.group_user,1,0,0,0 diff --git a/addons/stock/security/stock_security.xml b/addons/stock/security/stock_security.xml index f44d354f12111..044ff1333cde9 100644 --- a/addons/stock/security/stock_security.xml +++ b/addons/stock/security/stock_security.xml @@ -50,7 +50,7 @@ <field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field> </record> - <record model="ir.rule" id="stock_picking_rule"> + <record model="ir.rule" id="stock_picking_type_rule"> <field name="name">Stock Picking Type multi-company</field> <field name="model_id" search="[('model','=','stock.picking.type')]" model="ir.model"/> <field name="global" eval="True"/> diff --git a/addons/stock/stock.py b/addons/stock/stock.py index d6d28c919e626..7e529b9047ad3 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -272,27 +272,28 @@ def _get_inventory_value(self, cr, uid, quant, context=None): _columns = { 'name': fields.function(_get_quant_name, type='char', string='Identifier'), - 'product_id': fields.many2one('product.product', 'Product', required=True, ondelete="restrict"), - 'location_id': fields.many2one('stock.location', 'Location', required=True, ondelete="restrict"), - 'qty': fields.float('Quantity', required=True, help="Quantity of products in this quant, in the default unit of measure of the product"), - 'package_id': fields.many2one('stock.quant.package', string='Package', help="The package containing this quant"), - 'packaging_type_id': fields.related('package_id', 'packaging_id', type='many2one', relation='product.packaging', string='Type of packaging', store=True), - 'reservation_id': fields.many2one('stock.move', 'Reserved for Move', help="The move the quant is reserved for"), - 'lot_id': fields.many2one('stock.production.lot', 'Lot'), + 'product_id': fields.many2one('product.product', 'Product', required=True, ondelete="restrict", readonly=True), + 'location_id': fields.many2one('stock.location', 'Location', required=True, ondelete="restrict", readonly=True), + 'qty': fields.float('Quantity', required=True, help="Quantity of products in this quant, in the default unit of measure of the product", readonly=True), + 'package_id': fields.many2one('stock.quant.package', string='Package', help="The package containing this quant", readonly=True), + 'packaging_type_id': fields.related('package_id', 'packaging_id', type='many2one', relation='product.packaging', string='Type of packaging', readonly=True, store=True), + 'reservation_id': fields.many2one('stock.move', 'Reserved for Move', help="The move the quant is reserved for", readonly=True), + 'lot_id': fields.many2one('stock.production.lot', 'Lot', readonly=True), 'cost': fields.float('Unit Cost'), - 'owner_id': fields.many2one('res.partner', 'Owner', help="This is the owner of the quant"), + 'owner_id': fields.many2one('res.partner', 'Owner', help="This is the owner of the quant", readonly=True), - 'create_date': fields.datetime('Creation Date'), - 'in_date': fields.datetime('Incoming Date'), + 'create_date': fields.datetime('Creation Date', readonly=True), + 'in_date': fields.datetime('Incoming Date', readonly=True), 'history_ids': fields.many2many('stock.move', 'stock_quant_move_rel', 'quant_id', 'move_id', 'Moves', help='Moves that operate(d) on this quant'), - 'company_id': fields.many2one('res.company', 'Company', help="The company to which the quants belong", required=True), + 'company_id': fields.many2one('res.company', 'Company', help="The company to which the quants belong", required=True, readonly=True), 'inventory_value': fields.function(_calc_inventory_value, string="Inventory Value", type='float', readonly=True), # Used for negative quants to reconcile after compensated by a new positive one - 'propagated_from_id': fields.many2one('stock.quant', 'Linked Quant', help='The negative quant this is coming from'), - 'negative_move_id': fields.many2one('stock.move', 'Move Negative Quant', help='If this is a negative quant, this will be the move that caused this negative quant.'), - 'negative_dest_location_id': fields.related('negative_move_id', 'location_dest_id', type='many2one', relation='stock.location', string="Negative Destination Location", help="Technical field used to record the destination location of a move that created a negative quant"), + 'propagated_from_id': fields.many2one('stock.quant', 'Linked Quant', help='The negative quant this is coming from', readonly=True), + 'negative_move_id': fields.many2one('stock.move', 'Move Negative Quant', help='If this is a negative quant, this will be the move that caused this negative quant.', readonly=True), + 'negative_dest_location_id': fields.related('negative_move_id', 'location_dest_id', type='many2one', relation='stock.location', string="Negative Destination Location", readonly=True, + help="Technical field used to record the destination location of a move that created a negative quant"), } _defaults = { @@ -606,7 +607,6 @@ def _check_location(self, cr, uid, location, context=None): raise osv.except_osv(_('Error'), _('You cannot move to a location of type view %s.') % (location.name)) return True - #---------------------------------------------------------- # Stock Picking #---------------------------------------------------------- @@ -1248,6 +1248,7 @@ def _create_extra_moves(self, cr, uid, picking, context=None): ''' move_obj = self.pool.get('stock.move') operation_obj = self.pool.get('stock.pack.operation') + moves = [] for op in picking.pack_operation_ids: for product_id, remaining_qty in operation_obj._get_remaining_prod_quantities(cr, uid, op, context=context).items(): if remaining_qty > 0: @@ -1260,9 +1261,12 @@ def _create_extra_moves(self, cr, uid, picking, context=None): 'product_uom': product.uom_id.id, 'product_uom_qty': remaining_qty, 'name': _('Extra Move: ') + product.name, - 'state': 'confirmed', + 'state': 'draft', } - move_obj.create(cr, uid, vals, context=context) + moves.append(move_obj.create(cr, uid, vals, context=context)) + if moves: + move_obj.action_confirm(cr, uid, moves, context=context) + return moves def rereserve_quants(self, cr, uid, picking, move_ids=[], context=None): """ Unreserve quants then try to reassign quants.""" @@ -1289,11 +1293,13 @@ def do_transfer(self, cr, uid, picking_ids, context=None): else: need_rereserve, all_op_processed = self.picking_recompute_remaining_quantities(cr, uid, picking, context=context) #create extra moves in the picking (unexpected product moves coming from pack operations) + todo_move_ids = [] if not all_op_processed: - self._create_extra_moves(cr, uid, picking, context=context) + todo_move_ids += self._create_extra_moves(cr, uid, picking, context=context) + picking.refresh() #split move lines eventually - todo_move_ids = [] + toassign_move_ids = [] for move in picking.move_lines: remaining_qty = move.remaining_qty @@ -1371,7 +1377,7 @@ def action_pack(self, cr, uid, picking_ids, operation_filter_ids=None, context=N op = operation if (operation.qty_done < operation.product_qty): new_operation = stock_operation_obj.copy(cr, uid, operation.id, {'product_qty': operation.qty_done,'qty_done': operation.qty_done}, context=context) - stock_operation_obj.write(cr, uid, operation.id, {'product_qty': operation.product_qty - operation.qty_done,'qty_done': 0}, context=context) + stock_operation_obj.write(cr, uid, operation.id, {'product_qty': operation.product_qty - operation.qty_done,'qty_done': 0, 'lot_id': False}, context=context) op = stock_operation_obj.browse(cr, uid, new_operation, context=context) pack_operation_ids.append(op.id) for record in op.linked_move_operation_ids: @@ -1783,7 +1789,7 @@ def _prepare_procurement_from_move(self, cr, uid, move, context=None): 'move_dest_id': move.id, 'group_id': group_id, 'route_ids': [(4, x.id) for x in move.route_ids], - 'warehouse_id': move.warehouse_id and move.warehouse_id.id or False, + 'warehouse_id': move.warehouse_id.id or (move.picking_type_id and move.picking_type_id.warehouse_id.id or False), 'priority': move.priority, } @@ -3521,7 +3527,6 @@ def _apply(self, cr, uid, rule, move, context=None): # ------------------------- from openerp.report import report_sxw -report_sxw.report_sxw('report.stock.quant.package.barcode', 'stock.quant.package', 'addons/stock/report/package_barcode.rml') class stock_package(osv.osv): """ @@ -3818,8 +3823,8 @@ def action_drop_down(self, cr, uid, ids, context=None): if pack_op.qty_done < pack_op.product_qty: # we split the operation in two op = self.copy(cr, uid, pack_op.id, {'product_qty': pack_op.qty_done, 'qty_done': pack_op.qty_done}, context=context) - self.write(cr, uid, ids, {'product_qty': pack_op.product_qty - pack_op.qty_done, 'qty_done': 0}, context=context) - processed_ids.append(op) + self.write(cr, uid, [pack_op.id], {'product_qty': pack_op.product_qty - pack_op.qty_done, 'qty_done': 0, 'lot_id': False}, context=context) + processed_ids.append(op) self.write(cr, uid, processed_ids, {'processed': 'true'}, context=context) def create_and_assign_lot(self, cr, uid, id, name, context=None): @@ -3828,10 +3833,16 @@ def create_and_assign_lot(self, cr, uid, id, name, context=None): obj = self.browse(cr,uid,id,context) product_id = obj.product_id.id val = {'product_id': product_id} + new_lot_id = False if name: + lots = self.pool.get('stock.production.lot').search(cr, uid, ['&', ('name', '=', name), ('product_id', '=', product_id)], context=context) + if lots: + new_lot_id = lots[0] val.update({'name': name}) + if not obj.lot_id: - new_lot_id = self.pool.get('stock.production.lot').create(cr, uid, val, context=context) + if not new_lot_id: + new_lot_id = self.pool.get('stock.production.lot').create(cr, uid, val, context=context) self.write(cr, uid, id, {'lot_id': new_lot_id}, context=context) def _search_and_increment(self, cr, uid, picking_id, domain, filter_visible=False, visible_op_ids=False, increment=True, context=None): @@ -3869,11 +3880,15 @@ def _search_and_increment(self, cr, uid, picking_id, domain, filter_visible=Fals self.write(cr, uid, [operation_id], {'qty_done': qty}, context=context) else: #no existing operation found for the given domain and picking => create a new one + picking_obj = self.pool.get("stock.picking") + picking = picking_obj.browse(cr, uid, picking_id, context=context) values = { 'picking_id': picking_id, 'product_qty': 0, + 'location_id': picking.location_id.id, + 'location_dest_id': picking.location_dest_id.id, 'qty_done': 1, - } + } for key in domain: var_name, dummy, value = key uom_id = False diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml index e2673b1ab1f67..cb2c2ab31d230 100644 --- a/addons/stock/stock_view.xml +++ b/addons/stock/stock_view.xml @@ -355,7 +355,7 @@ <record model="ir.actions.act_window" id="location_open_quants"> <field name="context">{'search_default_productgroup': 1}</field> <field name="domain">[('location_id', 'child_of', active_ids)]</field> - <field name="name">Quants</field> + <field name="name">Current Stock</field> <field name="res_model">stock.quant</field> </record> @@ -1356,6 +1356,7 @@ <field name="model">stock.picking.type</field> <field name="arch" type="xml"> <tree string="Picking Types"> + <field name="sequence" widget="handle"/> <field name="name"/> <field name="warehouse_id"/> <field name="sequence_id"/> @@ -1794,7 +1795,7 @@ </record> <record model="ir.actions.act_window" id="product_open_quants"> <field name="context">{'search_default_internal_loc': 1, 'search_default_product_id': active_id, 'search_default_locationgroup':1}</field> - <field name="name">Quants</field> + <field name="name">Current Stock</field> <field name="res_model">stock.quant</field> </record> diff --git a/addons/stock/views/report_location_barcode.xml b/addons/stock/views/report_location_barcode.xml index d9065e0d20738..7e6466ed5c809 100644 --- a/addons/stock/views/report_location_barcode.xml +++ b/addons/stock/views/report_location_barcode.xml @@ -7,18 +7,15 @@ <t> <div class="page"> <div class="oe_structure"/> - <div class="row"> - <div class="col-xs-4"> - <img class="image" t-att-src="'data:image/png;base64,%s' % res_company.logo" style="border:auto;"/> - </div> - </div> <div class="row"> <div class="col-xs-6 mt6"> <table class="table table-condensed" style="border-bottom: 3px solid black !important;"><thead><th> </th></thead></table> <img t-if="not o.loc_barcode" t-att-src="'/report/barcode/?type=%s&value=%s&width=%s&height=%s' % ('Code128', o.name, 600, 100)" style="width:300px;height:50px"/> <img t-if="o.loc_barcode" t-att-src="'/report/barcode/?type=%s&value=%s&width=%s&height=%s' % ('Code128', o.loc_barcode, 600, 100)" style="width:300px;height:50px"/> - <p class="text-center" t-if="not o.loc_barcode" t-field="o.name"></p> - <p class="text-center" t-if="o.loc_barcode" t-field="o.loc_barcode"></p> + <p> + <span t-if="not o.loc_barcode" t-field="o.name"/> + <span t-if="o.loc_barcode" t-field="o.loc_barcode"/> + </p> </div> </div> </div> diff --git a/addons/stock/views/report_stockpicking.xml b/addons/stock/views/report_stockpicking.xml index 0b67ba94db6b0..7d2bb125de2a7 100644 --- a/addons/stock/views/report_stockpicking.xml +++ b/addons/stock/views/report_stockpicking.xml @@ -7,15 +7,15 @@ <t t-call="report.external_layout"> <div class="page"> <div class="row"><div class="col-xs-4 pull-right"> - <img t-att-src="'/report/barcode/Code128/%s' % o.name"/> + <img t-att-src="'/report/barcode/?type=%s&value=%s&width=%s&height=%s' % ('Code128', o.name, 600, 100)" style="width:300px;height:50px;"/> </div></div> - <div t-if="o.picking_type_id.code=='incoming'"> + <div t-if="o.picking_type_id.code=='incoming' and o.partner_id"> <span><strong>Supplier Address:</strong></span> </div> - <div t-if="o.picking_type_id.code=='internal'"> + <div t-if="o.picking_type_id.code=='internal' and o.partner_id"> <span><strong>Warehouse Address:</strong></span> </div> - <div t-if="o.picking_type_id.code=='outgoing'"> + <div t-if="o.picking_type_id.code=='outgoing' and o.partner_id"> <span><strong>Customer Address:</strong></span> </div> <div t-if="o.partner_id" name="partner_header"> @@ -73,7 +73,7 @@ <t t-if="o.picking_type_id.code != 'incoming'"><td><span t-field="move.location_id"/></td></t> <td> <span t-if="move.product_id and move.product_id.ean13"> - <img t-att-src="'/report/barcode/EAN13/%s' % move.product_id.ean13"/> + <img t-att-src="'/report/barcode/?type=%s&value=%s&width=%s&height=%s' % ('EAN13', move.product_id.ean13, 600, 100)" style="width:300px;height:50px"/> </span> </td> <t t-if="o.picking_type_id.code != 'outgoing'"><td><span t-field="move.location_dest_id"/></td></t> @@ -104,13 +104,13 @@ </t> <td> <span t-if="pack_operation.lot_id"> - <img t-att-src="'/report/barcode/Code128/%s' % pack_operation.lot_id.name"/> + <img t-att-src="'/report/barcode/?type=%s&value=%s&width=%s&height=%s' % ('Code128', pack_operation.lot_id.name, 600, 100)" style="width:300px;height:50px"/> </span> <span t-if="pack_operation.product_id and not pack_operation.lot_id and pack_operation.product_id.ean13"> - <img t-att-src="'/report/barcode/EAN13/%s' % pack_operation.product_id.ean13"/> + <img t-att-src="'/report/barcode/?type=%s&value=%s&width=%s&height=%s' % ('EAN13', pack_operation.product_id.ean13, 600, 100)" style="width:300px;height:50px"/> </span> <span t-if="pack_operation.package_id and not pack_operation.product_id"> - <img t-att-src="'/report/barcode/Code128/%s' % pack_operation.package_id.name"/> + <img t-att-src="'/report/barcode/?type=%s&value=%s&width=%s&height=%s' % ('Code128', pack_operation.package_id.name, 600, 100)" style="width:300px;height:50px"/> </span> </td> <t t-if="o.picking_type_id.code != 'outgoing'"><td><span t-field="pack_operation.location_dest_id"/> diff --git a/addons/stock/wizard/orderpoint_procurement.py b/addons/stock/wizard/orderpoint_procurement.py index 2cbc794cde310..f898dac430552 100644 --- a/addons/stock/wizard/orderpoint_procurement.py +++ b/addons/stock/wizard/orderpoint_procurement.py @@ -43,8 +43,10 @@ def _procure_calculation_orderpoint(self, cr, uid, ids, context=None): proc_obj = self.pool.get('procurement.order') #As this function is in a new thread, I need to open a new cursor, because the old one may be closed new_cr = self.pool.cursor() - for proc in self.browse(new_cr, uid, ids, context=context): - proc_obj._procure_orderpoint_confirm(new_cr, uid, use_new_cursor=new_cr.dbname, context=context) + user_obj = self.pool.get('res.users') + user = user_obj.browse(new_cr, uid, uid, context=context) + for comp in user.company_ids: + proc_obj._procure_orderpoint_confirm(new_cr, uid, use_new_cursor=new_cr.dbname, company_id = comp.id, context=context) #close the new cursor new_cr.close() return {} diff --git a/addons/stock_account/__openerp__.py b/addons/stock_account/__openerp__.py index a2dab1289f49c..5c67002f61fbc 100644 --- a/addons/stock_account/__openerp__.py +++ b/addons/stock_account/__openerp__.py @@ -53,6 +53,7 @@ 'wizard/stock_change_standard_price_view.xml', 'wizard/stock_invoice_onshipping_view.xml', 'wizard/stock_valuation_history_view.xml', + 'wizard/stock_return_picking_view.xml', 'product_data.xml', 'product_view.xml', 'stock_account_view.xml', diff --git a/addons/stock_account/product_view.xml b/addons/stock_account/product_view.xml index 97f51b04ac58e..960280154fd0d 100644 --- a/addons/stock_account/product_view.xml +++ b/addons/stock_account/product_view.xml @@ -30,11 +30,7 @@ <field name="property_stock_account_input" domain="[('type','<>','view'),('type','<>','consolidation')]"/> <field name="property_stock_account_output" domain="[('type','<>','view'),('type','<>','consolidation')]"/> </group> - </xpath> - <xpath expr="//field[@name='standard_price']" position='replace'> - <field name="standard_price" attrs="{'readonly':[('cost_method','=','average')]}"/> - <field name="cost_method" groups="stock_account.group_inventory_valuation"/> - </xpath> + </xpath> </field> </record> diff --git a/addons/stock_account/stock.py b/addons/stock_account/stock.py index db08ba39eb4c0..56d851cec7a50 100644 --- a/addons/stock_account/stock.py +++ b/addons/stock_account/stock.py @@ -27,11 +27,10 @@ class stock_location_path(osv.osv): 'invoice_state': fields.selection([ ("invoiced", "Invoiced"), ("2binvoiced", "To Be Invoiced"), - ("none", "Not Applicable")], "Invoice Status", - required=True,), + ("none", "Not Applicable")], "Invoice Status",), } _defaults = { - 'invoice_state': 'none', + 'invoice_state': '', } #---------------------------------------------------------- @@ -43,11 +42,10 @@ class procurement_rule(osv.osv): 'invoice_state': fields.selection([ ("invoiced", "Invoiced"), ("2binvoiced", "To Be Invoiced"), - ("none", "Not Applicable")], "Invoice Status", - required=True), + ("none", "Not Applicable")], "Invoice Status",), } _defaults = { - 'invoice_state': 'none', + 'invoice_state': '', } #---------------------------------------------------------- @@ -61,16 +59,16 @@ class procurement_order(osv.osv): 'invoice_state': fields.selection([("invoiced", "Invoiced"), ("2binvoiced", "To Be Invoiced"), ("none", "Not Applicable") - ], "Invoice Control", required=True), + ], "Invoice Control"), } def _run_move_create(self, cr, uid, procurement, context=None): res = super(procurement_order, self)._run_move_create(cr, uid, procurement, context=context) - res.update({'invoice_state': (procurement.rule_id.invoice_state in ('none', False) and procurement.invoice_state or procurement.rule_id.invoice_state) or 'none'}) + res.update({'invoice_state': procurement.rule_id.invoice_state or procurement.invoice_state or 'none'}) return res _defaults = { - 'invoice_state': 'none' + 'invoice_state': '' } @@ -92,7 +90,7 @@ class stock_move(osv.osv): } def _get_master_data(self, cr, uid, move, company, context=None): - ''' returns a tupple (browse_record(res.partner), ID(res.users), ID(res.currency)''' + ''' returns a tuple (browse_record(res.partner), ID(res.users), ID(res.currency)''' return move.picking_id.partner_id, uid, company.currency_id.id def _create_invoice_line_from_vals(self, cr, uid, move, invoice_line_vals, context=None): @@ -204,7 +202,7 @@ def action_invoice_create(self, cr, uid, ids, journal_id, group=False, type='out for picking in self.browse(cr, uid, ids, context=context): key = group and picking.id or True for move in picking.move_lines: - if move.procurement_id and (move.procurement_id.invoice_state == '2binvoiced') or move.invoice_state == '2binvoiced': + if move.invoice_state == '2binvoiced': if (move.state != 'cancel') and not move.scrapped: todo.setdefault(key, []) todo[key].append(move) @@ -259,12 +257,7 @@ def _invoice_create_line(self, cr, uid, moves, journal_id, inv_type='out_invoice invoice_line_vals['origin'] = origin move_obj._create_invoice_line_from_vals(cr, uid, move, invoice_line_vals, context=context) - move_obj.write(cr, uid, move.id, {'invoice_state': 'invoiced'}, context=context) - if move.procurement_id: - self.pool.get('procurement.order').write(cr, uid, [move.procurement_id.id], { - 'invoice_state': 'invoiced', - }, context=context) invoice_obj.button_compute(cr, uid, invoices.values(), context=context, set_total=(inv_type in ('in_invoice', 'in_refund'))) return invoices.values() diff --git a/addons/stock_account/stock_account_view.xml b/addons/stock_account/stock_account_view.xml index 3b3ab37b212f2..4f8c2122e5517 100644 --- a/addons/stock_account/stock_account_view.xml +++ b/addons/stock_account/stock_account_view.xml @@ -33,7 +33,6 @@ <field name="arch" type="xml"> <xpath expr="//button[@name='do_partial_open_barcode']" position="after"> <button name="%(action_stock_invoice_onshipping)d" string="Create Invoice" attrs="{'invisible': ['|',('state','<>','done'),('invoice_state','<>','2binvoiced')]}" type="action" class="oe_highlight" groups="base.group_user"/> - <button name="%(action_stock_invoice_onshipping)d" string="Refund Invoice" attrs="{'invisible': ['|',('state','<>','done'),('invoice_state','<>','invoiced')]}" type="action" class="oe_highlight" groups="base.group_user" context="{'inv_type': 'out_refund'}"/> </xpath> <xpath expr="//field[@name='move_type']" position="after"> <field name="invoice_state" groups="account.group_account_invoice"/> diff --git a/addons/stock_account/wizard/__init__.py b/addons/stock_account/wizard/__init__.py index 87f0841e3c564..09d08bb82d18c 100644 --- a/addons/stock_account/wizard/__init__.py +++ b/addons/stock_account/wizard/__init__.py @@ -22,3 +22,4 @@ import stock_change_standard_price import stock_invoice_onshipping import stock_valuation_history +import stock_return_picking diff --git a/addons/stock_account/wizard/stock_invoice_onshipping.py b/addons/stock_account/wizard/stock_invoice_onshipping.py index f600b28f5856a..1675275632af4 100644 --- a/addons/stock_account/wizard/stock_invoice_onshipping.py +++ b/addons/stock_account/wizard/stock_invoice_onshipping.py @@ -24,34 +24,48 @@ class stock_invoice_onshipping(osv.osv_memory): def _get_journal(self, cr, uid, context=None): - res = self._get_journal_id(cr, uid, context=context) - if res: - return res[0][0] - return False - - def _get_journal_id(self, cr, uid, context=None): + journal_obj = self.pool.get('account.journal') + journal_type = self._get_journal_type(cr, uid, context=context) + journals = journal_obj.search(cr, uid, [('type', '=', journal_type)]) + return journals and journals[0] or False + + def _get_journal_type(self, cr, uid, context=None): if context is None: context = {} - journal_obj = self.pool.get('account.journal') - value = journal_obj.search(cr, uid, [('type', 'in',('sale','sale_Refund'))]) + res_ids = context and context.get('active_ids', []) + pick_obj = self.pool.get('stock.picking') + pickings = pick_obj.browse(cr, uid, res_ids, context=context) vals = [] - for jr_type in journal_obj.browse(cr, uid, value, context=context): - t1 = jr_type.id,jr_type.name - if t1 not in vals: - vals.append(t1) - return vals + pick = pickings and pickings[0] + if not pick or not pick.move_lines: + return 'sale' + src_usage = pick.move_lines[0].location_id.usage + dest_usage = pick.move_lines[0].location_dest_id.usage + type = pick.picking_type_id.code + if type == 'outgoing' and dest_usage == 'supplier': + journal_type = 'purchase_refund' + elif type == 'outgoing' and dest_usage == 'customer': + journal_type = 'sale' + elif type == 'incoming' and src_usage == 'supplier': + journal_type = 'purchase' + elif type == 'incoming' and src_usage == 'customer': + journal_type = 'sale_refund' + else: + journal_type = 'sale' + return journal_type _name = "stock.invoice.onshipping" _description = "Stock Invoice Onshipping" _columns = { - 'journal_id': fields.selection(_get_journal_id, 'Destination Journal',required=True), + 'journal_id': fields.many2one('account.journal', 'Destination Journal', required=True), + 'journal_type': fields.selection([('purchase_refund', 'Refund Purchase'), ('purchase', 'Create Supplier Invoice'), + ('sale_refund', 'Refund Sale'), ('sale', 'Create Customer Invoice')], 'Journal Type', readonly=True), 'group': fields.boolean("Group by partner"), - 'inv_type': fields.selection([('out_invoice','Create Invoice'),('out_refund','Refund Invoice')], "Invoice Type"), 'invoice_date': fields.date('Invoice Date'), } _defaults = { + 'journal_type': _get_journal_type, 'journal_id' : _get_journal, - 'inv_type': lambda self,cr,uid,ctx: ctx.get('inv_type', 'out_invoice') } def view_init(self, cr, uid, fields_list, context=None): @@ -71,24 +85,30 @@ def view_init(self, cr, uid, fields_list, context=None): def open_invoice(self, cr, uid, ids, context=None): if context is None: context = {} + invoice_ids = self.create_invoice(cr, uid, ids, context=context) if not invoice_ids: raise osv.except_osv(_('Error!'), _('No invoice created!')) - onshipdata_obj = self.read(cr, uid, ids, ['journal_id', 'group', 'invoice_date', 'inv_type']) - inv_type = onshipdata_obj[0]['inv_type'] + data = self.browse(cr, uid, ids[0], context=context) action_model = False action = {} - + + journal2type = {'sale':'out_invoice', 'purchase':'in_invoice' , 'sale_refund':'out_refund', 'purchase_refund':'in_refund'} + inv_type = journal2type.get(data.journal_type) or 'out_invoice' data_pool = self.pool.get('ir.model.data') - if inv_type == "out_refund": - action_model,action_id = data_pool.get_object_reference(cr, uid, 'account', "action_invoice_tree3") - elif inv_type == "out_invoice": - action_model,action_id = data_pool.get_object_reference(cr, uid, 'account', "action_invoice_tree1") + if inv_type == "out_invoice": + action_id = data_pool.xmlid_to_res_id(cr, uid, 'account.action_invoice_tree1') + elif inv_type == "in_invoice": + action_id = data_pool.xmlid_to_res_id(cr, uid, 'account.action_invoice_tree2') + elif inv_type == "out_refund": + action_id = data_pool.xmlid_to_res_id(cr, uid, 'account.action_invoice_tree3') + elif inv_type == "in_refund": + action_id = data_pool.xmlid_to_res_id(cr, uid, 'account.action_invoice_tree4') - if action_model: - action_pool = self.pool[action_model] + if action_id: + action_pool = self.pool['ir.actions.act_window'] action = action_pool.read(cr, uid, action_id, context=context) action['domain'] = "[('id','in', ["+','.join(map(str,invoice_ids))+"])]" return action @@ -97,18 +117,17 @@ def open_invoice(self, cr, uid, ids, context=None): def create_invoice(self, cr, uid, ids, context=None): context = context or {} picking_pool = self.pool.get('stock.picking') - onshipdata_obj = self.read(cr, uid, ids, ['journal_id', 'group', 'invoice_date', 'inv_type']) - - context['date_inv'] = onshipdata_obj[0]['invoice_date'] - inv_type = onshipdata_obj[0]['inv_type'] + data = self.browse(cr, uid, ids[0], context=context) + journal2type = {'sale':'out_invoice', 'purchase':'in_invoice', 'sale_refund':'out_refund', 'purchase_refund':'in_refund'} + context['date_inv'] = data.invoice_date + acc_journal = self.pool.get("account.journal") + inv_type = journal2type.get(data.journal_type) or 'out_invoice' context['inv_type'] = inv_type active_ids = context.get('active_ids', []) - if isinstance(onshipdata_obj[0]['journal_id'], tuple): - onshipdata_obj[0]['journal_id'] = onshipdata_obj[0]['journal_id'][0] res = picking_pool.action_invoice_create(cr, uid, active_ids, - journal_id = onshipdata_obj[0]['journal_id'], - group = onshipdata_obj[0]['group'], + journal_id = data.journal_id.id, + group = data.group, type = inv_type, context=context) return res diff --git a/addons/stock_account/wizard/stock_invoice_onshipping_view.xml b/addons/stock_account/wizard/stock_invoice_onshipping_view.xml index e632fc4057bef..54cced6de4f7d 100644 --- a/addons/stock_account/wizard/stock_invoice_onshipping_view.xml +++ b/addons/stock_account/wizard/stock_invoice_onshipping_view.xml @@ -7,10 +7,10 @@ <field name="arch" type="xml"> <form string="Create invoice"> <h1> - <field name="inv_type" readonly="1"/> + <field name="journal_type" readonly="1"/> </h1> <group> - <field name="journal_id"/> + <field name="journal_id" domain="[('type','=',journal_type)]"/> <field name="group"/> <field name="invoice_date" /> </group> @@ -23,17 +23,6 @@ </field> </record> - - <act_window name="Create Invoice" - res_model="stock.invoice.onshipping" - src_model="stock.picking" - key2="client_action_multi" - multi="True" - view_mode="form" - view_type="form" - target="new" - id="action_stock_invoice_onshipping"/> - <act_window name="Create Draft Invoices" res_model="stock.invoice.onshipping" src_model="stock.picking" diff --git a/addons/stock_account/wizard/stock_return_picking.py b/addons/stock_account/wizard/stock_return_picking.py new file mode 100644 index 0000000000000..4ceaf35363edb --- /dev/null +++ b/addons/stock_account/wizard/stock_return_picking.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +############################################################################## + +from openerp.osv import osv, fields +from openerp.tools.translate import _ +import openerp.addons.decimal_precision as dp + + +class stock_return_picking(osv.osv_memory): + _inherit = 'stock.return.picking' + _columns = { + 'invoice_state': fields.selection([('2binvoiced', 'To be refunded/invoiced'), ('none', 'No invoicing')], 'Invoicing',required=True), + } + + def default_get(self, cr, uid, fields, context=None): + res = super(stock_return_picking, self).default_get(cr, uid, fields, context=context) + record_id = context and context.get('active_id', False) or False + pick_obj = self.pool.get('stock.picking') + pick = pick_obj.browse(cr, uid, record_id, context=context) + if pick: + if 'invoice_state' in fields: + if pick.invoice_state=='invoiced': + res.update({'invoice_state': '2binvoiced'}) + else: + res.update({'invoice_state': 'none'}) + return res + + + + def _create_returns(self, cr, uid, ids, context=None): + if context is None: + context = {} + data = self.browse(cr, uid, ids[0], context=context) + new_picking, picking_type_id = super(stock_return_picking, self)._create_returns(cr, uid, ids, context=context) + if data.invoice_state == '2binvoiced': + pick_obj = self.pool.get("stock.picking") + move_obj = self.pool.get("stock.move") + move_ids = [x.id for x in pick_obj.browse(cr, uid, new_picking, context=context).move_lines] + move_obj.write(cr, uid, move_ids, {'invoice_state': '2binvoiced'}) + return new_picking, picking_type_id + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/stock_account/wizard/stock_return_picking_view.xml b/addons/stock_account/wizard/stock_return_picking_view.xml new file mode 100644 index 0000000000000..8365c424b95f6 --- /dev/null +++ b/addons/stock_account/wizard/stock_return_picking_view.xml @@ -0,0 +1,14 @@ +<openerp> + <data> + <record id="view_stock_return_picking_form_inherit" model="ir.ui.view"> + <field name="name">Return lines</field> + <field name="model">stock.return.picking</field> + <field name="inherit_id" ref="stock.view_stock_return_picking_form"/> + <field name="arch" type="xml"> + <field name="product_return_moves" position="after"> + <field name="invoice_state"/> + </field> + </field> + </record> + </data> +</openerp> diff --git a/addons/stock_account/wizard/stock_valuation_history.py b/addons/stock_account/wizard/stock_valuation_history.py index 42b40b5643229..540a308c536a8 100644 --- a/addons/stock_account/wizard/stock_valuation_history.py +++ b/addons/stock_account/wizard/stock_valuation_history.py @@ -55,12 +55,13 @@ def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, con product_tmpl_obj = self.pool.get("product.template") lines_rec = self.browse(cr, uid, lines, context=context) for line_rec in lines_rec: - if not line_rec.product_id.id in prod_dict: - if line_rec.product_id.cost_method == 'real': - prod_dict[line_rec.product_id.id] = line_rec.price_unit_on_quant - else: + if line_rec.product_id.cost_method == 'real': + price = line_rec.price_unit_on_quant + else: + if not line_rec.product_id.id in prod_dict: prod_dict[line_rec.product_id.id] = product_tmpl_obj.get_history_price(cr, uid, line_rec.product_id.product_tmpl_id.id, line_rec.company_id.id, date=date, context=context) - inv_value += prod_dict[line_rec.product_id.id] * line_rec.quantity + price = prod_dict[line_rec.product_id.id] + inv_value += price * line_rec.quantity line['inventory_value'] = inv_value return res diff --git a/addons/stock_dropshipping/stock_dropshipping.xml b/addons/stock_dropshipping/stock_dropshipping.xml index ede1f00afede7..de1de472d208b 100644 --- a/addons/stock_dropshipping/stock_dropshipping.xml +++ b/addons/stock_dropshipping/stock_dropshipping.xml @@ -14,7 +14,7 @@ <record id="picking_type_dropship" model="stock.picking.type"> <field name="name">Dropship</field> <field name="sequence_id" ref="seq_picking_type_dropship"/> - <field name="code">incoming</field> + <field name="code">outgoing</field> <field name="default_location_src_id" ref="stock.stock_location_suppliers"/> <field name="default_location_dest_id" ref="stock.stock_location_customers"/> </record> @@ -37,7 +37,6 @@ <field name="procure_method">make_to_stock</field> <field name="route_id" ref="route_drop_shipping"/> <field name="picking_type_id" ref="picking_type_dropship"/> - </record> - + </record> </data> </openerp>