380 lines
15 KiB
YAML
380 lines
15 KiB
YAML
-
|
|
Set a product as using fifo price
|
|
-
|
|
!record {model: product.product, id: product_fifo_icecream}:
|
|
default_code: FIFO
|
|
name: FIFO Ice Cream
|
|
type: product
|
|
categ_id: product.product_category_1
|
|
list_price: 100.0
|
|
standard_price: 70.0
|
|
uom_id: product.product_uom_kgm
|
|
uom_po_id: product.product_uom_kgm
|
|
procure_method: make_to_stock
|
|
cost_method: fifo
|
|
valuation: real_time
|
|
property_stock_account_input: account.o_expense
|
|
property_stock_account_output: account.o_income
|
|
description: FIFO Ice Cream can be mass-produced and thus is widely available in developed parts of the world. Ice cream can be purchased in large cartons (vats and squrounds) from supermarkets and grocery stores, in smaller quantities from ice cream shops, convenience stores, and milk bars, and in individual servings from small carts or vans at public events.
|
|
-
|
|
I create a draft Purchase Order for first in move for 10 kg at 50 euro
|
|
-
|
|
!record {model: purchase.order, id: purchase_order_fifo1}:
|
|
partner_id: base.res_partner_3
|
|
location_id: stock.stock_location_stock
|
|
pricelist_id: 1
|
|
order_line:
|
|
- product_id: product_fifo_icecream
|
|
product_qty: 10.0
|
|
product_uom: product.product_uom_categ_kgm
|
|
price_unit: 50.0
|
|
name: 'FIFO Ice Cream'
|
|
-
|
|
I create a draft Purchase Order for second shipment for 30 kg at 80 euro
|
|
-
|
|
!record {model: purchase.order, id: purchase_order_fifo2}:
|
|
partner_id: base.res_partner_3
|
|
location_id: stock.stock_location_stock
|
|
pricelist_id: 1
|
|
order_line:
|
|
- product_id: product_fifo_icecream
|
|
product_qty: 30.0
|
|
product_uom: product.product_uom_categ_kgm
|
|
price_unit: 80.0
|
|
name: 'FIFO Ice Cream'
|
|
-
|
|
I confirm the first purchase order
|
|
-
|
|
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_fifo1}
|
|
-
|
|
I check the "Approved" status of purchase order 1
|
|
-
|
|
!assert {model: purchase.order, id: purchase_order_fifo1}:
|
|
- state == 'approved'
|
|
-
|
|
Process the reception of purchase order 1 and set date
|
|
-
|
|
!python {model: stock.partial.picking}: |
|
|
pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_fifo1")).picking_ids
|
|
partial_id = self.create(cr, uid, {}, context={'active_model': 'stock.picking','active_ids': [pick_ids[0].id]})
|
|
self.do_partial(cr, uid, [partial_id])
|
|
-
|
|
Check the standard price of the product (fifo icecream)
|
|
-
|
|
!python {model: product.product}: |
|
|
assert self.browse(cr, uid, ref("product_fifo_icecream")).standard_price == 70.0, 'Standard price should not have changed!'
|
|
-
|
|
I confirm the second purchase order
|
|
-
|
|
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_fifo2}
|
|
-
|
|
Process the reception of purchase order 2
|
|
-
|
|
!python {model: stock.partial.picking}: |
|
|
pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_fifo2")).picking_ids
|
|
partial_id = self.create(cr, uid, {}, context={'active_model': 'stock.picking','active_ids': [pick_ids[0].id]})
|
|
self.do_partial(cr, uid, [partial_id])
|
|
-
|
|
A purchase order towards the Chicago shop TODO code for receiving
|
|
-
|
|
!record {model: purchase.order, id: purchase_order_fifo_comp}:
|
|
partner_id: base.res_partner_3
|
|
company_id: stock.res_company_1
|
|
location_id: stock.stock_location_shop0
|
|
pricelist_id: 1
|
|
order_line:
|
|
- product_id: product_fifo_icecream
|
|
product_qty: 35.0
|
|
product_uom: product.product_uom_categ_kgm
|
|
price_unit: 50.0
|
|
name: 'FIFO Ice Cream'
|
|
-
|
|
Check the standard price should not have changed
|
|
-
|
|
!python {model: product.product}: |
|
|
assert self.browse(cr, uid, ref("product_fifo_icecream")).standard_price == 70.0, 'Standard price as fifo price of second reception incorrect!'
|
|
-
|
|
Let us send some goods
|
|
-
|
|
!record {model: stock.picking, id: outgoing_fifo_shipment}:
|
|
type: out
|
|
-
|
|
Picking needs movement from stock
|
|
-
|
|
!record {model: stock.move, id: outgoing_shipment_fifo_icecream}:
|
|
picking_id: outgoing_fifo_shipment
|
|
product_id: product_fifo_icecream
|
|
product_uom: product.product_uom_kgm
|
|
product_qty: 20.0
|
|
type: out
|
|
-
|
|
I confirm outgoing shipment of 20 kg of FIFO Ice Cream.
|
|
-
|
|
!workflow {model: stock.picking, action: button_confirm, ref: outgoing_fifo_shipment}
|
|
-
|
|
Process the delivery of the outgoing shipment
|
|
-
|
|
!python {model: stock.partial.picking}: |
|
|
partial_id = self.create(cr, uid, {}, context={'active_model': 'stock.picking','active_ids': [ref("outgoing_fifo_shipment")], 'default_type':'out'})
|
|
self.do_partial(cr, uid, [partial_id])
|
|
-
|
|
Check 2 stock move matchings were created
|
|
-
|
|
!python {model: stock.picking}: |
|
|
assert len(self.browse(cr, uid, ref("outgoing_fifo_shipment")).move_lines[0].matching_ids_out) == 2, "It should have created 2 "
|
|
-
|
|
Check product standard price changed to 65.0
|
|
-
|
|
!python {model: product.product}: |
|
|
assert self.browse(cr, uid, ref("product_fifo_icecream")).standard_price == 65.0
|
|
-
|
|
Do a delivery of an extra 500 g (delivery order)
|
|
-
|
|
!record {model: stock.picking, id: outgoing_fifo_shipment_uom}:
|
|
type: out
|
|
-
|
|
Picking needs movement from stock
|
|
-
|
|
!record {model: stock.move, id: outgoing_shipment_fifo_icecream_gram}:
|
|
picking_id: outgoing_fifo_shipment_uom
|
|
product_id: product_fifo_icecream
|
|
product_uom: product.product_uom_gram
|
|
product_qty: 500.0
|
|
type: out
|
|
-
|
|
I confirm outgoing shipment of 500g of FIFO Ice Cream.
|
|
-
|
|
!workflow {model: stock.picking, action: button_confirm, ref: outgoing_fifo_shipment_uom}
|
|
-
|
|
Process the delivery of the outgoing shipment
|
|
-
|
|
!python {model: stock.partial.picking}: |
|
|
partial_id = self.create(cr, uid, {}, context={'active_model': 'stock.picking','active_ids': [ref("outgoing_fifo_shipment_uom")], 'default_type':'out'})
|
|
self.do_partial(cr, uid, [partial_id])
|
|
-
|
|
Check 1 stock move matching was created
|
|
-
|
|
!python {model: stock.picking}: |
|
|
assert len(self.browse(cr, uid, ref("outgoing_fifo_shipment_uom")).move_lines[0].matching_ids_out) == 1, 'Should have created 1 matching'
|
|
-
|
|
Check product price changed to 80.0
|
|
-
|
|
!python {model: product.product}: |
|
|
assert self.browse(cr, uid, ref("product_fifo_icecream")).standard_price == 80.0
|
|
-
|
|
Create new pricelist in usd
|
|
-
|
|
!record {model: product.pricelist, id: supplier_pricelist_usd}:
|
|
name: Supplier Pricelist
|
|
type: purchase
|
|
currency_id: base.USD
|
|
version_id:
|
|
- name: v1.0
|
|
items_id:
|
|
- name: First version
|
|
sequence: 1
|
|
price_min_margin: 2
|
|
price_max_margin: 5
|
|
product_id: product_fifo_icecream
|
|
base: -2
|
|
-
|
|
Purchase order in usd
|
|
-
|
|
I create a draft Purchase Order for 30000 g at 0.150 USD/g and 10 kg at 150 USD/kg
|
|
-
|
|
!record {model: purchase.order, id: purchase_order_fifo_usd}:
|
|
partner_id: base.res_partner_3
|
|
location_id: stock.stock_location_stock
|
|
pricelist_id: supplier_pricelist_usd
|
|
order_line:
|
|
- product_id: product_fifo_icecream
|
|
product_qty: 30000
|
|
product_uom: product.product_uom_gram
|
|
price_unit: 0.150
|
|
name: 'FIFO Ice Cream'
|
|
- product_id: product_fifo_icecream
|
|
product_qty: 10.0
|
|
product_uom: product.product_uom_kgm
|
|
price_unit: 150.0
|
|
-
|
|
I confirm the purchase order in USD
|
|
-
|
|
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_fifo_usd}
|
|
-
|
|
Process the reception of purchase order with usd
|
|
-
|
|
!python {model: stock.partial.picking}: |
|
|
pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_fifo_usd")).picking_ids
|
|
partial_id = self.create(cr, uid, {}, context={'active_model': 'stock.picking','active_ids': [pick_ids[0].id]})
|
|
self.do_partial(cr, uid, [partial_id])
|
|
-
|
|
We create delivery order of 49.5 kg
|
|
-
|
|
!record {model: stock.picking, id: outgoing_fifo_shipment_cur}:
|
|
type: out
|
|
-
|
|
Picking needs movement from stock
|
|
-
|
|
!record {model: stock.move, id: outgoing_shipment_fifo_icecream_cur}:
|
|
picking_id: outgoing_fifo_shipment_cur
|
|
product_id: product_fifo_icecream
|
|
product_uom: product.product_uom_kgm
|
|
product_qty: 49.5
|
|
type: out
|
|
-
|
|
Process the delivery of the outgoing shipment
|
|
-
|
|
!python {model: stock.partial.picking}: |
|
|
partial_id = self.create(cr, uid, {}, context={'active_model': 'stock.picking','active_ids': [ref("outgoing_fifo_shipment_cur")], 'default_type':'out'})
|
|
self.do_partial(cr, uid, [partial_id])
|
|
-
|
|
Check rounded price is 102 euro
|
|
-
|
|
!python {model: product.product}: |
|
|
assert round(self.browse(cr, uid, ref("product_fifo_icecream")).standard_price) == 102
|
|
-
|
|
Do a delivery of an extra 10 kg
|
|
-
|
|
!record {model: stock.picking, id: outgoing_fifo_shipment_ret}:
|
|
type: out
|
|
-
|
|
Picking needs movement from stock
|
|
-
|
|
!record {model: stock.move, id: outgoing_shipment_fifo_icecream_ret}:
|
|
picking_id: outgoing_fifo_shipment_ret
|
|
product_id: product_fifo_icecream
|
|
product_uom: product.product_uom_kgm
|
|
product_qty: 10.0
|
|
type: out
|
|
-
|
|
I confirm outgoing shipment of 10 kg of FIFO Ice Cream.
|
|
-
|
|
!workflow {model: stock.picking, action: button_confirm, ref: outgoing_fifo_shipment_ret}
|
|
-
|
|
Process the delivery of the outgoing shipment
|
|
-
|
|
!python {model: stock.partial.picking}: |
|
|
partial_id = self.create(cr, uid, {}, context={'active_model': 'stock.picking','active_ids': [ref("outgoing_fifo_shipment_ret")], 'default_type':'out'})
|
|
self.do_partial(cr, uid, [partial_id])
|
|
-
|
|
Check rounded price is 150.0 / 1.2834
|
|
-
|
|
!python {model: product.product}: |
|
|
assert round(self.browse(cr, uid, ref("product_fifo_icecream")).standard_price) == round(150.0 / 1.2834)
|
|
-
|
|
Let us create some outs to get negative stock. Create outpicking. We create delivery order of 200 kg, but will pick only 100 kg
|
|
-
|
|
!record {model: stock.picking, id: outgoing_fifo_shipment_neg}:
|
|
type: out
|
|
-
|
|
Picking needs movement from stock
|
|
-
|
|
!record {model: stock.move, id: outgoing_shipment_fifo_icecream_neg}:
|
|
picking_id: outgoing_fifo_shipment_neg
|
|
product_id: product_fifo_icecream
|
|
product_uom: product.product_uom_kgm
|
|
product_qty: 200.0
|
|
type: out
|
|
-
|
|
Let us create another out of 400 kg, but will pick only 50 kg
|
|
-
|
|
!record {model: stock.picking, id: outgoing_fifo_shipment_neg2}:
|
|
type: out
|
|
-
|
|
Picking needs movement from stock
|
|
-
|
|
!record {model: stock.move, id: outgoing_shipment_fifo_icecream_neg2}:
|
|
picking_id: outgoing_fifo_shipment_neg2
|
|
product_id: product_fifo_icecream
|
|
product_uom: product.product_uom_kgm
|
|
product_qty: 400.0
|
|
type: out
|
|
-
|
|
Process the delivery of the outgoing shipments
|
|
-
|
|
!python {model: stock.partial.picking}: |
|
|
partial_id = self.create(cr, uid, {}, context={'active_model': 'stock.picking','active_ids': [ref("outgoing_fifo_shipment_neg")], 'default_type':'out'})
|
|
line = self.browse(cr, uid, partial_id, context=context).move_ids[0]
|
|
self.pool.get("stock.partial.picking.line").write(cr, uid, [line.id], {'quantity':100})
|
|
self.do_partial(cr, uid, [partial_id])
|
|
partial_id = self.create(cr, uid, {}, context={'active_model': 'stock.picking','active_ids': [ref("outgoing_fifo_shipment_neg2")], 'default_type':'out'})
|
|
line = self.browse(cr, uid, partial_id, context=context).move_ids[0]
|
|
self.pool.get("stock.partial.picking.line").write(cr, uid, [line.id], {'quantity':50})
|
|
self.do_partial(cr, uid, [partial_id])
|
|
-
|
|
Receive purchase order with 50 kg FIFO Ice Cream at 50 euro/kg
|
|
-
|
|
!record {model: purchase.order, id: purchase_order_fifo_neg}:
|
|
partner_id: base.res_partner_3
|
|
location_id: stock.stock_location_stock
|
|
pricelist_id: 1
|
|
order_line:
|
|
- product_id: product_fifo_icecream
|
|
product_qty: 50.0
|
|
product_uom: product.product_uom_categ_kgm
|
|
price_unit: 50.0
|
|
name: 'FIFO Ice Cream'
|
|
-
|
|
I confirm the first purchase order
|
|
-
|
|
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_fifo_neg}
|
|
-
|
|
Process the reception of purchase order 1
|
|
-
|
|
!python {model: stock.partial.picking}: |
|
|
pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_fifo_neg")).picking_ids
|
|
partial_id = self.create(cr, uid, {}, context={'active_model': 'stock.picking','active_ids': [pick_ids[0].id]})
|
|
self.do_partial(cr, uid, [partial_id])
|
|
-
|
|
Assert price on product is still the old price as the out move has not been received fully yet
|
|
-
|
|
!python {model: product.product}: |
|
|
assert round(self.browse(cr, uid, ref("product_fifo_icecream")).standard_price) == round(150.0 / 1.2834)
|
|
-
|
|
Receive purchase order with 60 kg FIFO Ice Cream at 80 euro/kg
|
|
-
|
|
!record {model: purchase.order, id: purchase_order_fifo_neg2}:
|
|
partner_id: base.res_partner_3
|
|
location_id: stock.stock_location_stock
|
|
pricelist_id: 1
|
|
order_line:
|
|
- product_id: product_fifo_icecream
|
|
product_qty: 60.0
|
|
product_uom: product.product_uom_categ_kgm
|
|
price_unit: 80
|
|
name: 'FIFO Ice Cream'
|
|
-
|
|
I confirm the second negative purchase order
|
|
-
|
|
!workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_fifo_neg2}
|
|
-
|
|
Process the reception of purchase order 2
|
|
-
|
|
!python {model: stock.partial.picking}: |
|
|
pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_fifo_neg2")).picking_ids
|
|
partial_id = self.create(cr, uid, {}, context={'active_model': 'stock.picking','active_ids': [pick_ids[0].id]})
|
|
self.do_partial(cr, uid, [partial_id])
|
|
-
|
|
The price of the product should have changed back to 65.0
|
|
-
|
|
!python {model: product.product}: |
|
|
assert self.browse(cr, uid, ref("product_fifo_icecream")).standard_price == 65.0
|
|
-
|
|
Check Stock Valuation Report view, check first purchase order line corresponds with first outgoing line
|
|
-
|
|
!python {model: report.stock.valuation}: |
|
|
pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_fifo1")).picking_ids
|
|
original_move = pick_ids[0].name
|
|
pick_compare = self.pool.get("stock.picking").browse(cr, uid, ref("outgoing_fifo_shipment")).name
|
|
ids = self.search(cr, uid, [('product_id', '=', ref("product_fifo_icecream")), ('product_qty', '=', -10.0), ('value', '=', -500.0),
|
|
('related_move_in', '=', original_move), ('name', '=', pick_compare)])
|
|
assert len(ids) == 1, 'Could not find the correct line in the report'
|
|
-
|
|
Check Stock Inventory Report view if it shows the correct value of the stock
|
|
-
|
|
!python {model: report.stock.inventory}: |
|
|
print self.pool.get("product.product").browse(cr, uid, ref("product_fifo_icecream")).qty_available
|
|
ids = self.search(cr, uid, [('product_id', '=', ref("product_fifo_icecream")), ("state", "=", "done"), ("product_qty", ">", 0.0)])
|
|
for line in self.browse(cr, uid, ids):
|
|
print line.product_qty, line.value, line.location_src_type, line.location_dest_type, line.state, line.ref
|
|
assert len(ids) == 0, 'No lines should be visible in the stock inventory' |