I am checking Procurement orders. There are 3 orders generated for Oranges, Sugar and Water.
-
!python {model: procurement.order}: |
- from tools.translate import _
proc_ids = self.search(cr, uid, [('product_id','in',[ref('product_product_orange0'),ref('product_product_sugar0'),ref('product_product_water0')])])
- assert proc_ids, _('No Procurements!')
+ assert proc_ids, 'No Procurements!'
-
The scheduler runs.
-
stock moves for Oranges, Sugar and Water made correctly.
-
!python {model: stock.picking}: |
- from tools.translate import _
pick_ids = self.search(cr, uid, [('type','=','internal')])
- assert pick_ids, _('No Internal Pickings!')
+ assert pick_ids, 'No Internal Pickings!'
-
According to minimum stock rules. I have 2 purchase orders for
Sugar with 6 Kg from Axelor and Orange 60 Kg from ASUStek.
I confirm the purchase order of Sugar and Orange.
-
!python {model: purchase.order}: |
- from tools.translate import _
import netsvc
purch_ids = self.search(cr, uid, [('state','=','draft')])
- assert purch_ids, _('No Purchase Orders were made!')
+ assert purch_ids, 'No Purchase Orders were made!'
wf_service = netsvc.LocalService("workflow")
for p_id in purch_ids:
wf_service.trg_validate(uid, 'purchase.order', p_id, 'purchase_confirm', cr)
-
- I see two incoming pickings for Orange and Sugar.
+ I see two incoming pickings for Orange and Sugar, and receive them.
-
!python {model: stock.picking}: |
- from tools.translate import _
pick_ids = self.search(cr, uid, [('type','=','in')])
- assert pick_ids, _('No Incoming Shipments found!')
--
- I receive both the products. My incoming pickings are done.
--
- I create record for the incoming picking wizard.
--
- !record {model: stock.partial.picking, id: stock_partial_picking0}:
- date: !eval datetime.today().strftime("%Y-%m-%d %H:%M:%S")
--
- I make my pickings done.
--
- !python {model: stock.partial.picking}: |
- pick_obj = self.pool.get('stock.picking')
- picking_ids = pick_obj.search(cr, uid, [('type','=','in'),('state','=','assigned')])
- partial = self.browse(cr, uid, ref('stock_partial_picking0'), context)
- partial_datas = {
- 'delivery_date': partial.date
- }
- for pick in pick_obj.browse(cr, uid, picking_ids):
- for m in pick.move_lines:
- partial_datas['move%s'%(m.id)] = {
- 'product_id': m.product_id.id,
- 'product_qty': m.product_qty,
- 'product_uom': m.product_uom.id
- }
- if (pick.type == 'in') and (m.product_id.cost_method == 'average'):
- partial_datas['move%s'%(m.id)].update({
- 'product_price': m.product_price,
- 'product_currency': m.product_currency
- })
- pick_obj.do_partial(cr, uid, picking_ids, partial_datas, context=context)
+ assert pick_ids, 'No Incoming Shipments found!'
+ stock_partial_picking = self.pool.get('stock.partial.picking')
+ for pick_id in pick_ids:
+ partial_id = stock_partial_picking.create(cr, uid, {},
+ context={'active_model': 'stock.picking',
+ 'active_ids': [pick_id]})
+ stock_partial_picking.do_partial(cr, uid, [partial_id])
-
Again the scheduler runs.
-
I check my internal picking of "Orange Juice" is done.
-
!python {model: stock.picking}: |
- from tools.translate import _
pick_ids = self.search(cr, uid, [('type','=','internal'),('state','=','done')])
- assert pick_ids, _('Internal Picking is not done yet!')
+ assert pick_ids, 'Internal Picking is not done yet!'
-
I check my manufacturing order for "Orange Juice" is ready or not.
-
!python {model: mrp.production}: |
- from tools.translate import _
- pick_ids = self.search(cr, uid, [('state','=','ready'),('id','=',ref('mrp_production_mo0'))])
- assert pick_ids, _('Manufacturing order is not ready!')
+ prod_ids = self.search(cr, uid, [('state','=','ready'),('id','=',ref('mrp_production_mo0'))])
+ assert prod_ids, 'Manufacturing order is not ready!'
-
I start the production order.
-
!workflow {model: mrp.production, action: button_produce, ref: mrp_production_mo0}
-
-
I Check incoming shipments for cloth. And receive products.
-
!python {model: stock.picking}: |
- from tools.translate import _
pick_ids = self.search(cr, uid, [('address_id.name','=','Wong'),('state','=','assigned')])
- assert pick_ids, _('No Incoming Shipments found!')
--
- I create record for partial picking.
--
- !record {model: stock.partial.picking, id: stock_partial_picking0}:
- date: !eval datetime.today().strftime("%Y-%m-%d %H:%M:%S")
-
--
- I make my picking done.
--
- !python {model: stock.partial.picking}: |
- pick_obj = self.pool.get('stock.picking')
- picking_ids = pick_obj.search(cr, uid, [('address_id.name','=','Wong'),('state','=','assigned')])
- partial = self.browse(cr, uid, ref('stock_partial_picking0'), context)
- partial_datas = {
- 'delivery_date' : partial.date
- }
- for pick in pick_obj.browse(cr, uid, picking_ids):
- for m in pick.move_lines:
- partial_datas['move%s'%(m.id)] = {
- 'product_id' : m.product_id.id,
- 'product_qty' : m.product_qty,
- 'product_uom' : m.product_uom.id
- }
- if (pick.type == 'in') and (m.product_id.cost_method == 'average'):
- partial_datas['move%s'%(m.id)].update({
- 'product_price' : m.product_price,
- 'product_currency': m.product_currency
- })
- pick_obj.do_partial(cr, uid, picking_ids, partial_datas, context=context)
+ assert pick_ids, 'No Incoming Shipments found!'
+ stock_partial_picking = self.pool.get('stock.partial.picking')
+ for pick_id in pick_ids:
+ partial_id = stock_partial_picking.create(cr, uid, {},
+ context={'active_model': 'stock.picking',
+ 'active_ids': [pick_id]})
+ stock_partial_picking.do_partial(cr, uid, [partial_id])
-
I Check incoming shipments for buttons and receive products.
-
!python {model: stock.picking}: |
- from tools.translate import _
pick_ids = self.search(cr, uid, [('address_id.name','=','Tang'),('state','=','assigned')])
- assert pick_ids, _('No Incoming Shipments found!')
--
- I create record for partial picking.
--
- !record {model: stock.partial.picking, id: stock_partial_picking0}:
- date: !eval datetime.today().strftime("%Y-%m-%d %H:%M:%S")
-
--
- I make my picking done.
--
- !python {model: stock.partial.picking}: |
- pick_obj = self.pool.get('stock.picking')
- picking_ids = pick_obj.search(cr, uid, [('address_id.name','=','Tang'),('state','=','assigned')])
- partial = self.browse(cr, uid, ref('stock_partial_picking0'), context)
- partial_datas = {
- 'delivery_date': partial.date
- }
- for pick in pick_obj.browse(cr, uid, picking_ids):
- for m in pick.move_lines:
- partial_datas['move%s'%(m.id)] = {
- 'product_id': m.product_id.id,
- 'product_qty': m.product_qty,
- 'product_uom': m.product_uom.id
- }
- if (pick.type == 'in') and (m.product_id.cost_method == 'average'):
- partial_datas['move%s'%(m.id)].update({
- 'product_price': m.product_price,
- 'product_currency': m.product_currency
- })
- pick_obj.do_partial(cr, uid, picking_ids, partial_datas, context=context)
+ assert pick_ids, 'No Incoming Shipments found!'
+ stock_partial_picking = self.pool.get('stock.partial.picking')
+ for pick_id in pick_ids:
+ partial_id = stock_partial_picking.create(cr, uid, {},
+ context={'active_model': 'stock.picking',
+ 'active_ids': [pick_id]})
+ stock_partial_picking.do_partial(cr, uid, [partial_id])
-
Run scheduler again.
-
I produce 2 products with 5.00 quantities each.
-
!python {model: mrp.product.produce}: |
- from tools.translate import _
prod_obj = self.pool.get('mrp.production')
prod_ids = prod_obj.search(cr, uid, [('product_id.name','=','Shirt')])
self.do_produce(cr, uid, [ref('mrp_product_produce0')], context={'active_ids': prod_ids})
And finally production order is done.
-
!python {model: mrp.product.produce}: |
- from tools.translate import _
prod_obj = self.pool.get('mrp.production')
prod_ids = prod_obj.search(cr, uid, [('product_id.name','=','Shirt')])
- self.do_produce(cr, uid, [1], context={'active_ids': prod_ids})
+ self.do_produce(cr, uid, [ref('mrp_product_produce0')], context={'active_ids': prod_ids})
purchase_obj.write(cursor, user, [picking.purchase_id.id], {'invoice_id': invoice_id,})
return super(stock_picking, self)._invoice_hook(cursor, user, picking, invoice_id)
-stock_picking()
-
class stock_partial_picking(osv.osv_memory):
_inherit = 'stock.partial.picking'
- def default_get(self, cr, uid, fields, context=None):
- """ To get default values for the object.
- @param self: The object pointer.
- @param cr: A database cursor
- @param uid: ID of the user currently logged in
- @param fields: List of fields for which we want default values
- @param context: A standard dictionary
- @return: A dictionary which of fields with values.
- """
- if context is None:
- context = {}
- pick_obj = self.pool.get('stock.picking')
- res = super(stock_partial_picking, self).default_get(cr, uid, fields, context=context)
- for pick in pick_obj.browse(cr, uid, context.get('active_ids', []), context=context):
- 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)
- list_index = 0
- for item in res['product_moves_in']:
- if item['move_id'] == m.id:
- res['product_moves_in'][list_index]['cost'] = m.purchase_line_id.price_unit
- res['product_moves_in'][list_index]['currency'] = m.picking_id.purchase_id.pricelist_id.currency_id.id
- list_index += 1
- return res
-stock_partial_picking()
-
-class stock_partial_move(osv.osv_memory):
- _inherit = "stock.partial.move"
- def default_get(self, cr, uid, fields, context=None):
- """ To get default values for the object.
- @param self: The object pointer.
- @param cr: A database cursor
- @param uid: ID of the user currently logged in
- @param fields: List of fields for which we want default values
- @param context: A standard dictionary
- @return: A dictionary which of fields with values.
- """
- if context is None:
- context = {}
- res = super(stock_partial_move, self).default_get(cr, uid, fields, context=context)
- move_obj = self.pool.get('stock.move')
- for m in move_obj.browse(cr, uid, context.get('active_ids', []), context=context):
- if m.picking_id.type == 'in' and m.product_id.cost_method == 'average' \
- and m.purchase_line_id and m.picking_id.purchase_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)
- list_index = 0
- for item in res['product_moves_in']:
- if item['move_id'] == m.id:
- res['product_moves_in'][list_index]['cost'] = m.purchase_line_id.price_unit
- res['product_moves_in'][list_index]['currency'] = m.picking_id.purchase_id.pricelist_id.currency_id.id
- list_index += 1
- return res
-stock_partial_move()
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+ # Overridden to inject the purchase price as true 'cost price' when processing
+ # incoming pickings.
+ def _product_cost_for_average_update(self, cr, uid, move):
+ if move.picking_id.purchase_id:
+ return {'cost': move.purchase_line_id.price_unit,
+ 'currency': move.picking_id.purchase_id.pricelist_id.currency_id.id}
+ return super(stock_partial_picking, self)._product_cost_for_average_update(cr, uid, move)
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
-
!workflow {model: sale.order, action: order_confirm, ref: sale_order_so9}
-
- I verify that the picking has been generated for the sale order
+ I verify that the picking has been generated for the sale order and I process it
-
!python {model: sale.order}: |
so = self.browse(cr, uid, ref("sale_order_so9"))
assert so.picking_ids,"Picking has not been generated for sale_order_so9"
--
- Then I confirm the picking
--
- !record {model: stock.partial.picking, id: stock_partial_picking_0}:
- date: !eval time.strftime('%Y-%m-%d %H:%M:%S')
--
- Then I done the picking
--
- !python {model: stock.picking }: |
- import time
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so9"))
- picking_id = self.search(cr, uid, [('origin','=',so.name),('type','=','out')])
- if picking_id:
- pick=self.browse(cr,uid,picking_id[0])
- pick.force_assign(cr, uid)
- partial_datas = {
- 'partner_id':pick.address_id.partner_id.id,
- 'address_id': pick.address_id.id,
- 'delivery_date' : time.strftime('%Y-%m-%d'),
- }
- move = pick.move_lines[0]
- partial_datas['move%s'%(move.id)]= {
- 'product_id': move.product_id.id,
- 'product_qty': '100',
- 'product_uom': move.product_uom.id,
- }
- self.do_partial(cr, uid, [pick.id],partial_datas)
+ picking, = so.picking_ids
+ stock_partial_picking = self.pool.get('stock.partial.picking')
+ partial_id = stock_partial_picking.create(cr, uid, {},
+ context={'active_model': 'stock.picking',
+ 'active_ids': [picking.id]})
+ stock_partial_picking.do_partial(cr, uid, [partial_id])
-
I click on Create Invoice button to create the invoice.
-
-
!workflow {model: sale.order, action: order_confirm, ref: sale_order_so6}
-
- I verify that the picking has been generated for the sale order
+ I verify that the picking has been generated for the sale order and I process it
-
!python {model: sale.order}: |
so = self.browse(cr, uid, ref("sale_order_so6"))
assert so.picking_ids,"Picking has not been generated for sale_order_so6"
--
- Then I click on the "Product Sent" button of Outgoing Shipments
--
- !record {model: stock.partial.picking, id: stock_partial_picking_0}:
- date: !eval time.strftime('%Y-%m-%d %H:%M:%S')
--
- I change the quantity on the picking to 199, and confirm partially 100 PCE.
--
- !python {model: stock.picking }: |
- import time
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so6"))
- picking_id = self.search(cr, uid, [('origin','=',so.name),('type','=','out')])
- if picking_id:
- pick=self.browse(cr,uid,picking_id[0])
- self.pool.get('stock.move').write(cr, uid, [pick.move_lines[0].id], {'product_qty': 199, 'product_uos_qty': 199})
- pick=self.browse(cr,uid,picking_id[0])
- pick.force_assign(cr, uid)
- partial_datas = {
- 'partner_id':pick.address_id.partner_id.id,
- 'address_id': pick.address_id.id,
- 'delivery_date' : time.strftime('%Y-%m-%d'),
- }
- move = pick.move_lines[0]
- partial_datas['move%s'%(move.id)]= {
- 'product_id': move.product_id.id,
- 'product_qty': '100',
- 'product_uom': move.product_uom.id,
- }
- self.do_partial(cr, uid, [pick.id],partial_datas)
+ picking, = so.picking_ids
+ stock_partial_picking = self.pool.get('stock.partial.picking')
+ partial_id = stock_partial_picking.create(cr, uid, {},
+ context={'active_model': 'stock.picking',
+ 'active_ids': [picking.id]})
+ # I change the qty to 100 for a partial delivery
+ partial = stock_partial_picking.browse(cr,uid,partial_id)
+ line_id = partial.move_ids[0].id
+ partial.write({'move_ids': [(1,line_id,{'quantity':100})]})
+ partial.do_partial()
-
Then I click on 'Create Invoices' button
-
import time
sale_obj = self.pool.get('sale.order')
sale_id = sale_obj.browse(cr, uid, ref("sale_order_so6"))
- ids = [x.id for x in sale_id.picking_ids]
+ ids = [x.id for x in sale_id.picking_ids if x.state == 'done']
wiz_id = self.create(cr, uid, {'invoice_date': time.strftime('%Y-%m-%d'), 'journal_id': ref('account.sales_journal')},
{'active_ids': ids, 'active_model': 'stock.picking'})
self.create_invoice(cr, uid, [wiz_id], {"active_ids": ids, "active_id": ids[0]})
inv_brw = self.browse(cr,uid,inv_id)[0]
for inv_lines in inv_brw.invoice_line:
qty1=inv_lines.quantity
- assert (qty1 == qty), "Quantities are not the same"
+ assert (qty1 == qty), "Quantities are not the same: invoiced: %s, shipped: %s" % (qty1,qty)
-
I open the Invoice for the SO.
-
I verify that a procurement state is "running"
-
!python {model: procurement.order}: |
- from tools.translate import _
- modules = self.pool.get('ir.module.module')
- mod_pur = modules.search(cr, uid, [('name','=','purchase')])
- mod_brw = modules.browse(cr,uid,mod_pur)[0]
- if (mod_brw.state == 'installed'):
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so0"))
- proc_ids = self.search(cr, uid, [('origin','=',so.name),('state','=','running')])
- assert(proc_ids),"Procurement is not in the running state!"
+ sale_order_obj = self.pool.get('sale.order')
+ so = sale_order_obj.browse(cr, uid, ref("sale_order_so0"))
+ proc_ids = self.search(cr, uid, [('origin','=',so.name),('state','=','running')])
+ assert(proc_ids),"Procurement is not in the running state!"
-
I verify that a purchase order has been generated
-
for pur in pur_ids:
wf_service.trg_validate(uid, 'purchase.order',pur,'purchase_approve', cr)
-
- I verify that a picking related to purchase order has been generated.
+ I verify that a picking related to purchase order has been generated and I process it
-
!python {model: sale.order}: |
modules = self.pool.get('ir.module.module')
pur_id = pur_obj.search(cr, uid, [('origin','=',so.name)])
po = pur_obj.browse(cr, uid, pur_id)[0]
assert(po.picking_ids),"Picking for purchase order has not been generated"
--
- Then I click on the "Products Received" button of Incoming Shipments
--
- !record {model: stock.partial.picking, id: stock_partial_picking_0}:
- date: !eval time.strftime('%Y-%m-%d %H:%M:%S')
--
- I click on the "Validate" button
--
- !python {model: stock.picking}: |
- modules = self.pool.get('ir.module.module')
- sale_order_obj = self.pool.get('sale.order')
- pur_obj = self.pool.get('purchase.order')
- mod_pur = modules.search(cr, uid, [('name','=','purchase')])
- mod_brw = modules.browse(cr,uid,mod_pur)[0]
- if (mod_brw.state == 'installed'):
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so0"))
- pur_id = pur_obj.search(cr, uid, [('origin','=',so.name)])
- po = pur_obj.browse(cr, uid, pur_id)[0]
- pick_ser_id = self.search(cr, uid, [('purchase_id', '=', po.id )])
- import netsvc
- wf_service = netsvc.LocalService("workflow")
- for pick in pick_ser_id:
- wf_service.trg_validate(uid, 'stock.picking',pick,'button_done', cr)
+ picking, = po.picking_ids
+ stock_partial_picking = self.pool.get('stock.partial.picking')
+ partial_id = stock_partial_picking.create(cr, uid, {},
+ context={'active_model': 'stock.picking',
+ 'active_ids': [picking.id]})
+ stock_partial_picking.do_partial(cr, uid, [partial_id])
-
I verify that picking for purchase order has been done.
-
ids = picking_obj.search(cr, uid, [('purchase_id', '=', po.id ),('state', '=', 'done')])
assert(ids),"Picking is not in the done state!"
-
- Then I done the picking
+ Then I process the picking
-
!python {model: stock.picking }: |
import time
if picking_id:
pick=self.browse(cr,uid,picking_id[0])
pick.force_assign(cr, uid)
- partial_datas = {
- 'partner_id':pick.address_id.partner_id.id,
- 'address_id': pick.address_id.id,
- 'delivery_date' : time.strftime('%Y-%m-%d'),
- }
- move = pick.move_lines[0]
- partial_datas['move%s'%(move.id)]= {
- 'product_id': move.product_id.id,
- 'product_qty': move.product_qty,
- 'product_uom': move.product_uom.id,
- }
- self.do_partial(cr, uid, [pick.id],partial_datas)
+ stock_partial_picking = self.pool.get('stock.partial.picking')
+ partial_id = stock_partial_picking.create(cr, uid, {},
+ context={'active_model': 'stock.picking',
+ 'active_ids': [pick.id]})
+ stock_partial_picking.do_partial(cr, uid, [partial_id])
-
I verify that picking for sale order is in done state.
-
pick = self.browse(cr,uid,picking_id[0])
assert (pick.state) =='done', "Picking for SO is not in done state."
-
- Then I done the delivery order
--
- !python {model: stock.picking }: |
- import time
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so0"))
- picking_id = self.search(cr, uid, [('origin','=',so.name)])
- if picking_id:
- pick=self.browse(cr,uid,picking_id[0])
- pick.force_assign(cr, uid)
- partial_datas = {
- 'partner_id':pick.address_id.partner_id.id,
- 'address_id': pick.address_id.id,
- 'delivery_date' : time.strftime('%Y-%m-%d'),
- }
- move = pick.move_lines[0]
- partial_datas['move%s'%(move.id)]= {
- 'product_id': move.product_id.id,
- 'product_qty': move.product_qty,
- 'product_uom': move.product_uom.id,
- }
- self.do_partial(cr, uid, [pick.id],partial_datas)
--
- I verify that delivery state is done
--
- !python {model: stock.picking }: |
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so0"))
- picking_id = self.search(cr, uid, [('origin','=',so.name)])
- pick = self.browse(cr,uid,picking_id[0])
- assert (pick.state) =='done', "Picking for SO is not in done state."
--
I verify that a "Picked" has been set to true
-
!python {model: sale.order}: |
if picking_id:
pick=self.browse(cr,uid,picking_id[0])
pick.force_assign(cr, uid)
- partial_datas = {
- 'partner_id':pick.address_id.partner_id.id,
- 'address_id': pick.address_id.id,
- 'delivery_date' : time.strftime('%Y-%m-%d'),
- }
- move = pick.move_lines[0]
- partial_datas['move%s'%(move.id)]= {
- 'product_id': move.product_id.id,
- 'product_qty': move.product_qty,
- 'product_uom': move.product_uom.id,
- }
- self.do_partial(cr, uid, [pick.id],partial_datas)
+ stock_partial_picking = self.pool.get('stock.partial.picking')
+ partial_id = stock_partial_picking.create(cr, uid, {},
+ context={'active_model': 'stock.picking',
+ 'active_ids': [pick.id]})
+ stock_partial_picking.do_partial(cr, uid, [partial_id])
-
Then I click on 'Create Invoices' button
-
for pur in pur_ids:
wf_service.trg_validate(uid, 'purchase.order',pur,'purchase_approve', cr)
-
- I verify that a picking related to purchase order has been generated.
+ I verify that a picking related to purchase order has been generated and I process it
-
!python {model: sale.order}: |
modules = self.pool.get('ir.module.module')
pur_id = pur_obj.search(cr, uid, [('origin','=',so.name)])
po = pur_obj.browse(cr, uid, pur_id)[0]
assert(po.picking_ids),"Picking for purchase order has not been generated"
--
- Then I click on the "Products Received" button of Incoming Shipments
--
- !record {model: stock.partial.picking, id: stock_partial_picking_0}:
- date: !eval time.strftime('%Y-%m-%d %H:%M:%S')
--
- I click on the "Validate" button
--
- !python {model: stock.picking}: |
- modules = self.pool.get('ir.module.module')
- mod_pur = modules.search(cr, uid, [('name','=','purchase')])
- mod_brw = modules.browse(cr,uid,mod_pur)[0]
- if (mod_brw.state == 'installed'):
- sale_order_obj = self.pool.get('sale.order')
- pur_obj = self.pool.get('purchase.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so7"))
- pur_id = pur_obj.search(cr, uid, [('origin','=',so.name)])
- po = pur_obj.browse(cr, uid, pur_id)[0]
- pick_ser_id = self.search(cr, uid, [('purchase_id', '=', po.id )])
- import netsvc
- wf_service = netsvc.LocalService("workflow")
- for pick in pick_ser_id:
- wf_service.trg_validate(uid, 'stock.picking',pick,'button_done', cr)
+ picking, = po.picking_ids
+ stock_partial_picking = self.pool.get('stock.partial.picking')
+ partial_id = stock_partial_picking.create(cr, uid, {},
+ context={'active_model': 'stock.picking',
+ 'active_ids': [picking.id]})
+ stock_partial_picking.do_partial(cr, uid, [partial_id])
-
I verify that picking for purchase order has been done.
-
ids = picking_obj.search(cr, uid, [('purchase_id', '=', po.id ),('state', '=', 'done')])
assert ids, _('Picking is not in the done state!')
-
- I verify that delivery order has been generated for sale order
+ I verify that delivery order has been generated for sale order, and process it
-
!python {model: stock.picking }: |
sale_order_obj = self.pool.get('sale.order')
so = sale_order_obj.browse(cr, uid, ref("sale_order_so7"))
picking_id = self.search(cr, uid, [('origin','=',so.name)])
assert (picking_id),"Delivery order has not been generated"
--
- I verify that delivery has been done
--
- !python {model: stock.picking }: |
- import time
- sale_order_obj = self.pool.get('sale.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so7"))
- picking_id = self.search(cr, uid, [('origin','=',so.name)])
- if picking_id:
- pick=self.browse(cr,uid,picking_id[0])
- pick.force_assign(cr, uid)
- partial_datas = {
- 'partner_id':pick.address_id.partner_id.id,
- 'address_id': pick.address_id.id,
- 'delivery_date' : time.strftime('%Y-%m-%d'),
- }
- move = pick.move_lines[0]
- partial_datas['move%s'%(move.id)]= {
- 'product_id': move.product_id.id,
- 'product_qty': move.product_qty,
- 'product_uom': move.product_uom.id,
- }
- self.do_partial(cr, uid, [pick.id],partial_datas)
+ pick=self.browse(cr,uid,picking_id[0])
+ pick.force_assign(cr, uid)
+ stock_partial_picking = self.pool.get('stock.partial.picking')
+ partial_id = stock_partial_picking.create(cr, uid, {},
+ context={'active_model': 'stock.picking',
+ 'active_ids': [pick.id]})
+ stock_partial_picking.do_partial(cr, uid, [partial_id])
-
I verify that delivery state is done
-
pick = self.browse(cr,uid,picking_id[0])
assert (pick.state) =='done', "Picking for SO is not in done state."
-
- I verify that a "Picked" has been set to true
+ I verify that the sale order is marked as delivered
-
!python {model: sale.order}: |
so = self.browse(cr, uid, ref("sale_order_so7"))
if picking_id:
pick=self.browse(cr,uid,picking_id[0])
pick.force_assign(cr, uid)
- partial_datas = {
- 'partner_id':pick.address_id.partner_id.id,
- 'address_id': pick.address_id.id,
- 'delivery_date' : time.strftime('%Y-%m-%d'),
- }
- move = pick.move_lines[0]
- partial_datas['move%s'%(move.id)]= {
- 'product_id': move.product_id.id,
- 'product_qty': move.product_qty,
- 'product_uom': move.product_uom.id,
- }
- self.do_partial(cr, uid, [pick.id],partial_datas)
+ stock_partial_picking = self.pool.get('stock.partial.picking')
+ partial_id = stock_partial_picking.create(cr, uid, {},
+ context={'active_model': 'stock.picking',
+ 'active_ids': [pick.id]})
+ stock_partial_picking.do_partial(cr, uid, [partial_id])
-
I verify that picking order is in done state.
-
picking_id = self.search(cr, uid, [('origin','=',so.name)])
assert (picking_id),"Delivery order has not been generated"
-
- I click on the Products Sent button and then on the Validate button
+ I process the delivery order
-
!python {model: stock.picking }: |
import time
if picking_id:
pick=self.browse(cr,uid,picking_id[0])
pick.force_assign(cr, uid)
- partial_datas = {
- 'partner_id':pick.address_id.partner_id.id,
- 'address_id': pick.address_id.id,
- 'delivery_date' : time.strftime('%Y-%m-%d'),
- }
- move = pick.move_lines[0]
- partial_datas['move%s'%(move.id)]= {
- 'product_id': move.product_id.id,
- 'product_qty': move.product_qty,
- 'product_uom': move.product_uom.id,
- }
- self.do_partial(cr, uid, [pick.id],partial_datas)
--
- I verify that delivery state is done
+ stock_partial_picking = self.pool.get('stock.partial.picking')
+ partial_id = stock_partial_picking.create(cr, uid, {},
+ context={'active_model': 'stock.picking',
+ 'active_ids': [pick.id]})
+ stock_partial_picking.do_partial(cr, uid, [partial_id])
+-
+ I verify that delivery order is marked done
-
!python {model: stock.picking }: |
sale_order_obj = self.pool.get('sale.order')
for pur in pur_ids:
wf_service.trg_validate(uid, 'purchase.order',pur,'purchase_approve', cr)
-
- I verify that a picking related to purchase order has been generated.
+ I verify that a picking related to purchase order has been generated and I process it
-
!python {model: sale.order}: |
modules = self.pool.get('ir.module.module')
pur_id = pur_obj.search(cr, uid, [('origin','=',so.name)])
po = pur_obj.browse(cr, uid, pur_id)[0]
assert(po.picking_ids),"Picking for purchase order has not been generated"
+ picking, = po.picking_ids
+ stock_partial_picking = self.pool.get('stock.partial.picking')
+ partial_id = stock_partial_picking.create(cr, uid, {},
+ context={'active_model': 'stock.picking',
+ 'active_ids': [picking.id]})
+ stock_partial_picking.do_partial(cr, uid, [partial_id])
-
- Then I click on the "Products Received" button of Incoming Shipments
--
- !record {model: stock.partial.picking, id: stock_partial_picking_0}:
- date: !eval time.strftime('%Y-%m-%d %H:%M:%S')
--
- I click on the "Validate" button
--
- !python {model: stock.picking}: |
- modules = self.pool.get('ir.module.module')
- mod_pur = modules.search(cr, uid, [('name','=','purchase')])
- mod_brw = modules.browse(cr,uid,mod_pur)[0]
- if (mod_brw.state == 'installed'):
- sale_order_obj = self.pool.get('sale.order')
- pur_obj = self.pool.get('purchase.order')
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so8"))
- pur_id = pur_obj.search(cr, uid, [('origin','=',so.name)])
- po = pur_obj.browse(cr, uid, pur_id)[0]
- pick_ser_id = self.search(cr, uid, [('purchase_id', '=', po.id )])
- import netsvc
- wf_service = netsvc.LocalService("workflow")
- for pick in pick_ser_id:
- wf_service.trg_validate(uid, 'stock.picking',pick,'button_done', cr)
--
- I verify that picking for purchase order has been done.
+ I verify that picking for purchase order has been marked done.
-
!python {model: sale.order}: |
from tools.translate import _
ids = picking_obj.search(cr, uid, [('purchase_id', '=', po.id ),('state', '=', 'done')])
assert ids, _('Picking is not in the done state!')
-
- I verify that a "Picked" has been set to true
+ I verify that the sale order is marked as delivered
-
!python {model: sale.order}: |
so = self.browse(cr, uid, ref("sale_order_so8"))
if picking_id:
pick=self.browse(cr,uid,picking_id[0])
pick.force_assign(cr, uid)
- partial_datas = {
- 'partner_id':pick.address_id.partner_id.id,
- 'address_id': pick.address_id.id,
- 'delivery_date' : time.strftime('%Y-%m-%d'),
- }
- move = pick.move_lines[0]
- partial_datas['move%s'%(move.id)]= {
- 'product_id': move.product_id.id,
- 'product_qty': move.product_qty,
- 'product_uom': move.product_uom.id,
- }
- self.do_partial(cr, uid, [pick.id],partial_datas)
+ stock_partial_picking = self.pool.get('stock.partial.picking')
+ partial_id = stock_partial_picking.create(cr, uid, {},
+ context={'active_model': 'stock.picking',
+ 'active_ids': [pick.id]})
+ stock_partial_picking.do_partial(cr, uid, [partial_id])
-
I verify that picking order is in done state.
-
for pur in pur_ids:
wf_service.trg_validate(uid, 'purchase.order',pur,'purchase_approve', cr)
-
- I verify that a picking related to purchase order has been generated.
+ I verify that a picking related to purchase order has been generated and I process it
-
!python {model: sale.order}: |
modules = self.pool.get('ir.module.module')
pur_id = pur_obj.search(cr, uid, [('origin','=',so.name)])
po = pur_obj.browse(cr, uid, pur_id)[0]
assert(po.picking_ids),"Picking for purchase order has not been generated"
--
- Then I click on the "Products Received" button of Incoming Shipments
--
- !record {model: stock.partial.picking, id: stock_partial_picking_0}:
- date: !eval time.strftime('%Y-%m-%d %H:%M:%S')
--
- I click on the "Validate" button
--
- !python {model: stock.picking}: |
- modules = self.pool.get('ir.module.module')
- sale_order_obj = self.pool.get('sale.order')
- pur_obj = self.pool.get('purchase.order')
- mod_pur = modules.search(cr, uid, [('name','=','purchase')])
- mod_brw = modules.browse(cr,uid,mod_pur)[0]
- if (mod_brw.state == 'installed'):
- so = sale_order_obj.browse(cr, uid, ref("sale_order_so1"))
- pur_id = pur_obj.search(cr, uid, [('origin','=',so.name)])
- po = pur_obj.browse(cr, uid, pur_id)[0]
- pick_ser_id = self.search(cr, uid, [('purchase_id', '=', po.id )])
- import netsvc
- wf_service = netsvc.LocalService("workflow")
- for pick in pick_ser_id:
- wf_service.trg_validate(uid, 'stock.picking',pick,'button_done', cr)
--
- I verify that picking for purchase order has been done.
--
- !python {model: sale.order}: |
- from tools.translate import _
- modules = self.pool.get('ir.module.module')
- mod_pur = modules.search(cr, uid, [('name','=','purchase')])
- mod_brw = modules.browse(cr,uid,mod_pur)[0]
- if(mod_brw.state == 'installed'):
- pur_obj = self.pool.get('purchase.order')
- so = self.browse(cr, uid, ref("sale_order_so1"))
- pur_id = pur_obj.search(cr, uid, [('origin','=',so.name)])
- po = pur_obj.browse(cr, uid, pur_id)[0]
+ picking, = po.picking_ids
+ stock_partial_picking = self.pool.get('stock.partial.picking')
+ partial_id = stock_partial_picking.create(cr, uid, {},
+ context={'active_model': 'stock.picking',
+ 'active_ids': [picking.id]})
+ stock_partial_picking.do_partial(cr, uid, [partial_id])
picking_obj = self.pool.get('stock.picking')
- ids = picking_obj.search(cr, uid, [('purchase_id', '=', po.id ),('state', '=', 'done')])
- assert ids, _('Picking is not in the done state!')
+ ids = picking_obj.search(cr, uid, [('purchase_id', '=', po.id),('state', '=', 'done')])
+ assert ids, 'Picking should be marked done!'
-
- I verify that a "Picked" has been set to true
+ I verify that the sale order is marked as delivered
-
!python {model: sale.order}: |
so = self.browse(cr, uid, ref("sale_order_so1"))
- assert (so.shipped == True), "Picking is not done."
+ assert (so.shipped == True), "Sale order is not marked as delivered"
-
I verify that a sale order is in done state
-
def action_process(self, cr, uid, ids, context=None):
if context is None: context = {}
- partial_id = self.pool.get("stock.partial.picking").create(
- cr, uid, {}, context=dict(context, active_ids=ids))
+ context = dict(context, active_ids=ids, active_model=self._name)
+ partial_id = self.pool.get("stock.partial.picking").create(cr, uid, {}, context=context)
return {
'name':_("Products to Process"),
'view_mode': 'form',
'nodestroy': True,
'target': 'new',
'domain': '[]',
- 'context': dict(context, active_ids=ids)
+ 'context': context,
}
def copy(self, cr, uid, id, default=None, context=None):
def action_partial_move(self, cr, uid, ids, context=None):
if context is None: context = {}
+ if context.get('active_model') != self._name:
+ context.update(active_ids=ids, active_model=self._name)
partial_id = self.pool.get("stock.partial.move").create(
cr, uid, {}, context=context)
return {
""" Makes the move done and if all moves are done, it will finish the picking.
@return:
"""
- partial_datas=''
picking_ids = []
move_ids = []
- partial_obj=self.pool.get('stock.partial.picking')
wf_service = netsvc.LocalService("workflow")
- partial_id=partial_obj.search(cr,uid,[])
- if partial_id:
- partial_datas = partial_obj.read(cr, uid, partial_id, context=context)[0]
if context is None:
context = {}
self.action_done(cr, uid, [move.move_dest_id.id], context=context)
self._create_product_valuation_moves(cr, uid, move, context=context)
- prodlot_id = partial_datas and partial_datas.get('move%s_prodlot_id' % (move.id), False)
- if prodlot_id:
- self.write(cr, uid, [move.id], {'prodlot_id': prodlot_id}, context=context)
if move.state not in ('confirmed','done','assigned'):
todo.append(move.id)
-
!python {model: stock.picking }: |
import time
- pick=self.browse(cr,uid,ref('stock_picking_0'))
- move =pick.move_lines[0]
- partial_datas = {
- 'partner_id':pick.address_id.partner_id.id,
- 'address_id': pick.address_id.id,
- 'delivery_date' : time.strftime('%Y-%m-%d')
- }
- partial_datas['move%s'%(move.id)]= {
- 'product_id': move.product_id,
- 'product_qty': move.product_qty,
- 'product_uom': move.product_uom.id,
- }
- self.do_partial(cr, uid, [ref('stock_picking_0')],partial_datas)
+ pick = self.browse(cr,uid,ref('stock_picking_0'))
+ stock_partial_picking = self.pool.get('stock.partial.picking')
+ partial_id = stock_partial_picking.create(cr, uid, {},
+ context={'active_model': 'stock.picking',
+ 'active_ids': [pick.id]})
+ stock_partial_picking.do_partial(cr, uid, [partial_id])
##############################################################################
#
# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
+# Copyright (C) 2004-TODAY OpenERP SA (<http://openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
##############################################################################
from osv import fields, osv
-from tools.translate import _
+from tools.misc import DEFAULT_SERVER_DATETIME_FORMAT
import time
-import decimal_precision as dp
-
-class stock_partial_move_memory_out(osv.osv_memory):
- _inherit = "stock.picking.memory.out"
- _name = "stock.move.memory.out"
- _columns = {
- 'wizard_id' : fields.many2one('stock.partial.move', string="Wizard"),
- }
-
-class stock_partial_move_memory_in(osv.osv_memory):
- _inherit = "stock.picking.memory.in"
- _name = "stock.move.memory.in"
+class stock_partial_move_line(osv.osv_memory):
+ _inherit = "stock.partial.picking.line"
+ _name = "stock.partial.move.line"
_columns = {
- 'wizard_id' : fields.many2one('stock.partial.move', string="Wizard"),
+ 'wizard_id' : fields.many2one('stock.partial.move', string="Wizard", ondelete='CASCADE'),
}
-
+
class stock_partial_move(osv.osv_memory):
_name = "stock.partial.move"
- _description = "Partial Move"
+ _inherit = 'stock.partial.picking'
+ _description = "Partial Move Processing Wizard"
_columns = {
'date': fields.datetime('Date', required=True),
- 'type': fields.char("Type", size=3),
- 'product_moves_out' : fields.one2many('stock.move.memory.out', 'wizard_id', 'Moves'),
- 'product_moves_in' : fields.one2many('stock.move.memory.in', 'wizard_id', 'Moves'),
+ 'move_ids' : fields.one2many('stock.partial.move.line', 'wizard_id', 'Moves'),
+
+ # picking_id is not used for move processing, so we remove the required attribute
+ # from the inherited column, and ignore it
+ 'picking_id': fields.many2one('stock.picking', 'Picking'),
}
-
-
- def __is_in(self,cr, uid, move_ids):
- """
- @return: True if one of the moves has as picking type 'in'
- """
- if not move_ids:
- return False
-
- move_obj = self.pool.get('stock.move')
- move_ids = move_obj.search(cr, uid, [('id','in',move_ids)])
-
- for move in move_obj.browse(cr, uid, move_ids):
- if move.picking_id.type == 'in' and move.product_id.cost_method == 'average':
- return True
- return False
-
- def __get_picking_type(self, cr, uid, move_ids):
- if self.__is_in(cr, uid, move_ids):
- return "product_moves_in"
- else:
- return "product_moves_out"
-
- def view_init(self, cr, uid, fields_list, context=None):
- res = super(stock_partial_move, self).view_init(cr, uid, fields_list, context=context)
- move_obj = self.pool.get('stock.move')
-
- if context is None:
- context = {}
- for move in move_obj.browse(cr, uid, context.get('active_ids', []), context=context):
- if move.state in ('done', 'cancel'):
- raise osv.except_osv(_('Invalid action !'), _('Cannot deliver products which are already delivered !'))
-
- return res
-
-
- def __create_partial_move_memory(self, move):
- move_memory = {
- 'product_id' : move.product_id.id,
- 'quantity' : move.product_qty,
- 'product_uom' : move.product_uom.id,
- 'prodlot_id' : move.prodlot_id.id,
- 'move_id' : move.id,
- }
-
- if move.picking_id.type == 'in':
- move_memory.update({
- 'cost' : move.product_id.standard_price,
- 'currency' : move.product_id.company_id and move.product_id.company_id.currency_id and move.product_id.company_id.currency_id.id or False,
- })
- return move_memory
- def __get_active_stock_moves(self, cr, uid, context=None):
- move_obj = self.pool.get('stock.move')
- if context is None:
- context = {}
-
- res = []
- for move in move_obj.browse(cr, uid, context.get('active_ids', []), context=context):
- if move.state in ('done', 'cancel'):
- continue
- res.append(self.__create_partial_move_memory(move))
-
+ def default_get(self, cr, uid, fields, context=None):
+ if context is None: context = {}
+ # no call to super!
+ res = {}
+ move_ids = context.get('active_ids', [])
+ if not move_ids or not context.get('active_model') == 'stock.move':
+ return res
+ if 'move_ids' in fields:
+ move_ids = self.pool.get('stock.move').browse(cr, uid, move_ids, context=context)
+ moves = [self._partial_move_for(cr, uid, m) for m in move_ids if m.state not in ('done','cancel')]
+ res.update(move_ids=moves)
+ if 'date' in fields:
+ res.update(date=time.strftime(DEFAULT_SERVER_DATETIME_FORMAT))
return res
-
- _defaults = {
- 'product_moves_in' : __get_active_stock_moves,
- 'product_moves_out' : __get_active_stock_moves,
- 'date' : lambda *a : time.strftime('%Y-%m-%d %H:%M:%S'),
- }
-
-
- def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
- if not context:
- context = {}
-
- message = {
- 'title' : _('Deliver Products'),
- 'info' : _('Delivery Information'),
- 'button' : _('Deliver'),
- }
- if context:
- if context.get('product_receive', False):
- message = {
- 'title' : _('Receive Products'),
- 'info' : _('Receive Information'),
- 'button' : _('Receive'),
- }
-
- move_ids = context.get('active_ids', False)
- message['picking_type'] = self.__get_picking_type(cr, uid, move_ids)
- result = super(stock_partial_move, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar, submenu)
- _moves_fields = result['fields']
- _moves_fields.update({
- 'product_moves_in' : {'relation': 'stock.move.memory.in', 'type' : 'one2many', 'string' : 'Product Moves'},
- 'product_moves_out' : {'relation': 'stock.move.memory.out', 'type' : 'one2many', 'string' : 'Product Moves'}
- })
-
- _moves_arch_lst = """
- <form string="%(title)s">
- <separator colspan="4" string="%(info)s"/>
- <field name="date" colspan="2"/>
- <separator colspan="4" string="Move Detail"/>
- <field name="%(picking_type)s" colspan="4" nolabel="1" mode="tree,form" width="550" height="200" ></field>
- <separator string="" colspan="4" />
- <label string="" colspan="2"/>
- <group col="2" colspan="2">
- <button icon='gtk-cancel' special="cancel" string="_Cancel" />
- <button name="do_partial" string="%(button)s"
- colspan="1" type="object" icon="gtk-apply" />
- </group>
- </form> """ % message
-
- result['arch'] = _moves_arch_lst
- result['fields'] = _moves_fields
- return result
-
+
def do_partial(self, cr, uid, ids, context=None):
- """ Makes partial moves and pickings done.
- @param self: The object pointer.
- @param cr: A database cursor
- @param uid: ID of the user currently logged in
- @param fields: List of fields for which we want default values
- @param context: A standard dictionary
- @return: A dictionary which of fields with values.
- """
-
- if context is None:
- context = {}
- move_obj = self.pool.get('stock.move')
-
- move_ids = context.get('active_ids', False)
+ # no call to super!
+ assert len(ids) == 1, 'Partial move processing may only be done one form at a time'
partial = self.browse(cr, uid, ids[0], context=context)
- partial_datas = {
+ partial_data = {
'delivery_date' : partial.date
}
-
- p_moves = {}
- picking_type = self.__get_picking_type(cr, uid, move_ids)
-
- moves_list = picking_type == 'product_moves_in' and partial.product_moves_in or partial.product_moves_out
- for product_move in moves_list:
- p_moves[product_move.move_id.id] = product_move
-
- moves_ids_final = []
- for move in move_obj.browse(cr, uid, move_ids, context=context):
- if move.state in ('done', 'cancel'):
- continue
- if not p_moves.get(move.id):
- continue
- partial_datas['move%s' % (move.id)] = {
- 'product_id' : p_moves[move.id].product_id.id,
- 'product_qty' : p_moves[move.id].quantity,
- 'product_uom' :p_moves[move.id].product_uom.id,
- 'prodlot_id' : p_moves[move.id].prodlot_id.id,
+ moves_ids = []
+ for move in partial.move_ids:
+ move_id = move.move_id.id
+ partial_data['move%s' % (move_id)] = {
+ 'product_id': move.product_id.id,
+ 'product_qty': move.quantity,
+ 'product_uom': move.product_uom.id,
+ 'prodlot_id': move.prodlot_id.id,
}
-
- moves_ids_final.append(move.id)
- if (move.picking_id.type == 'in') and (move.product_id.cost_method == 'average'):
- partial_datas['move%s' % (move.id)].update({
- 'product_price' : p_moves[move.id].cost,
- 'product_currency': p_moves[move.id].currency.id,
- })
-
-
- move_obj.do_partial(cr, uid, moves_ids_final, partial_datas, context=context)
+ moves_ids.append(move_id)
+ if (move.move_id.picking_id.type == 'in') and (move.product_id.cost_method == 'average'):
+ partial_data['move%s' % (move_id)].update(product_price=move.cost,
+ product_currency=move.currency.id)
+ self.pool.get('stock.move').do_partial(cr, uid, moves_ids, partial_data, context=context)
return {'type': 'ir.actions.act_window_close'}
-stock_partial_move()
-stock_partial_move_memory_out()
-stock_partial_move_memory_in()
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
-
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
-
-
-
<record id="action_partial_move_server" model="ir.actions.server">
<field name="name">Deliver/Receive Products</field>
<field name="model_id" ref="model_stock_move"/>
<field name="state">code</field>
<field name="code">action = obj.action_partial_move(context=context)</field>
</record>
-
+
<record id="ir_open_partial_move_wizard" model="ir.values">
<field eval="'client_action_multi'" name="key2"/>
<field eval="'stock.move'" name="model"/>
<field eval="True" name="object"/>
</record>
-
-
- <record id="stock_move_memory_tree_in" model="ir.ui.view">
- <field name="name">stock.move.memory.tree</field>
- <field name="model">stock.move.memory.in</field>
- <field name="type">tree</field>
- <field name="arch" type="xml">
- <tree editable="bottom" string="Product Moves">
- <field name="product_id" />
- <field name="quantity" />
- <field name="product_uom" />
- <field name="location_id" />
- <field name="location_dest_id" />
- <field name="prodlot_id" domain="[('product_id', '=', product_id)]" groups="base.group_extended" />
- <field name="cost" />
- <field name="currency" />
- </tree>
- </field>
- </record>
-
- <record id="stock_move_memory_form_in" model="ir.ui.view">
- <field name="name">stock.move.memory.form</field>
- <field name="model">stock.move.memory.in</field>
+ <record id="stock_partial_move_form" model="ir.ui.view">
+ <field name="name">stock.partial.move.form</field>
+ <field name="model">stock.partial.move</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form>
- <field name="product_id" />
- <field name="quantity" />
- <field name="product_uom" />
- <field name="location_id" />
- <field name="location_dest_id" />
- <field name="prodlot_id" domain="[('product_id', '=', product_id)]" groups="base.group_extended" />
- <field name="cost" />
- <field name="currency" />
- </form>
+ <separator colspan="4" string="Products"/>
+ <field name="move_ids" colspan="4" nolabel="1" mode="tree,form" width="550" height="200"/>
+ <separator string="" colspan="4" />
+ <label string="" colspan="2"/>
+ <group col="2" colspan="2">
+ <button icon='gtk-cancel' special="cancel" string="_Cancel" />
+ <button name="do_partial" string="_Validate" colspan="1" type="object" icon="gtk-go-forward" />
+ </group>
+ </form>
</field>
- </record>
-
- <record id="stock_move_memory_tree_out" model="ir.ui.view">
- <field name="name">stock.move.memory.tree</field>
- <field name="model">stock.move.memory.out</field>
+ </record>
+
+ <record id="stock_partial_move_line_list" model="ir.ui.view">
+ <field name="name">stock.partial.move.line.list</field>
+ <field name="model">stock.partial.move.line</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree editable="bottom" string="Product Moves">
<field name="product_uom" />
<field name="location_id" />
<field name="location_dest_id" />
- <field name="prodlot_id" domain="[('product_id', '=', product_id)]" groups="base.group_extended" />
+ <field name="prodlot_id" domain="[('product_id', '=', product_id)]" groups="base.group_extended" />
+ <field name="update_cost" invisible="1"/>
+ <field name="cost" attrs="{'invisible': [('update_cost','=', False)]}"/>
+ <field name="currency" attrs="{'invisible': [('update_cost','=', False)]}"/>
</tree>
</field>
</record>
-
- <record id="stock_move_memory_form_out" model="ir.ui.view">
- <field name="name">stock.move.memory.form</field>
- <field name="model">stock.move.memory.out</field>
+
+ <record id="stock_partial_move_line_form" model="ir.ui.view">
+ <field name="name">stock.partial.move.line.form</field>
+ <field name="model">stock.partial.move.line</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form>
<field name="location_id" />
<field name="location_dest_id" />
<field name="prodlot_id" domain="[('product_id', '=', product_id)]" groups="base.group_extended" />
- </form>
+ <field name="update_cost" invisible="1"/>
+ <field name="cost" attrs="{'invisible': [('update_cost','=', False)]}"/>
+ <field name="currency" attrs="{'invisible': [('update_cost','=', False)]}"/>
+ </form>
</field>
- </record>
-
+ </record>
</data>
</openerp>
-
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
+# Copyright (C) 2004-TODAY OpenERP SA (<http://openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
#
##############################################################################
-from osv import fields, osv
-from tools.translate import _
import time
+from osv import fields, osv
+from tools.misc import DEFAULT_SERVER_DATETIME_FORMAT
-class stock_partial_picking_memory_out(osv.osv_memory):
- _name = "stock.picking.memory.out"
+class stock_partial_picking_line(osv.TransientModel):
+ _name = "stock.partial.picking.line"
_rec_name = 'product_id'
_columns = {
- 'product_id' : fields.many2one('product.product', string="Product", required=True),
+ 'product_id' : fields.many2one('product.product', string="Product", required=True, ondelete='CASCADE'),
'quantity' : fields.float("Quantity", required=True),
- 'product_uom': fields.many2one('product.uom', 'Unit of Measure', required=True),
- 'prodlot_id' : fields.many2one('stock.production.lot', 'Production Lot'),
- 'location_id': fields.many2one('stock.location', 'Location', required=True),
- 'location_dest_id': fields.many2one('stock.location', 'Dest. Location', required=True),
- 'move_id' : fields.many2one('stock.move', "Move"),
- 'wizard_id' : fields.many2one('stock.partial.picking', string="Wizard"),
+ 'product_uom': fields.many2one('product.uom', 'Unit of Measure', required=True, ondelete='CASCADE'),
+ 'prodlot_id' : fields.many2one('stock.production.lot', 'Production Lot', ondelete='CASCADE'),
+ 'location_id': fields.many2one('stock.location', 'Location', required=True, ondelete='CASCADE'),
+ 'location_dest_id': fields.many2one('stock.location', 'Dest. Location', required=True, ondelete='CASCADE'),
+ 'move_id' : fields.many2one('stock.move', "Move", ondelete='CASCADE'),
+ 'wizard_id' : fields.many2one('stock.partial.picking', string="Wizard", ondelete='CASCADE'),
+ 'update_cost': fields.boolean('Need cost update'),
'cost' : fields.float("Cost", help="Unit Cost for this product line"),
- 'currency' : fields.many2one('res.currency', string="Currency", help="Currency in which Unit cost is expressed"),
+ 'currency' : fields.many2one('res.currency', string="Currency", help="Currency in which Unit cost is expressed", ondelete='CASCADE'),
}
-class stock_partial_picking_memory_in(osv.osv_memory):
- _inherit = "stock.picking.memory.out"
- _name = "stock.picking.memory.in"
-
class stock_partial_picking(osv.osv_memory):
_name = "stock.partial.picking"
- _description = "Partial Picking"
+ _description = "Partial Picking Processing Wizard"
_columns = {
'date': fields.datetime('Date', required=True),
- 'product_moves_out' : fields.one2many('stock.picking.memory.out', 'wizard_id', 'Moves'),
- 'product_moves_in' : fields.one2many('stock.picking.memory.in', 'wizard_id', 'Moves'),
+ 'move_ids' : fields.one2many('stock.partial.picking.line', 'wizard_id', 'Product Moves'),
+ 'picking_id': fields.many2one('stock.picking', 'Picking', required=True, ondelete='CASCADE'),
}
- def get_picking_type(self, cr, uid, picking, context=None):
- picking_type = picking.type
- for move in picking.move_lines:
- if picking.type == 'in' and move.product_id.cost_method == 'average':
- picking_type = 'in'
- break
- else:
- picking_type = 'out'
- return picking_type
-
def default_get(self, cr, uid, fields, context=None):
- """ To get default values for the object.
- @param self: The object pointer.
- @param cr: A database cursor
- @param uid: ID of the user currently logged in
- @param fields: List of fields for which we want default values
- @param context: A standard dictionary
- @return: A dictionary which of fields with values.
- """
- if context is None:
- context = {}
-
- pick_obj = self.pool.get('stock.picking')
+ if context is None: context = {}
res = super(stock_partial_picking, self).default_get(cr, uid, fields, context=context)
picking_ids = context.get('active_ids', [])
- if not picking_ids:
+ if not picking_ids or (not context.get('active_model') == 'stock.picking') \
+ or len(picking_ids) != 1:
+ # Partial Picking Processing may only be done for one picking at a time
return res
-
- result = []
- for pick in pick_obj.browse(cr, uid, picking_ids, context=context):
- pick_type = self.get_picking_type(cr, uid, pick, context=context)
- for m in pick.move_lines:
- if m.state in ('done', 'cancel'):
- continue
- result.append(self.__create_partial_picking_memory(m, pick_type))
-
- if 'product_moves_in' in fields:
- res.update({'product_moves_in': result})
- if 'product_moves_out' in fields:
- res.update({'product_moves_out': result})
+ picking_id, = picking_ids
+ if 'picking_id' in fields:
+ res.update(picking_id=picking_id)
+ if 'move_ids' in fields:
+ picking = self.pool.get('stock.picking').browse(cr, uid, picking_id, context=context)
+ moves = [self._partial_move_for(cr, uid, m) for m in picking.move_lines if m.state not in ('done','cancel')]
+ res.update(move_ids=moves)
if 'date' in fields:
- res.update({'date': time.strftime('%Y-%m-%d %H:%M:%S')})
+ res.update(date=time.strftime(DEFAULT_SERVER_DATETIME_FORMAT))
return res
-
- def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
- result = super(stock_partial_picking, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar, submenu)
-
- pick_obj = self.pool.get('stock.picking')
- picking_ids = context.get('active_ids', False)
- if not picking_ids:
- # not called through an action (e.g. buildbot), return the default.
- return result
-
- for pick in pick_obj.browse(cr, uid, picking_ids, context=context):
- picking_type = self.get_picking_type(cr, uid, pick, context=context)
+ def _product_cost_for_average_update(self, cr, uid, move):
+ """Returns product cost and currency ID for the given move, suited for re-computing
+ the average product cost.
- _moves_arch_lst = """<form string="%s">
- <field name="date" invisible="1"/>
- <separator colspan="4" string="%s"/>
- <field name="%s" colspan="4" nolabel="1" mode="tree,form" width="550" height="200" ></field>
- """ % (_('Process Document'), _('Products'), "product_moves_" + picking_type)
- _moves_fields = result['fields']
-
- # add field related to picking type only
- _moves_fields.update({
- 'product_moves_' + picking_type: {'relation': 'stock.move.memory.'+picking_type, 'type' : 'one2many', 'string' : 'Product Moves'},
- })
+ :return: map of the form::
- _moves_arch_lst += """
- <separator string="" colspan="4" />
- <label string="" colspan="2"/>
- <group col="2" colspan="2">
- <button icon='gtk-cancel' special="cancel"
- string="_Cancel" />
- <button name="do_partial" string="_Validate"
- colspan="1" type="object" icon="gtk-go-forward" />
- </group>
- </form>"""
- result['arch'] = _moves_arch_lst
- result['fields'] = _moves_fields
- return result
+ {'cost': 123.34,
+ 'currency': 42}
+ """
+ # Currently, the cost on the product form is supposed to be expressed in the currency
+ # of the company owning the product. If not set, we fall back to the picking's company,
+ # which should work in simple cases.
+ return {'cost': move.product_id.standard_price,
+ 'currency': move.product_id.company_id.currency_id.id \
+ or move.picking_id.company_id.currency_id.id \
+ or False}
- def __create_partial_picking_memory(self, picking, pick_type):
- move_memory = {
- 'product_id' : picking.product_id.id,
- 'quantity' : picking.product_qty,
- 'product_uom' : picking.product_uom.id,
- 'prodlot_id' : picking.prodlot_id.id,
- 'move_id' : picking.id,
- 'location_id' : picking.location_id.id,
- 'location_dest_id' : picking.location_dest_id.id,
+ def _partial_move_for(self, cr, uid, move):
+ partial_move = {
+ 'product_id' : move.product_id.id,
+ 'quantity' : move.product_qty,
+ 'product_uom' : move.product_uom.id,
+ 'prodlot_id' : move.prodlot_id.id,
+ 'move_id' : move.id,
+ 'location_id' : move.location_id.id,
+ 'location_dest_id' : move.location_dest_id.id,
}
-
- if pick_type == 'in':
- move_memory.update({
- 'cost' : picking.product_id.standard_price,
- 'currency' : picking.product_id.company_id and picking.product_id.company_id.currency_id and picking.product_id.company_id.currency_id.id or False,
- })
- return move_memory
+ if move.picking_id.type == 'in' and move.product_id.cost_method == 'average':
+ partial_move.update(update_cost=True, **self._product_cost_for_average_update(cr, uid, move))
+ return partial_move
def do_partial(self, cr, uid, ids, context=None):
- """ Makes partial moves and pickings done.
- @param self: The object pointer.
- @param cr: A database cursor
- @param uid: ID of the user currently logged in
- @param fields: List of fields for which we want default values
- @param context: A standard dictionary
- @return: A dictionary which of fields with values.
- """
- pick_obj = self.pool.get('stock.picking')
- stock_move_obj = self.pool.get('stock.move')
- picking_ids = context.get('active_ids', False)
+ assert len(ids) == 1, 'Partial picking processing may only be done one at a time'
+ stock_picking = self.pool.get('stock.picking')
+ stock_move = self.pool.get('stock.move')
partial = self.browse(cr, uid, ids[0], context=context)
- partial_datas = {
+ partial_data = {
'delivery_date' : partial.date
}
- for pick in pick_obj.browse(cr, uid, picking_ids, context=context):
- picking_type = self.get_picking_type(cr, uid, pick, context=context)
- moves_list = picking_type == 'in' and partial.product_moves_in or partial.product_moves_out
- for move in moves_list:
- if not move.move_id.id:
- seq_obj_name = 'stock.picking.' + picking_type
- move_id = stock_move_obj.create(cr,uid,{'name' : self.pool.get('ir.sequence').get(cr, uid, seq_obj_name),
- 'product_id': move.product_id.id,
- 'product_qty': move.quantity,
- 'product_uom': move.product_uom.id,
- 'prodlot_id': move.prodlot_id.id,
- 'location_id' : move.location_id.id,
- 'location_dest_id' : move.location_dest_id.id,
- 'picking_id': pick.id
- },context=context)
- stock_move_obj.action_done(cr, uid, [move_id], context)
- else:
- move_id = move.move_id.id
-
- partial_datas['move%s' % (move_id)] = {
- 'product_id': move.product_id.id,
- 'product_qty': move.quantity,
- 'product_uom': move.product_uom.id,
- 'prodlot_id': move.prodlot_id.id,
- }
- if (picking_type == 'in') and (move.product_id.cost_method == 'average'):
- partial_datas['move%s' % (move.move_id.id)].update({
- 'product_price' : move.cost,
- 'product_currency': move.currency.id,
- })
- pick_obj.do_partial(cr, uid, picking_ids, partial_datas, context=context)
+ picking_type = partial.picking_id.type
+ for move in partial.move_ids:
+ move_id = move.move_id.id
+ if not move_id:
+ seq_obj_name = 'stock.picking.' + picking_type
+ move_id = stock_move.create(cr,uid,{'name' : self.pool.get('ir.sequence').get(cr, uid, seq_obj_name),
+ 'product_id': move.product_id.id,
+ 'product_qty': move.quantity,
+ 'product_uom': move.product_uom.id,
+ 'prodlot_id': move.prodlot_id.id,
+ 'location_id' : move.location_id.id,
+ 'location_dest_id' : move.location_dest_id.id,
+ 'picking_id': partial.picking_id.id
+ },context=context)
+ stock_move.action_done(cr, uid, [move_id], context)
+ partial_data['move%s' % (move_id)] = {
+ 'product_id': move.product_id.id,
+ 'product_qty': move.quantity,
+ 'product_uom': move.product_uom.id,
+ 'prodlot_id': move.prodlot_id.id,
+ }
+ if (picking_type == 'in') and (move.product_id.cost_method == 'average'):
+ partial_data['move%s' % (move.move_id.id)].update(product_price=move.cost,
+ product_currency=move.currency.id)
+ stock_picking.do_partial(cr, uid, [partial.picking_id.id], partial_data, context=context)
return {'type': 'ir.actions.act_window_close'}
-stock_partial_picking()
-stock_partial_picking_memory_out()
-stock_partial_picking_memory_in()
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
<field name="target">new</field>
</record>
+ <record id="stock_partial_picking_form" model="ir.ui.view">
+ <field name="name">stock.partial.picking.form</field>
+ <field name="model">stock.partial.picking</field>
+ <field name="type">form</field>
+ <field name="arch" type="xml">
+ <form>
+ <separator colspan="4" string="Products"/>
+ <field name="move_ids" colspan="4" nolabel="1" mode="tree,form" width="550" height="200"/>
+ <separator string="" colspan="4" />
+ <label string="" colspan="2"/>
+ <group col="2" colspan="2">
+ <button icon='gtk-cancel' special="cancel" string="_Cancel" />
+ <button name="do_partial" string="_Validate" colspan="1" type="object" icon="gtk-go-forward" />
+ </group>
+ </form>
+ </field>
+ </record>
+
+ <record id="stock_partial_picking_line_list" model="ir.ui.view">
+ <field name="name">stock.partial.picking.line.list</field>
+ <field name="model">stock.partial.picking.line</field>
+ <field name="type">tree</field>
+ <field name="arch" type="xml">
+ <tree editable="bottom" string="Product Moves">
+ <field name="product_id" />
+ <field name="quantity" />
+ <field name="product_uom" />
+ <field name="location_id" />
+ <field name="location_dest_id" />
+ <field name="prodlot_id" domain="[('product_id', '=', product_id)]" groups="base.group_extended" />
+ <field name="update_cost" invisible="1"/>
+ <field name="cost" attrs="{'invisible': [('update_cost','=', False)]}"/>
+ <field name="currency" attrs="{'invisible': [('update_cost','=', False)]}"/>
+ </tree>
+ </field>
+ </record>
+ <record id="stock_partial_picking_line_form" model="ir.ui.view">
+ <field name="name">stock.partial.picking.line.form</field>
+ <field name="model">stock.partial.picking.line</field>
+ <field name="type">form</field>
+ <field name="arch" type="xml">
+ <form>
+ <field name="product_id" />
+ <field name="quantity" />
+ <field name="product_uom" />
+ <field name="location_id" />
+ <field name="location_dest_id" />
+ <field name="prodlot_id" domain="[('product_id', '=', product_id)]" groups="base.group_extended" />
+ <field name="update_cost" invisible="1"/>
+ <field name="cost" attrs="{'invisible': [('update_cost','=', False)]}"/>
+ <field name="currency" attrs="{'invisible': [('update_cost','=', False)]}"/>
+ </form>
+ </field>
+ </record>
</data>
</openerp>
"active_ids": [ref("stock.menu_action_picking_tree")], "active_id": ref("stock.menu_action_picking_tree"),
})
-
- I create a record for partial picking.
--
- !record {model: stock.partial.picking, id: stock_partial_picking_0}:
- date: !eval time.strftime('%Y-%m-%d %H:%M:%S')
--
- I make picking order Done.
+ I process the delivery
-
!python {model: stock.partial.picking}: |
- pick_obj = self.pool.get('stock.picking')
- partial = self.browse(cr, uid, ref('stock_partial_picking_0'), context)
- partial_datas = {
- 'delivery_date' : partial.date
- }
- for pick in pick_obj.browse(cr, uid, [ref('stock_picking_out0')]):
- for m in pick.move_lines:
- partial_datas['move%s'%(m.id)] = {
- 'product_id' : m.product_id.id,
- 'product_qty' : m.product_qty,
- 'product_uom' : m.product_uom.id
- }
- pick_obj.do_partial(cr, uid, [ref('stock_picking_out0')], partial_datas, context=context)
+ partial_id = self.create(cr, uid, {}, context={'active_model':'stock.picking',
+ 'active_ids':[ref('stock_picking_out0')]})
+ self.do_partial(cr, uid, [partial_id])
-
As the Invoice state of the picking order is To be invoiced. I create invoice for my outgoing picking order.
-
_inherit = 'stock.partial.picking'
def do_partial(self, cr, uid, ids, context=None):
- """ Makes partial moves and pickings done and
- launches Create invoice wizard if invoice state is To be Invoiced.
- @param self: The object pointer.
- @param cr: A database cursor
- @param uid: ID of the user currently logged in
- @param context: A standard dictionary
- @return:
+ """Launch Create invoice wizard if invoice state is To be Invoiced,
+ after processing the partial picking.
"""
- if context is None:
- context = {}
+ if context is None: context = {}
result = super(invoice_directly, self).do_partial(cr, uid, ids, context)
- pick_obj = self.pool.get('stock.picking')
- context.update({'active_model':'stock.picking'})
- picking_ids = context.get('active_ids', False)
- if picking_ids:
- context.update({'active_id':picking_ids[0]})
- pick = pick_obj.browse(cr, uid, picking_ids, context=context)[0]
- if pick.invoice_state == '2binvoiced':
+ partial = self.browse(cr, uid, ids[0], context)
+ context.update(active_model='stock.picking',
+ active_ids=[partial.picking_id.id])
+ if partial.picking_id.invoice_state == '2binvoiced':
return {
'name': 'Create Invoice',
'view_type': 'form',
return {'type': 'ir.actions.act_window_close'}
invoice_directly()
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file