Openerp WMS: Draft Proposal To Clean Existing Openerp Models - V8 Work in Progress..

Download as pdf or txt
Download as pdf or txt
You are on page 1of 51

OpenERP WMS

Draft proposal to clean existing OpenERP models - v8

Work in Progress...

 
This analysis is a collaborative effort between ​
Camptocamp​
 and​
 OpenERP SA​

 
 
Legend: 
● Pending Questions/Issues 
● Something has to be developed 
 
1. Introduction 
List of Concepts 
2. Analysis of Concepts 
2.1 Routing of Products: Stock Movements 
2.1.1 Concepts Explained 
2.1.1.1 Stock movements: stock.move 
2.1.1.2 Push rules: 
2.1.1.3 Pull rules: 
2.1.1.4 Notes on Pull and Push rules 
2.1.1.5 Removal strategies 
2.1.1.6 Put away strategies 
2.1.1.7 Routes 
2.1.1.8 Cancellation of an operation in a chain 
2.1.1.9 Change of quantities in a chain 
2.1.1.10 Procurement Group 
2.1.1.11 Impact on pickings 
2.1.2 Use cases 
2.1.2.1 Incoming Shipments, with input = stock 
2.1.2.2a Incoming shipments with input != stock 
2.1.2.2b Reception with a purchase order coming from a procurement on 
stock 
2.1.2.3 Simple outgoing shipments (ship only) 
2.1.2.4 Outgoing shipments (pack + ship) 
2.1.2.5 Outgoing with pick → pack → ship 
2.1.2.6: Sale → Purchase and MTO (drop shipping) 
2.2 Pickings 
2.2.1 Concept explained 
2.2.1.1 Introduction to pickings 
2.2.1.2 Picking and push rules 
2.2.1.3 Picking and pull rules 
2.2.2 Use Cases 
2.2.2.1: Cross­Docking 

1/51 
Aside Notes on Pegging strategy 
2.2.2.2: routing at reception 
2.3 Picking Waves 
2.3.1 Concept of picking wave 
2.3.2 Use Cases 
2.3.2.1 Batch picking 
2.3.2.2. Wave Picking 
2.3.2.3 Trip assignation 
2.4 Quants 
2.4.1 Concept Explained 
2.4.1.2 Consumables vs Stockable products 
2.4.2 Use Cases 
2.4.2.1 examples of some moves 
2.4.2.2 How is it used in lots management 
2.4.2.3 How is it used in FIFO 
2.4.2.5: negative stocks 
2.4.2.7 Impact on performance 
2.4.3 Separation of concepts 
2.5 Lots Management 
2.6 Packings 
Data Model: packaging 
Removal Strategies 
Packing in stock.picking 
Some notes on the interface 
Examples 
Use case 1: reception 
Use case 2: Pick 
Use Case 3: pack 
Use Case 4: Ship 
Use Case 5: Partial Pick 
Viewing a pack (stock.quant.pack) 
Pack (stock.quant.pack) and putaway strategies 
2.7 Real Time Costing 
2.7.1 Basics 
2.7.1.1 ‘Standard Price’ costing method 
2.7.1.2 ‘Average Price’ costing method 
2.7.1.2 ‘Real Costs’ costing method (FIFO, LIFO) 
2.7.2 Stock valuation reconciliation 
2.7.3 Landed costs 
2.7.4 Anglo saxon accounting 
2.7.5 Stock Ownership 
2.7.6 Implementation 
2.8 Multi­Company 
2.8.1 Explanation of the current problem 
2.8.2 Things to do to in order to solve this problem 
2.9 Burst Process 

2/51 
2.10 Dates Management 
2.11 Replenishment strategy 
2.12 KPI 
2.13 Purchase Order Workflow and Procurements 
Use Case: Reception → Quality Control → Stock (pull) 
Modularity 
List of Corner cases to take care of 
Negative Quants 
Identified Issues 
Misc points 
Raised points to include in the doc 
 
 

3/51 
1. Introduction
 

List of Concepts
 
● Put Away Strategies 
● Removal Strategies 
● Push Rules 
● Pull Rules 
● Cross­Dock 
● Picking 
● Packing 
● Procurements 
● Stock Moves 
● Routes 
● Batch Picking 
● Wave Picking 
● Quants 
● FIFO 
 

2. Analysis of Concepts
 

2.1 Routing of Products: Stock Movements


 

2.1.1 Concepts Explained


 
2.1.1.1 Stock movements: stock.move
 
Stock  movements  are  represented  by the stock.move object and represent a transfer from 
one  location  source  to  a  destination  location.  All  movements  are  generated  in  advance 
because  it  is  what  allows  to  compute  virtual  stocks. (and, thus, trigger correct orderpoints, 
…) 
 
A stock.move has the following status: 
● Draft​ :​
 the stock move is uncertain, nothing has been planned yet 
● Confirmed​ :  the  stock  move  has  to be  done  (it  is  confirmed  that we will move  these 
products), but we did not identified the exact products (serial number) yet. 
● Waiting​ :  the  stock  move  is  linked  to  another  one  (usually  after  a  MTO)  and it  will 
become assigned only when the preceding one will be done.  
e.g: supplier → input → stock 
(in this case the move input → stock is linked to the move supplier → input) 
● Assigned​ :  the  product  is  reserved  (identified)  and  the  exact  locations  are  known 

4/51 
(source and destination) 
● Done​:​
 the stock move has been done (products have been moved) 
 
 
This concept already exists in OpenERP. 
 
 
2.1.1.2 Push rules:
 
A rule that trigger another stock.move based on a stock.move.  
 
● Example​ :   When  products  arrive  in  “Input”  location,  you  want   to  move  them  to 
“stock”  directly  with  a  push rule (this example intentionally simplifies the flow  by not 
taking eventual quality checks into account) 
 
So,   when  a  stock.move  “Supplier  →  Input”  is  ​ confirmed,  ​ this  rule  will  create  another 
stock.move:  “Input  →  Stock”.  It  allows  3  mode:  automatic  (the  second  operation  will  be 
validated  automatically),  manual  (the  second  operation  must  be  validated  manually), 
manual  no  step  added.  (the  destination   of  the  first  move  is   replaced  instead  of  creating 
another stock.move. 
 
Push rules can be defined on products or locations (or combinations of both). 
 
When  several   push  rules  are  triggered  at  the  same   time  (by  action_confirm  on 
stock.picking),  we  must  be  sure  that  all  chained  moves  that  have  the  same  destination 
location are grouped in the same picking. (according to group concept explained later) 
 
This concept already exists in OpenERP. 
 
 

2.1.1.3 Pull rules:


 
Pull  rules  are  not  the  opposite of push rules! It’s  very different as push rules impact moves 
and pull rules impact needs. (procurements) 
 
A  pull  rule  trigger  a  procurement  on  the  source location when a stock.move is ​ confirmed​. 
This  procurement   will  fulfill  products  at  the  source  location  through  different  ways  (move 
products from another location, purchase, produce) 
 
● Example​ :  When  there  exists  a pull  rule saying that products have to move from the 
“pick”  zone  to  the “pack”  zone,  the  system  creates  a  procurement  at  the pick zone 
for these products. This procurement will then move products from stock to pick. 
 
Pull are defined on products, depending on the location. 
 

5/51 
This  concept  already  exists  in  OpenERP  but  we  should  also  add  the  concept  of  group  of 
picking 
 
2.1.1.4 Notes on Pull and Push rules
 
1. Neither  the  pull  nor  the  push  rules  propagate  a  change  in  the  quantity  on  a  stock 
move 
 
Example​ :   i  ordered  5  products  to  a  supplier  and  have  a  manual  push  rule  from  input  to 
stock, in the system. I have the given chained stock moves: supplier → input → stock  
 
Given  that  i   see  there  is  a  broken  piece  in  the  incoming  shipment  when  i  receive  the 
products, I have 2 possibilities: 
1°)  i  make  the  partial  reception  and  it  creates  a  backorder  for  the  remaining  product.  The 
next  chained  move  stays  in  ‘Waiting’  while  all  backorders  are  not  ‘Done’.  This  is  the 
current behavior. 
 
2°)  i  want  to  accept  the  current  reception  fully  so  that  the  rest  of  the  flow  can  proceed 
further  without  waiting for  a  new  shipment from my supplier, if i change  my  quantity on the 
initial stock move (supplier → input) it won’t be propagated.  
 
In   this  second  case,  the  behavior  is  normal  because  imagine  you  were  doing 
cross­docking  operation and forwarding the goods to the client directly (supplier → input → 
output  →  customer): you  certainly don’t want to automatically deliver your customer all but 
one  product,  as you may have another product from stock to  replace the missing one. This 
case  is  an exception in the logistics flow and must be treated manually (as does OpenERP 
for all exception cases). 
 
There  are  scenario where  we want  to  propagate  changes  in  quantities  and  split  of moves 
(reception)  and  others  where  we  don’t  want  to propagate (picking → packing or picking → 
mo). 
 
We   should  probably  define  on  the  stock.move   if  we  propagate  changes  or  not.  This  is 
probably   linked  to  the  existing  feature:  propagate  cancel  of  moves. ​ So,  we  should  reuse 
and extend this to propagate split and quantity changed, not only cancellation. 
 
Remark​ :  Currently,  we  have  cancel_cascade  on  moves,  but  this  can  only  be triggered  by 
pull  moves   (it  is  False   for  push  moves).  The  problem  with  the  pull  rules  is  that  the 
cancellation  advances  forward, while  it  should  advance  in  the  backwards  direction.  (=> if 
you  cancel  a  picking,  it  will cancel the delivery order, but if  you cancel the delivery order, it 
won’t cancel the picking and it should be the other way around) 
 
2. Chained moves propagate the quant (and thus the lot number) 
 
Chained  locations  propagate  the  quants.  Both  push  and  pull rules chain locations. So, the 
lot number (which is referenced on the quant) is propagated for both push and pull rules. 
6/51 
 
When  a   stock.move  is  done,  the  quant  is  selected  (if  not  provided  manually)  and,  by 
default, it reuses the quant of the preceding chained move.  
 
 
3. Push/Pull rules aren’t new but may need to be improved 
 
To add some flexibility, power … for example it may be interesting to  
● add  the  possibility  to  define  a  push/pull  rule  from  a  product  category  (means  we 
chose  the  rule  to  apply/create  at  category  level,  and  the  product  aggregates  the 
rules from his categories (recursively)) . 
● Push/pull rules should also work on a product attribute 
○ A Further deeper analysis will cover this point. (TODO) 
 
 
4. (We may need to add a big picture of pull/push rules) 
 
We  think  that  it  may  be  interesting  to  show  in  a  clear  way  all routes defined in the system 
as pull/push rules, ideally in the form of a diagram view. 
 
We   need  a  related  button  on  the  product  form  that  opens  all  push/pull  rules  that  may 
impact  this   product.  (from  the  product,  it’s  category,  rules  on  locations,  …)  This  list  view 
can be converted into a diagram view to see it graphically. 
 
This isn’t necessary at all and can come at last. I let it here for the record only 
 
 
5. Pull rules doesn’t seem to work with non stockable products.  
 
There  exists   a  bug  currently  to  fix:  pull  rules  aren’t  working  with  non  stockable  products 
(maybe only in MTS, not sure) 
 

2.1.1.5 Removal strategies


 
When  a   stock.move  goes  from  “confirmed”  to  “assigned”,  OpenERP’s  warehouse  tries to 
find  available  products  that  can  be  assigned  to  this  move. The  way OpenERP finds these 
products should depend on the “removal strategy” that is defined on the product. 
 
As an example, if you have the following location structure: 
 
● Stock 
○ Area 1:  3 Computers 
○ Area 2:  4 Computers 
○ Area 3:  0 Computers 
 
If you create the following confirmed stock.move: 
7/51 
● 5 PC: Stock → Ouput (confirmed) 
 
When you will assign the stock.move it will be splitted into: 
● 3 PC: Stock / Area 1 → Output (assigned) 
● 2 PC: Stock / Area 2 → Output (assigned) 
 
Removal  strategies are usually used in picking operations  to select the best products while 
optimizing the distance for the worker. 
 
Note that a “waiting” move is automatically converted into “assigned” without going through 
removal  strategies  when  the  linked  move  is  done.  (because  the  source  is  the one  of  the 
linked move, no need to compute anything). 
 
This  concept  already  exists  in  OpenERP,  but  only  one  strategy  is  implemented:  “Nearest 
available  products”.  (actually  it  seems  wrong:  Lowest  ID  goes  first  →  I  think  it’s  lowest  ID 
in nearest available based on order of locations; to be checked) 
 
We   need  to  allow  easy  hacking  to  add  new  selection  methods  like  ‘by  expiry  date’  and 
allow the stock manager to select the removal strategy per product or product category). 
 
The  removal  strategies  must  be  defined  on  locations,  and  one  of  the  removal  strategy  is 
“use  removal   strategy  from  product”  (actually  it’s  the  default  value).  Thus,   the  removal 
strategy  can  be  defined  at  the  product  or  product/category  level,  but  the  removal strategy 
from the location has precedence. 
● By default the removal strategy is on the product category 
● If  nothing   is  specified  in  product  category,  it  comes  from  the   location  (depending 
obn the category) 
● If nothing is on the location, it has no removal strategy 
 
Type of removal strategy: 
● FIFO  
● LIFO 
● Nearest goes first (regarding location) 
● Regarding the packaging of the product (to avoid repacking) 
● expiry date (FEFO), etc. 
 
Important:  in v7, the removal strategy may imply to split a stock.move → this should not be 
the  case   anymore  as  the  split  is  done  at  the  quant  level.  Destination  locations  are  not 
changed on the stock.move but set on the quant. 
 
For the first implementation, we plan to only implement fifo and lifo. 
 

2.1.1.6 Put away strategies


 
Same  principle  as  removal  strategies,  but  affect  the  destination  location  of a  stock.move. 
It’s  usually  used  when  receiving  products  to  store  them  at  the  right location  according  to 
8/51 
different strategies. 
 
Unlike the Removal strategies, the putaway strategies are used in case of chained move. 
 
Put  away  strategies are defined at the location  level.  (not like removal strategies which are 
defined at the product level). 
 
We   need  to  a  “Prefered  Locations”  object  linked  to  the  stock.move  where  entries  are 
created when the stock.move is assigned: 
● location_id 
● quantity 
 
The quant creation should be created using the “Prefered Locations” and Lots if possible. 
 
This concept does not exists in OpenERP. 
 
 

2.1.1.7 Routes
 
A  route  is  a  set  of  rules  (push  and/or  pull).  On  products   and   categories  of  products,  we 
assign routes (many2many_tags), not directly push/pulll rules. 
 
The  worst  of  the  push/pull  rules  today  are  the  configuration  of  them.  Very difficult  to  set 
and  manage  a  large  quantity  of  product  and  be  sure  that  everyone  has  the  proper  rules. 
Route will allow to easily reuse a set of rules. 
 
Routes   for  basic  configurations  could  also  be   defined  by  default  to  help  the  setup  of  
warehouses flows. (this shouldn’t be done at first) 
 
This  concept  does  not  exists  in  OpenERP  and  need  to  be  developped:  a  route  is  just  a 
name,  and  2  many2many  fields:  one  containing  all  the  push  rules  of  the  route,  the  other 
one all the pull rules of the route. 
 
 

2.1.1.8 Cancellation of an operation in a chain


 
The current OpenERP approach is good: 
● Stock → Picking → Pack → Delivery Order 
 
If you cancel the operation Stock → Picking, OpenERP broke the chain and you get: 
● Cancelled: Stock → Picking 
● Confirmed (instead of waiting): picking → pack 
● Waiting: PAck → Delivery Order 
 
Moreover,   OpenERP  creates  a  procurement  (MTS)  linked  to  the  confirmed  move,  at  the 

9/51 
pick  location.   OpenERP  also  supports  to  propagate  cancellation.  So,  we  will  need  to 
configure pull/push rules accordingly: 
● input → stock (propagate) 
● pick → pack (do not propagate) 
● pack → delivery (propagate) 
● input → crossdock (propagate) 
 
This  feature  already  exists  in  OpenERP  but  should  be   extended  to  also  propagate 
changes in quantities and split of stock.move. 
 
 

2.1.1.9 Change of quantities in a chain


 
See  point  just above: we  need  to  extend  the  “propagate cancel” feature to also propagate 
changes in quantities and split.. 
 
 

2.1.1.10 Procurement Group


 
We   need  a  new  object  to  group  procurements  together  when  created  in  the  same  time 
(from  a  SO,  from  an  orderpoint,  from  a  MRP  order...)  if  the  source  and  destination 
locations and the partner are the same. It will allow to make  only one PO to a supplier if we 
need  to  buy  him  different  products  for  the  same  SO.  Currently  one  PO  per  product would 
have been made. 
 
This  object  (procurement.group)  is  just  a many2one on procurements that has only 1 field: 
name   which  is  a  sequence.  It  will  be  very  useful  as  it  will  allow  to  group  together  all  the 
procurements triggered by a SO. 
 
Each new SO, or MRP order creates a new procurement group.  
 
On  pull  rules  and  orderpoints,  men  can  give  a  procurement.group  to  use.  If  nothing  is 
given,  it   just  propagate  previous  (if  any).  →  object:  stock.move.group,  not  procurement 
group for the name of the object. 
 
This concept is totally new. 
 

2.1.1.11 Impact on pickings


 
In OpenERP v7, all documents produced pickings that produced stock.moves. So, it was 
the picking’s workflow that ‘controlled’ the stock.move. In OpenERP v8, the key concept 
becomes the stock.move, not the picking. 
 
So, we propose to remove the workflow of the picking and replace the state field on the 

10/51 
picking by a function field computed based on its related stock.move. This will have 
several impacts: 
● change the way purchases monitor receptions (listen to stock.move, not picking) 
● change everything that was related to the picking workflow (mrp.production, 
repairs, …) 
 

2.1.2 Use cases


2.1.2.1 Incoming Shipments, with input = stock
 
In   case  of  warehouses  where  the  incoming  shipments  are  received  and  placed  in  stock 
immediately, in one operation. (small companies without a complex warehouse) 
 
Configuration: 
● In locations, you just have “stock”, no input 
● On the warehouse, you have “input location” equals to stock 
 
The steps: 
● When the purchase order is validated, a stock.move is created (in state: confirmed) 

Confirmed: Supplier  Stock 
 
● When  we  change  the  state  of  the  stock.move  to  assigned,  a  put  away  rule  will 
select  the  right  destination  location  within  children  location  of “stock” according to 
the put away strategy. 

Assigned: Supplier  Stock \ Bin A 
 
(*) = Put Away strategy 
 
To develop: 
● Implement  put  away  strategies  to  select  the  right  location  according  to  different 
criteria: location capacities, complete existing bin with same product, … 
 
● Purchase  orders  should  create  stock.move,  in  “​ confirmed​ ”  state,  not  in  assigned 
state.  (because  the  destination  (using  put   away   strategy)  has  to  be  done  when 
receiving the products, not when confirming the purchase) 
 
Note  that  this  can  be  managed  with  push  rules  (with  no  step  added) for  very  simple rules 
(this product goes into this location). 
 
 
2.1.2.2a Incoming shipments with input != stock
 
Scenario with: 

11/51 
● Purchase order recorded manually 
● incoming  shipment  is  received  on  an  input  location  first  (e.g.  at  the docks)  before 
the goods go to a specific location in the stock.   
 
Configuration: 
● Location Structure: 
○ Warehouse 
■ Input (quai de déchargement) 
■ Stock 
● On the warehouse, you have “input location” equals to “Input” 
 
The steps: 
● When the purchase order is validated, a stock.move is created (in state: confirmed) 

Confirmed: Supplier  Input 
 
● This  stock.move  triggers  a  push  rule  (input  →  Stock)  that  creates  the  following 
move: 

Waiting: Input  Stock 
 
● At  the  product  reception,  we  execute  the  first  move  and  assign  the second  move, 
we get: 

Done: Supplier   Input 

Assigned: Input  Stock \ Bin A 
 
(*) Put Away strategy 
 
The  user  can  also  change  the  destination  manually,  selecting another destination location 
(e.g. bin) on the document. 
 
2.1.2.2b Reception with a purchase order coming from a procurement on stock
 
A procurement on stock should trigger: 
 
● Pull rule 1: move: Input → Stock (MTO) 
● Pull rule 2: po: supplier → input 
 
To develop: 
● Nothing more than previous use case 
 
This  means  we  need  to  create  3  rules  to  handle  reception  through  an  input  lnput location  
(one for manual orders (push) and two from pulled flows) 

12/51 
 
 

2.1.2.3 Simple outgoing shipments (ship only)


 
In  case  of  simple  warehouses  like  Use  Case  1.  The  goods  are  sent from a specific stock 
location immediately to the customer.   
 
Configuration: 
● In locations, you just have “stock”, no output/input 
● On the warehouse, you have “output location” equals to stock 
 
The steps:  
● When the sales order is validated, a stock move is created:  

Confirmed: Stock Customer 
 
● When we assign it, we get:  

Assigned: Stock  Customer 
 
(*) Removal Strategy 
 
To develop:  
● Need to implement other removal strategies than nearest first 
● Split when stock comes from different sub­locations (see below) 

2.1.2.4 Outgoing shipments (pack + ship)


 
In   case  of  warehouses  like  Use  Case  2.  The  goods  are  brought together on  the  Output 
location before being sent to the Customer.   
 
Configuration: 
● Location Structure: 
○ Warehouse 
■ Packing Zone 
■ Output (quai de chargement) 
■ Stock 
● On the warehouse, you have “output location” equals to “Output” 
 
Steps: 
● A sales order generates a delivery order and a need at the customer 

Confirmed: Output Customer 
 

13/51 
● The  pull  rules  will   generate  a  move  from  packing  zone  to  output  and  another  one 
from stock to packing zone, both chained together. 

Waiting: Packing  Zone  Output 

Waiting: Stock  Packing Zone 
 
● When  the  second  move  becomes  assigned,  it  selects  the  right  sub­location  of 
stock: 

Waiting: Packing  Zone  Output 

Assigned: Stock / Bin A  Packing Zone 
(*) Removal strategy 
 
● Whenever  the  second stock move  gets done, the stock move from packing zone to 
output becomes assigned: 

Assigned: Packing  Zone  Output 

Done: Stock / Bin A  Packing Zone 
(*) Removal strategy 

2.1.2.5 Outgoing with pick → pack → ship


 
In   case  of  a  situation  with  picking  ,  we  can  have  multiple  pulls  or  orderpoints  after  each 
other.  
 
Configuration:  
● Location Structure: 
○ Warehouse 
■ Output (loading dock) (several sublocations) 
■ Stock (several sublocations) 
■ Picked: where you put goods before being packed (= pack in) 
■ Packed: where you put the packed goods (= pack out) 
● On the warehouse, you have “output location” equals to “Output” 
 
Steps: 
● A  validated  sales  order  generates  a  delivery  order  and  the  Output  location  in  turn 
has a pull rule from packed which has a pull rule from Picked 
 

Waiting: Stock  Picked  Packed 

14/51 
Output  Customer 
 
Pull1  :   Does   not  need  to  be  a  pull  rule  itself   from   Stock  to   Picked.  It  can  be 
triggered  by  an  orderpoint  instead  which  can  make  sure  the  packer  has enough to 
pack, but does not lead to an uncluttered pack of goods next to the packer.  
Pull2: Packed pulls from Picking 
Pull3: Output pulls from Packed 
 
● When  we  execute  the  flow, all the pickings get towards assigned/done.  When they 
get  assigned,  they  could  get  a  different  location  because  of Put Away (or Removal 
Strategies only on first move):  
 

Stock / Bin B  Picked  Packed 

           Output / Gate A  Customer 


 
In  this example, the location Stock / Bin B is decided by a removal  strategy, and the 
Output  /  Gate  A  is  decided  by  a  putaway  strategy   (but  it  could  also  be  manually 
chosen):  it finds an appropriate child location of the destination, not at the source of 
the move.   

2.1.2.6: Sale → Purchase and MTO (drop shipping)


 
The sale order in v7 creates: 
● a stock.picking 
● stock.move related to products sold 
● a procurement for every product 
 
We  should  change  sales  order  so that they just  generate a procurement (on the Customer 
location)  and  not  the  Stock  →  Customer  moves.  The  procurement  will  trigger  the picking 
and stock → Customer moves. 
 
This would: 
● reduce code (just create procurement, not picking and moves) 
● allow drop­shipping (from supplier to customer, without going through the stock) 
 
 
 
   

15/51 
2.2 Pickings
2.2.1 Concept explained

2.2.1.1 Introduction to pickings


 
A  picking  in  OpenERP  is  a  list  of  stock.move.  It  does  not  only  reflect  the  “picking” 
operation   but  every  operation  that  moves  products:   receptions,  delivery  order,  internal 
move, … 
 
Pickings are created from different ways: 
● Sale order (delivery order to the customer) 
● Purchase order (reception) 
● Manufacturing Order (pick des matières premières) 
● Manually 
 

2.2.1.2 Picking and push rules


 
When  checking  push rules on a processed picking,   we may have different push rules fired 
(by  product)  and  at  that  time  ​ OpenERP  groups  the  chained  operations  together  in  a 
picking  if  they  share  the same destination and source location, and the same procurement 
group​ .   (not  that  this  is  evaluated  before  putaway  strategies  apply  as  they  apply  only  at 
assignation). 
 
So, if you have this picking INTERNAL/001: 
● 5 Computers: stock → pick 
● 2 Mouses: stock → pick 
● 1 Keyboard: stock → pick 
 
If  you  have a push rule on pick location (pick → pack) and one on the pick location specific 
to the product keyboard (pick → pack2). The push rules will create two picking: 
 
INTERNAL/002: 
● 5 Computers: pick → pack 
● 2 Mouses: pick → pack 
INTERNAL/003 
● 1 Keyboard: pick → pack2 
 
2.2.1.3 Picking and pull rules
 
same than for push​ , picking are splitted if sources or destination are differen​
t. 
 
2.2.1.4. Picking Types 
 
By   default,  in  OpenERP  v7,  a  stock.picking  has  3  possible  types:  Incoming,  Internal, 

16/51 
Outgoing. We think this should be removed to allow supporting more types of movements: 
● Receptions 
● Cross­Dock 
● Drop­Shipping 
● Pick 
● Pack 
● Shipping 
● Quality Control, ... 
 
So, we will create a new object handling the different picking types (stock.picking.type) and 
different values must be stored on this object, rather than computed in the code (e.g. 
default source location, default destination location) 
 
The Picking Type (describing what operation you want to do) should be the entry point in 
the application as we don’t have the 3 menus anymore (Incoming, outgoing, internal). We 
need a clean kanban view that replaced the menu showing all possible operations and key 
metrics about what to do and performance. (like sales team in trunk, sales module) 
 

2.2.2 Use Cases


 

2.2.2.1: Cross-Docking
 
Configuration of Locations:  
● Input: reception of goods 
● Crossdock: zone where goods are temporarily waiting for out 
● Stock 
○ Bin A/B/... 
● Picked (where goods are put after picking) 
● Packed (where goods are put after packing) 
● Output 
 
Scenario 1: routes are defined according to the product  
We  will  give  the  example  of  fresh  products  that always do crossdock and plastic cups that 
always go to stock.   
 
In case of plastic cups, we will always go to stock: 

17/51 
 
In case of fresh products, we will always do crossdock: 

 
 
 
Then, the exact sequence of steps are: 
● SO triggers: Output → Customer 
● Then several pull rules according to products trigger: 
○ Packed → Output  
○ Input →Cross­dock → Output (for fresh products) 
● Then pull rules according to locations 
○ Stock → Picked →Packed 
○ Supplier → Input (through a PO: pull rule of type ‘buy’) 
 
Steps:  
● Sales order with fresh products that will be cross­docked and plastic cups.   
Waiting: Output → Customer with fresh products and plastic cups 
● 1 purchase order from the same supplier with fresh products and plastic cups: 
Confirmed: Supplier → Input with fresh products and plastic cups 
● It  will  split  in  two  pickings  as  fresh  products  always  do  crossdock  and  plastic  cups 
do  not.  So  there  will  be  pull  rules  on  the  product  from  Cross­dock→  output  and 
from Input →Cross­dock 
Confirmed: Input → Stock → Picked → Packed → Output with plastic cups 
Confirmed: Input → Crossdock → Output with fresh products 
● Put   Away  Strategy  on  Stock  when  first  move  gets  assigned  and  when  second 
move  gets  assigned  it will  do  the  removal  strategy  and  as  it is the only stock, it will 
take from the stock we entered:  
Confirmed: Input → Stock / Bin A → Picked → Packed → Output 
Confirmed: Input → Crossdock → Output with fresh products 
 
 
Scenario 2: routes are defined at reception by the warehouse manager: 
 

18/51 
 
 
(*) with auto­propagation of cancel 
(**) pull for scenario 1, push for scenario 2 (if there is a pull, the push does not apply) 
 
 
● Multiple sales orders with plastic and glass cups 
SO  A:  Waiting:  Output  →  Customer  with  glass  and  plastic  cups  (two  full  
pallets, one plastic, one glass) 
SO  B:  Waiting:  Output  →  Customer  with  glass  and  plastic  cups  (2  boxes 
and a half of glass cups and half a box of plastic cups) 
● One  big  purchase  order  with  plastic  and  glass cups to  the same supplier.  (two full 
homogeneous pallets and one mixed pallet) 
Supplier  → Input → Stock →Picked  →Packed  →Output  →Customer 
● Then  the  warehouse  manager  will  decide  that  SO  B  needs  to  go  to  stock  and 
packing  because the truck will only arrive tomorrow and it becomes  too cluttered on 
the  floor.  It   is  also  better  to  provide  3  boxes  instead  of  one  pallet  on  the  truck 
(packing).  
● =>   Warehouse  Manager  decides  that  the  two  pallets  have  to  go  through 
Cross­Dock and the 3 boxes will go to stock 
This will split the moves, and for the 2 pallets, the original flow will be cancelled:  
2 pallets: Input → Cross­dock → Output (and the previous flow will be cancelled) 
3 boxes: Input →Stock →Picked →Packed →Output 
 
Our  proposition  is  to  create  all  location  by  default  (may  be  in  stock_location  module),  the 
default  routes  (pick>pack>ship,  crossdock,  drop  ship,  …).  So  that  it’s   very  easy  to  do  a 
demo  or  configure the  system  without  having  to  create  all  locations  and rules (just set the 
route on the product) 
 
Scenario  3:  removal  strategy  that  decides  where  we  can  take  the  products  (stock  or 
cross­dock) 
 
● I do not know if it’s feasible in our solution? Describe the sequence of steps  
● Sales order 
Stock/Input ­> Output ­> Customer 
● Purchase order  
Supplier ­> Input 
● Removal  strategy  on  Stock  /  Input.  It  will decide a specific location in  Stock / Input 

19/51 
(disadvantage: confuses concepts of location / bin (or bin locations) ) 
 
TODO: Scenario depending on MTO/MTS for different lines of a sale order 
 
 
Question: 
● So, when having received products, there are two possibilities:  
○ We  leave  the  products  waiting  for  the execution of  an outgoing shipment as 
we expect its transport soon or it is over there already 
○ We move the products towards the stock in order to keep the docks empty  
● An  important  question  here  is  whether  we  can  define  beforehand  which  products 
will  do   crossdock  and  which  will  not.  If  we  know  we  will  do  crossdocking  by 
advance,  and  if  we are  used to, then we can manage this by a pull rule from output 
to input. 
 
Note that: 
● The  stock.pickings  above  could  be  split  in  several  pickings   when  there  will  be 
products  that are  ready  for  crossdock  and  other products  that  do not.  It is possible 
that  the  warehouse  manager  decides  to  bring  certain products in stock or products 
in crossdock.  
● Our  future  solution  must allow the warehouse manager to decide case by case and 
override  the  picking  proposed  by  push/pull  rule  and  solve  this  problem  in  an 
efficient  way  (cancellation  propagation?).  For  more  details,   see  the small note  on 
Pegging Strategy just below. 
 
Aside Notes on Pegging strategy
 
Pegging is the links between requirements with suitable stocks or receipts. 
The  pegging  strategy if  consequently  the  regulation  that  determines  the  time  sequence in 
which  the  system  processes  requirements  in  dynamic  pegging  and the  time  sequence  in 
which  the  system  assigns  the  receipt  elements  in  the  pegging  interval  to  a  requirement. 
The pegging strategy therefore controls: 
● which requirement the system processes first 
● which receipts the system uses first 
 
In particular,  
● it does the matching between IN/OUT operations 
● it handles reserved, released and priority changes 
●  ​ If  you  have  on  unit  of  product A in your stock, you sell one unit to customer A, one 
unit  on  customer B.  If  you  first  validate  your  Customer  A,  then B => then you have 
a  available  picking  for  Customer  A.  The  picking  for  Customer  B  is  waiting.  Then  if 
you  want  now  to  invert the  priority, because  customer  B  is  more  important,  it  take 
lots  of  time  and  operation..  overall  if  the  move  are  chained  !  canceling  them  all  to 
allow OpenERP to re­affect the sales to customer B take too much time. 
● =>   A   more  important  customer  than  another  is  a  very  common  case  in 
real life. We need to handle this properly ! 
● If more than one product are in that case, it become the hell. 
20/51 
 
 
2.2.2.2: routing at reception
 
In  this  use  case  we  will  receive  fresh  tomatoes  and  frozen ice cream in one shipment, but 
the different products will need to follow a different route through the warehouse.   
 
Location Config: 
● Input (docks) 
● Freezer input 
● Fresh input 
● Stock Freezer 
○ Freezer A  
○ Freezer B 
● Fresh 
○ Fresh table A 
○ Fresh table B 
 
Steps: 
● A purchase order will create an incoming shipment towards Input from Supplier 

Confirmed: Supplier Input 
 
● Then  if  there  are  products  with  different  push  rules,  when  the  original  moves  will 
propagate it will split in several pickings accordingly to the destination location. 
● Thus, we will have the following routing: 

Supplier   Input   Freezer input   Stock Freezer 


 

        

   Fresh Input  Stock Fresh 
 
● The last pushes eventually become:  

Assigned: Freezer Input  Freezer A 

Assigned: Fresh Input  Fresh Table A 
 
(*) Put Away Strategy 

21/51 
 
It  is  also  possible  that  the  freezers  and  the  fresh  tables  are  close  to  each  other  and  the 
Freezer  Input  and  the  Fresh  Input  are  the  same  (maybe  even  Input).  Then  the  removal 
strategies will split the stock moves instead of the push rules splitting the picking. 
 
As a summary: 
● Split of picking (and, thus, operations): push rule 
● Split  of  lines   but  keep  the  same  picking  (in  the  same  operation,  by  the  same 
worker): put away strategy 
 
2.2.2.3: Supplier direct delivery (in MTO from SO) / Drop shipping
 
In order to resolve the dropshipping cases, we suggest to create, at the confirmation of the 
SO, a procurement on the customer location instead of a procurement on output + stock 
move from output to customer. The picking from output to customer will be managed by 
the procurement instead of the SO (need toc reate a pull rule)=> we will remove a bunch 
of code and simplify the whole process (we may need to remove some code from 
stock_location and move it in stock (procurement that creates an internal move)   

22/51 
More over, the MTO/MTS selection field is not useful anymore on a sale order line. As an 
example, take a “Pick → Pack → Ship” process; there is no interest to set the Ship 
operation in MTS/MTO. This means we have to replace the MTS/MTO selection field on 
the sale order line by a route selection. (MTO becomes an available route that impact the 
Pick operations, downstream) 
 
When doing a sale order, routes should come from: 
● the warehouse (required to process Customers location), e.g.: Pick → Pack → Ship 
● the sale order lines (optional), e.g.: MTO 
 
Routes must be assigned to stock.move and propagated to procurement (using others 
routes defined on pull rules.) 
 
As this requires a lot of setup, the modules “stock” and “stock_location” must implement all 
the default routes and pull rules so that the user just have to select an existing route when 
doing a flow. 
 

2.3 Picking Waves


 

2.3.1 Concept of picking wave


 
The  Goal  of the picking waves is to group operations that may (needs to) be done together 
in  order  to  increase  their  efficiency. It may also be useful to assign  jobs (one person = one 
wave)  or  help  the timing management  of  operations  (tasks to be done at 1pm). In practice 
this is simply a many2one on stock.picking (wave_id). 
 
We   also  need  to  define  a  way  to  assign  automatically  this  wave_id field,  based  on  a  rule 
system that manages 
● timing (all picking to be done between 1:00 and 2:00) 
○ most urgent first... 
● volume/load constraints 
● destination 
● … 
This  object  (wave.rule)  would  have  the  following  fields:  name,  responsible  (user_id), 
capacity (weight, packs, volume..), location_id(s), time (1:00).. ​ To be Improved 
 
We   need  to  be  able  to  validate  a  whole  wave  in  a  row  (validate  all  pickings  inside  this 
wave) 
 
Inspiration can be found in 
● picking_dispatch module: 
http://bazaar.launchpad.net/~stock­logistic­core­editors/stock­logistic­flows/7.0/files 
● Syleam module 
 
Note:  the  picking  wave  is  different  than  the  strategy  to  group  several  moves  within  the 
23/51 
same picking. 
 
  Picking Wave  Group Move in Picking 

Used for  Prepare Orders for Worker  Link moves that should be made 


together 

Depends On  Timing,  Grouping defined on orderpoint (all 


Volume Constraints,  frozen product should be picked 
Locations  together), on push/pull rules, sales 
order 

Strategy  A strategy using constraints  Groups Defined manually 


 
 
 

2.3.2 Use Cases


 
2.3.2.1 Batch picking
 

 
In  batch  picking,  groups  of  orders  are  picked  at  the  same time to minimize repeat visits to 
the  same   product  bin  location.  An  order  management  system  will  arrange  a  group  of 
orders  in the most  efficient picking sequence and those orders are picked in the same time 
(all  P1  products  are  picked  and  5  are  placed  in  X  while  10  are  placed  in  Y,  then  the 
operation is repeated for P2, P3, P4). 
 
To implement batch picking: 

24/51 
● Use pull rules between Pick Zone and Stock 
● So,   pickings  will   remain  the  same  than  the  sale  order  (this  allows   to  prepare 
pickings by packing or do pick and pack at the same time) 
 
2.3.2.2. Wave Picking
 

 
 
In   bigger  warehouses,  it  may  be  more  efficient  to  work  in   wave  picking  instead of  batch 
picking.  In  this  method,  the  operations  are  grouped  by  products,  not  by order (pack). This 
allow  a   more  efficient  management  of  load/volume  constraint  but  involves  also  to  rebuild 
orders. 
 
To implement this with our solution, you need to: 
● define  an  automatic  orderpoint  (minimum  0,  maximum  0)  on  the  pick  zone   that 
creates  picking  for  each  product.  (in  the  stock  zone)  instead   of  a  pull  rule.  ​
To 
implement  this,  we  need  to  be  able  to  create  orderpoints  of categories  of products 
(child_of) 
● This  would   generate  lots  of  pickings  with  one  line  that  will  be  grouped  efficiently 
with the wave algorithm 
 
 
2.3.2.3 Trip assignation
 
Once  the  packs  are done,  we  may use  the  waves to group together all the delivery orders 
in  the   same  area.  This  wave  would  reflect  the  places  the  carrier  would   have  to  do  in  a 
single trip. 
 
Once all packs have been done (or during the operation of doing the packs): 
● You  can  create wave per  trip  (automatically  or  assign  manually  each pack to a trip 
by setting the wave_id) 
● Then,  you   can  assign  trips  to  Doors/Gateway  by  moving   the  wave  to  the  right 
location. We should implement a few operation in a wave: 
○ validate all pickings at once 
25/51 
○ print the wave 
○ pack  all  the  wave in  one  packagin  →  this  would  allow  to  move  all  products 
of the wave in one operation. (internal move) → don’t thnk we need this 
 
 
● Steps 
The warehouse manager gets overview of all delivery orders 
Delivery A → France 
Delivery B → Germany 
Delivery C → Switzerland 
Delivery D → Netherlands 
The  warehouse  managers  know  that  tomorrow  transporter  A  will  arrive  with 
cheapest tariffs to Germany and Switzerland  
The day after transporter B will arrive specialized in France and the Netherlands 
The  warehouse  managers  knows  they  can  all  deliver  in  time.  He  will  assign B and 
C  to  the  transport  tomorrow  of  transporter  A  and  A  and  D  to  the  transport  of 
transporter D.  So the wave_id becomes a transport.   
Every transport will get a dock assigned 
When  the  movement  from  Packing  to  Gates  gets  assigned,  the  PutAway strategy 
has to check the Delivery Order to see to which gate it is assigned.   
   

26/51 
2.4 Quants
2.4.1 Concept Explained
 
The  Quants  is  a new table that stores the current state of stock (per  location). It is updated 
each time a stock.move is set to ​ done​ and has 3 main impacts: 
 
● it   allows  optimization  of  computation  (quantity  available  for  example),  because  it 
only   contains  information  about  the  current  stock  (not  the  past  or  the  future).  The 
volume is thus smaller and doesn’t grow with time. 
● it   will  also  be   used  in  FIFO  costing,  as  we  need  to  match  the  incoming  and 
outgoing moves for a correct stock valuation. 
● this  table  can  also  be  used  for  the  upstream/downstream   traceability  and  the  lot 
management:  this  table  will  also  contains  the  information  about  lots  and,  a  list of 
stock  moves  that  explains  the  current  stock  level  a  record  is  depicting  (it  will 
replace  the  2 one2many ‘move_history_ids’ and ‘move_histoy_ids2’, currently used 
to get the chained moves). This field  is called history_ids later on the doc. 
 
The following properties should be on the Quant 
● lot #, many2one: 
○ serial # 
○ expiry date... 
● cost price (in the currency of the company) 
● quantity (of this lot) 
● location_id (of this lot) 
● pack_id (see later for packaging) 
● reservation_move_id (ID of the move that assigned/reserved this quant) 
● history_ids:  
 
The following properties should be on the stock.move: 
● quantity (total quantity to move) 
● src location 
● dest location  
● quant_ids (inversed one2many: reservation_move_id) 
 

2.4.1.2 Consumables vs Stockable products


 
The difference between a consumable and a stockable product is that the consumable 
have no quants assigned to it. 
 
The following table summarize the difference between the different types of products: 
 
 
  Physical Products  Consumables  Services 

27/51 
Procurement  Yes  Yes  Yes 

Stock.move  Yes  Yes  / 

Stock.quants  Yes  /  / 
 
This means: 
● Consumables follows push and pull rules 
● But there is no putaway/removal strategies on consumables 
● No inventory valuation possible for consumables too 
 
 

2.4.2 Use Cases


 
2.4.2.1 examples of some moves
 
After the following stock.move: 
● ID 1: 5 PCE, Supplier → Input 
● ID 2: 3 PCE, Supplier → Input 
 
We got the following Quants: 
● 5 PCE Input (history_ids: ID1) 
● 3 PCE Input (history_ids: ID2) 
 
If we do the following stock.move: 
● ID3: 6 PCE, Input → Stock 
 
We got the following Quants: 
● 5 PCE Stock (history_ids: ID1, ID3) 
● 1 PCE Stock (history_ids: ID2, ID3) 
● 2 PCE Input (history_ids: ID2) 
 
Let’s  suppose  i  now  cross  dock  the  2  PCE  from  Input  to  Output.  I  do  the  following 
stock.move: 
● ID4: 2 PCE Input → Output 
 
The Quants table now looks like 
● 5 PCE Stock #1 10€ (history_ids: ID1, ID3) 
● 1 PCE Stock #2 12€ (history_ids: ID2, ID3) 
● 2 PCE Output #2 12€ (history_ids: ID2, ID4) 
 
This  Quant  record  about  5  PCE  can  be  interpreted  as:  “I  have  currently  5 PCE  in  Stock 
location,  and  these  5  PCE  have  follow  the   path  Supplier  →  Input  →  Stock”.  All  stock 
moves in history_ids applies for the quantity on the Quant record. 
 

28/51 
 

2.4.2.2 How is it used in lots management


 
Let’s take back the example used in the previous use case but this time with the tracking 
lot feature and let’s see the impact on the Quants table 
 
First i receive products from my supplier for the given lot numbers: 
● ID 1: 5 PCE, Supplier → Input, lot #1 
● ID 2: 3 PCE, Supplier → Input, lot #2 
 
In the Quants table, we have: 
● 5 PCE Input, lot #1 (history_ids: ID1) 
● 3 PCE Input, lot #2 (history_ids: ID2) 
 
If we do the following stock.move ( i don’t need to encode the lot number on the stock 
move (but if given it will have priority on the system default behavior): 
● ID3: 6 PCE, Input → Stock 
 
We got the following Quants: 
● 5 PCE Stock, lot #1 (history_ids: ID 1, ID3) 
● 1 PCE Stock, lot #2 (history_ids: ID 2, ID3) 
● 2 PCE Input, lot #2 (history_ids: ID2) 
 
Let’s suppose i now cross dock the 2 PCE from Input to Output. I do the following 
stock.move: 
● ID4: 2 PCE Input → Output 
 
The Quants table now looks like 
● 5 PCE Stock, lot #1 (history_ids: ID 1, ID3) 
● 1 PCE Stock, lot #2 (history_ids: ID 2, ID3) 
● 2 PCE Output, lot #2 (history_ids: ID2, ID4) 
 
 

2.4.2.3 How is it used in FIFO


m
In   FIFO,  as  for  any  other  valuation  method  when  the  product  is  set  up  as  having  a 
real­time accounting valuation (and not standard), we  must store the purchase price on the 
Quants record. The stock valuation is easy to do and fast to compute. 
 
First i receive products from my supplier for the given amounts: 
● ID 1: 5 PCE, Supplier → Input, unit price = 10€ 
● ID 2: 3 PCE, Supplier → Input, unit price = 13€ 
 
In the Quants table, we have: 
● 5 PCE Input, unit price 10€ (history_ids: ID1) 

29/51 
● 3 PCE Input, unit price 13€ (history_ids: ID2) 
The stock valuation is simply 5x10€ + 3x13€. 
 
If we do the following stock.move: 
● ID3: 7 PCE, Input → Stock 
 
We got the following Quants: 
● 5 PCE Stock, unit price 10€ (history_ids: ID 1, ID3) 
● 2 PCE Stock, unit price 13€ (history_ids: ID 2, ID3) 
● 1 PCE Input, unit price 13€ (history_ids: ID2) 
 
Let’s suppose i now move 6 products from stock → customer 
 
The Quants table now looks like 
● 5 PCE Customer, unit price 10€ (history_ids: ID 1, ID3, ID4), valuated as 5x10€ 
● 1 PCE Customer, unit price 13€ (history_ids: ID 2, ID3, ID4), valuated as 1x13€ 
● 1 PCE Stock, unit price 13€ (history_ids: ID 2, ID3) 
● 1 PCE Input, unit price 13€ (history_ids: ID2) 
 
 
Question:  
HOW MANY PRODUCT DO I HAD ON THE 1st JANUARY with this !!? What was the ​ real 
value of the stock in location “stock” (for example for a product with a price that change 
with the time (like gold for example)) + think about landed costs integration 
 
=> SQL Query to compute the inventory at a specific date: 
● select  qty,  cost,  product_id,  (select  location_dest_id  from  stock.move  m  where 
m.id=q.move_id and date_done<=DATE order by date_done limit 1) from quants; 
○ + join on m2m history_ids 
● + price historization 

2.4.2.4: Impact on removal strategies

Currently,  removal  strategy  works  on  stock.move,  but  they  should  be  implemented  at 
stock.quant level. 
 
A  quant   can  be  assigned  to  a  move  to  do  or   not  (reservation  mechanism)  with  the 
reservation_move_id field. 
 
The  removal  strategy  finds  the  quant  amongst  all  quants  in  a  specific  location  being  not 
reserved yet. It assign the quant to the move by setting the reservation_move_id. 
 
 

2.4.2.5: negative stocks


 
30/51 
Negative  stocks  may  appear  in  OpenERP  if  all  operations   aren’t  done  in  a 
logical/chronological  way.  For  example,  if  a  delivery  order  is confirmed  (because the truck 
went  away  with  the  goods)  before the move ‘pack → output’ has been set to done (human  
error,  latency...).  These  are  exceptional  cases  but  we  want to let  the possibility to users to 
make  these  strange  situations  appear  in  OpenERP  because  users  can’t  be  stopped  in  
their work. 
 
When  the  stock  becomes  negative,  we  will  have  a  quant  with  a  negative  quantity.  The 
purpose  for  this  quant  is  to  become  0  or  positive  again  as  it  should  correct  the  situation 
where  we  wanted  to  force  things.  In  the  history_ids,  you will only have this outgoing move 
in  the   beginning,  but  the  next  in  move  will  also   be  put  on  this  quant.  It  is  very  important 
here  that  the  move  which  is  corrected,  will  also  correct  the  moves  that  were  propagated 
from the original out move. 
 
At  the  end,  if  the  negative  stock  has  been  totally  solved,  we  must  have  the exact  same 
situation as if there has never been any negative stock 
 
Let’s see that with an example: 
● At  the  beginning,  we  have  20  pieces  available  on  the  Output  location  (from  ID1). 
The Quants table is:  
20 PCE output (history_ids: ID1) 
 
● Then  we  make  a  delivery  order  ID2  of  40  PCE (output → customer), which implies 
a  negative  stock  on  output.  As  we  are  20  pieces  short,   this  creates  a  negative 
quant  of  20  pieces  on  the  output  location.  However, these 20 PCE have been sent 
to  the  customer  location,  so  the total  stock  will  be  40  PCE  over  there.  This  results 
in  2  quants  of  20  PCE  on  the  customer  location  as  the  20  PCE  of  negative  stock 
will almost certainly come  from  a different incoming shipment. So, when  there is  not 
enough  stock,  two  quants  are  created:  a  negative   in  the  source  location  and  a 
positive  in  the  destination  location.  We  will make a link between these two quants, 
which makes it possible to propagate the reconciliation afterwards. 
 
The Quants table is now: 
20 PCE customer (history_ids: ID1, ID2) 
20 PCE customer (history_ids: ID2) 
­20 PCE output (history_ids: ID2) 
 
● Afterwards,  10  pieces  come in  output  with  ID3.  The  negative  record  in  the  Quants 
table   is  updated  and  this  update  needs  to  be  propagated  to  all  the  succeeding 
moves  by  use of the history_ids. The link between the positive and negative quants 
makes  sure  ID3  is  applied  to  the  history_ids  of  the  correct  quant  (second  quant in 
the  table  above).  However,  the  provided  quantity  is  still  not  enough  to completely 
fix  the  negative  stock,  thus  the  same  quant  is  split  in  two:  one  part  containing  the 
10  pieces  detected  as  sent  to  the  customer,  one  for   the  remaining  10  units  to 
reconcile with another quant. 
 

31/51 
The Quants table is now: 
20 PCE customer (history_ids: ID1, ID2) 
10 PCE customer (history_ids: ID2, ID3) 
10 PCE customer (history_ids: ID2) 
­10 PCE output (history_ids: ID2) 
 
● Finally,   yet   another  20  pieces  arrive  with  ID4.  The  negative  record  in  the  Quants 
table  is  updated and as it becomes 0 it is removed. We  add  the positive balance as 
a new Quants record: 
20 PCE customer (history_ids: ID1, ID2) 
10 PCE customer (history_ids: ID2, ID3) 
10 PCE customer (history_ids: ID2, ID4) 
minus 10 PCE output (history_ids: ID2) 
10 PCE output (history_ids: ID4) 
 
In  order  to  achieve  the above  use  case,  the  system  must  be  able  to  “reconcile”  quants to 
link a negative one with a positive (and, thus, generate accounting entries) 
 
This  reconciliation  can  happen  automatically  when   the  goods  received  later,  pass  in  the 
exact  location  of  the  negative  quant.  Depending  on the  PutAway  rules  e.g.,  it  is  possible 
that  the  goods  e.g. end up in the location next to the location of the negative quant e.g. bin 
B instead of bin A.   
 
In  that  case,  we provide  a  menu (or  a  filter)  that  shows the negative quants. Then we can 
tell  the  system   that  we  used  the  box  from  bin  B  in  bin  A.  The  system  will  create  a  move 
from  bin  B  to   bin   A  and  as  bin  A  has  the  negative  quant,  this  will  propagate  the  original 
move in the history_ids in the same way as in the example above.   
 
 
2.4.2.7 Impact on performance
 
This would speed up all operations like: 
● quant selection (confirm → assign on stock move: removal strategies) 
● quantities available (according to warehouse, location, …) 
 
Because: 
● Computations  are  made  on  products  that  are  still in the warehouse (limited volume 
of   data,  index  on  location_id),  rather  than  all  stock.move  since the  creation  of  the 
company (explosion of data) 
 
We   can  even  speed  up  virtual  stock  computation   because  we  base  them  on  two  limited 
sets of records: “quants” +” move not done” 
 
Inventory reports must be changed to use quants instead of stock.move. Same for 
quantities on products or locations, they should be implemented using the quant table. 
 
32/51 
2.4.3 Separation of concepts
 
The clear separation of concepts allows an easier implementation and an easier 
configuration of the whole system. 
 
 
 
 
Object  Impacting Concept  Used For 

stock.picking  picking.wave, picking.group  Work Orders 

stock.move  push rule, pull rule  Routing 

quants  removal strategy, put away strategies  Bins Allocation 


 
 
As an example, suppose you have a stock.move: 
● Input → Stock 
And the put away strategy says you have to put the product in Stock → Stock / Bin 1 
 
When the stock.move becomes “done”: 
● stock.move: Input → Stock 
● Related quant: Stock / Bin 1 
 
So, put away and remove strategies have no impact on the stock.move. The exact location 
is provided on the quant, not on the move. (move defines main routings in the warehouse). 
This means that: 
● Forecasts are defined at higher levels (Stock, not on bins) 
● Real operations (quants) are defined at low level (Stock / Bin 1) 
 
Removal strategies should have no impact on the stock.move (we should avoid splitting 
stock.move due to a stock reservation). 
 
This also means that we have no traceability at the bin level, only at main location level 
which we think is ok. (if one need a ful traceability at the bin level, we can add the 
location_id information in the many2many history field between quants and moves) 
 
 

2.5 Lots Management


 
Directly  linked  to  the  quants  solution,  but  we  should  define  scenario  more  precisely 
(receptions, delivery orders, internal moves …). 
 
Lots  assignation  is  defined  by  the  removal  strategy.  During  some  operations,  it  may 

33/51 
eventually automatically create or split lots numbers. 
 
On  doit  pouvoir  enforcer  qu’un  serial  number  est  créé  et   proposé  automatiquement  par 
OpenERP (à la réception/ manufacturing unique). 
 
Il   faut   une   contrainte  d’unicité  pour  certains  produits,   afin  de  gérer  les  traceabilités  à  la 
pièce (case à cocher sur le produit + constraint sur les Quants) 
 

2.6 Packings
 

Data Model: packaging


 
The different types of packaging are defined in the product.packaging table. “Pack Types”. 
 
We   propose  to  add  a  new  table  ”stock.quant.package”  with  one  instance  per  physical 
package with the following information: 
● Serial #: char 
● package_id: Type of Package (product.packaging) 
● quant_ids: one2many(‘stock.quant’, ‘pack_id’, ‘Content’) 
● parent_id: fields.many2one(‘stock.quant.package’) 
● location_id  ?  constraint  to  enforce  that  all  quants  in  a  given  package  are  in  the 
same location => location_id is a fields.related => need a technical way to do that 
 
On the stock.quant table, we add a fields.many2one(‘package_id’, ‘Package’). 
 
→  So,  several  quants  can  be  in  the  same  handling  unit  (a  box) and several boxes can be 
in a pallet (parent_id). 
 

Removal Strategies
 
Toute la complexité de la gestion des packs est dans le removal strategy (et éventuellment 
dans  les changements de quantité entre deux  opérations chainées → moins c’est ok, mais 
plus peut poser des problèmes) 
 
L’algo doit ressembler à qqch du genre, implémenté dans la removal strategy: 
● Prendre les packs du move chainée précédent s’il y en a 
● S’il  n’y  en  a  pas,  utiliser  les  stratégies  (à  définir)  du  genre:   si  j’ai  besoin  de  10 
produits,  je  vais  plutôt prendre une boite de  10 que 10 pièces isolées. On doit avoir 
plusieurs  stratégies  par  emplacements,  ex:  est­ce  que  j’accepte  d’ouvrir  une  boite 
lors de la mise en stock de marchandises reçues 
 
L’assignation des  stock.move doit  se  faire  en  masse  (en  tous cas par picking), et non pas 
un par un car un pack peut contenir plusieurs produits différents. 
 

34/51 
Packing in stock.picking
 
During an operation (picking, packing, internal move, reception), we need to be able to: 
● pack products in others handling units. (put products in boxes) 
● move packs (a whole pallet) 
● pack handling unites in others handling units (put boxes on pallets) 
 
The  same   object  (stock.picking)  can  be  used  for  receptions,  internal  moves,  picking, 
packing, shipments, … So, we need one flexible interface that adapts to main needs. 
 
We propose to split two concepts on the same picking: 
● What should be done, the current product lines (stock.move) 
○ 505 PCE Computer 
○ 10 PCE Mouse 
● What I do do, (the exact physical operation: moving boxes, packing products, …) 
○ 5 Boxes (containing 100 computers) 
○ 1 box (containing 10 mouse) 
 
When  the  picking  is  validated,  we  do  the  difference  between  what  have  been  done  and 
what should have been done and it generate optionally a backorder, in this scenario: 
● 5 PCE Computer 
 
This  system  would  replace  the  current  popup  wizard  with  quantities  processed  (partial 
picking wizard). 
 

Some notes on the interface


 
We think that the interface should be somehow looking to this mockup: 

 
Exemple of such an interface: ​ http://www.youtube.com/watch?v=QaflmApHX0k 
 
In  the  package  section,  you can select products or handling units (e.g.boxes)​
. When 

35/51 
a  picking  goes  from  confirmed  to  assigned,  the  removal  strategies  apply  and  OpenERP 
proposes automatically the handling unit according to  the required quantities. (and chained 
moves.  (a  web  module  development)  →  it’s  not  packaging,  it’s  what  you  do  (move 
products, move boxes) 
 
When  we  click  on   the  “pack”  button,  it  takes   all  products  and  boxes  that  are 
selected  and  create  a  package  in the bottom right. ​ (need to add a checkbox on the left 
of Laptop computers in the above mockup) 
 
The package many2one (Pack/001) in the above mockup) can be empty. 
 
A  tooltip  must   be  defined  on  the  product  line  (e.x.  505  laptop  computers). If  you  put  your 
mouse  over,  OpenEPR  suggest  appropriate  packaging  methods  according  to  the 
quantities of this product: “5 box X of 100, 1 box of 5”, “2 box Y of 200, 1 box of 100, ….” 
 
The  bottom  one2many  as a default value only if preceding moves are chained (e.g. ship of 
a previously packed parcel). If no move is chained, the one2many is empty by default. 
 
As in v7, location is: 
● source for internal move & delivery orders 
● destination for incoming shipments 
 
The  package  (PACK/001)  can  be  a  new  package  (usually)  or  an  existing  one  (moving 
product in one existing palet) → this field should be a many2one (allowing select or create) 
 
We need a print button to print a pack list on a selected pack. 
 
To  manage  homogeneous  package  when  packing  operation (series of  package),  ​ you  just  
click  on  (+) icon  to do several packages of the same type​ . there will be a integer field to let 
the user encode how much of the same package he wants. 
 
We may add a “copy all” or “clear all” button that will copy ordered qty to processed qty. 
 
OpenERP  will automatically manage the creation of the stock.quant.pack object and it may 
eventually move it into another stock.quant.pack (if you move a box and put it in a pallet) 
 
The  package  one2many  is  filled  automatically,  with  default  value,  by  OpenERP  at  the 
assignation​  of the picking. (proposition of packaging) only if they are chained moves 
 
This  system replaces  the confirmation wizard with quantities as it does the same (compare 
what  should  have  been  done  (product  lines)  and  what  we  did  (packs)  and  create  a  back 
order if necessary) 
 
In  the  picking  one2many,  we  may  add  a  “Preferred Packing” field  with the information that 
comes from the sale order. (and the product) 
 

36/51 
Ideally, this UI should be like the POS: 
● support  for  disconnected  mode  (you  load  a  picking wave and you can work in local 
storage) 
● responsive design to work on small screens 
This would allow to support major barcode readers without specific hardware interfaces. 
 

Examples

Use case 1: reception


 
Reception: 
 
Initial Screen: 
● Top: filled with products from the order 
● Bottom: Empty 
 
The worker do: 
● Record  packs  as  he  received  it,  by  checking  the  packing  list  of the supplier (select 
on the top) by clicking on products and clicking Pack for each recorded pack. 
 
Put away in stock: 
 
If he stores packs as it, initial screen: 
● Top: filled with products from the order 
● Bottom: Filled with packs from the reception 
He just has to click on validate 
 
If he wants to repack, initial screen: 
● Top: filled with products from the order 
● Bottom: Filled with packs from the preceding shipping (because chained picking) 
He clicks on “Clear” and pack products by clicking on them in another way. (like reception) 
 
Use case 2: Pick
 
Initial screen: 
● Top: filled with products from the picking list 
● Bottom: empty 
 
He  packs  products  by  clicking  on  them  and  clicking  on  the  pack  button  at  each  box. 
(usually  in  batch  picking)  or  he  doesn’t  pack  the  products  (usually  in wave picking)  or he 
can take boxes as it by selecting boxes (drop down when clicking on the product line) 
 
Use Case 3: pack
 
Initial screen, batch picking: 

37/51 
● Top: filled with products from the order 
● Bottom:  Filled  with  packs  from  the  picking  (batch  picking)  if  he  did  pack during the 
picking operation 
→ the user just has to validate (and may be pack differently) 
 
Initial screen, wave picking: 
● Top: filled with products from the order 
● Bottom: empty (as it’s not a pull mto, but an orderpoint) 
→ the user should record the packing 
Use Case 4: Ship
 
Initial screen, batch picking: 
● Top: filled with products from the order 
● Bottom: Filled with packs from the packing 
 
The user just has to validate. 
 
Use Case 5: Partial Pick
 
Initial screen: 
● Top: filled with products from the order 
● Bottom: empty 
 
 
The  user  starts  to  record  what  he  does  (products  or  boxes   move)  and  the  remaining 
column  changes.  Then,  he  validates  the  whole  picking  and  the  backorder  is  created  with 
remaining products. (like current v7 implementation). 
 

Viewing a pack (stock.quant.pack)


 
We need a menu where you can search packs by product, serial number, customer, etc.  
 
You  can  ask  the  tree  view  of  a  pack:  (related  button  on  the top right corner to open a tree 
view) 
● Container 102210 
○ Pallet 03240204202 
■ Box 43043203 
■ Box 32032032 
■ Box 20320320 
○ Pallet 04024043220 
○ … 
 
If  you  click  on  one  of  the  node,  you  get  all  quants  (group  by product_id)  belonging  to this  
pack (child_of) 

38/51 
 

Pack (stock.quant.pack) and putaway strategies


 
The  stock.move  should  have  a  preferred  packing  that  is  set  automatically  by  the  sale 
order/purchase order. (and the default value comes from the product form) 
 
The  picking   proposes  automatically  a  packaging  using  the  preferred  packing  when  going 
from confirm to assign. 
 
A  putaway  strategy  can  have  a  “Preferred  packing”   that   will  be  used  by  OpenERP  to 
propose  the  packaging  according  to  the  number  of  products  to  process.  this  putaway 
strategy sets the “Preferred Packing” on the stock.move created. 
 
 

2.7 Real Time Costing

2.7.1 Basics

2.7.1.1 ‘Standard Price’ costing method


Stock  valuation is  always  made  using  the  cost  price  set  on the product. Inventory value is 
given  by  quantity  in  stock  *  standard_price.  Modifying  the  standard  price  of  a  product 
results in posting accounting entries to adjust the stock value. 
 
2.7.1.2 ‘Average Price’ costing method
As  for  the  ‘standard price’  method, the stock valuation  is always made using the cost price 
set  on  the  product,  the inventory  value  is  given  by  quantity  in  stock  *  standard_price, and 
modifying  manually  the  standard  price  of  a product results in posting accounting entries to 
adjust  the  stock  value.  The  only  difference  is  that  the  new  average price  of a  product  is 
computed at each reception, accordingly to quantities. 
 
2.7.1.2 ‘Real Costs’ costing method (FIFO, LIFO)
This  costing  method,  also  known  as  ‘Specification  Identification’  method  tracks  the exact 
cost   of  each   inventory  item.  It  will  valuate  each  Quant  individually  accordingly  to  the 
purchase price stored on it when it comes in or goes out the company stock.  
 
This  option  allow  to  implement  FIFO  and  LIFO costing  methods,  that  are  really  achieved 
thanks  to  the removal strategies (products with costing method = ‘Real Costs’ and removal 
strategy = FIFO will be valuated in FIFO). 
 
While   this  method  allow  to always  reflect  the  reality,  the  direct  consequence  is  that  there 
can’t  be  a  different  algorithm  for  the  stock  valuation  and  the  removal  strategy.  You  can’t 
decide,  for  example,  to  remove  first  the  products  nearest  the  output  zone  and  make  a 
stock valuation for them in FIFO. 

39/51 
 
Another   limitation  is explained  in  the  following  example:  let’s  suppose  i  receive a  product 
that  i  configured  with  real  time  valuation,  real  costs  for  costing  method  and  FIFO  for  the 
removal  strategy.  This  time,  i  purchased  10  pieces  at  10€  the  unit  but i  had  a  remaining 
stock  of  5  pieces  at  8€  the  unit.  At  the  time  of  receiving  the  incoming  shipment,  i realize i 
have   an  outgoing  shipment  for  the  same  product  planned,  and  i  decide  to  make  cross 
docking  to  avoid  useless  stock  movements.  The  outgoing  products will  be  valuated at the 
price of 10€ instead of 8€ as would have suggested the FIFO removal strategy. 
 

2.7.2 Stock valuation reconciliation


Reconciliation  between  stock  valuation  and  the  supplier  invoice  is  a  way  to  ensure  the 
stock  value  is  correct  regarding what you really paid for your products. The way to achieve 
this is to add a many2many relationship between invoice lines and quants. 
 
Each time a new relation is made using this field, it posts the related entries. 
 

2.7.3 Landed costs


If  you  want to add landed costs to a product that is  currently present in your stock, you can 
use  the  same  many2many  between  invoice  lines  and  stock  moves.  Nothing  more  is 
planned at this time for this feature. 
 

2.7.4 Anglo saxon accounting


All  concepts  explained  before  stand  for  continental  accounting.  In  anglo  saxon  the  only  
difference  is  that  for  all products (no only the ones with ‘real costs’ as  costing method), the 
quant   table  will  be  used  also  to  book  the   eventual  entry  for  price  difference  at  the 
generation  of  the  supplier  invoice  from  the  purchase  order.  In  other  words,  the  matching 
beteween  the  invoice line  and  the  stock  move  will  automatically  be made  and  if there is a 
difference it will post it under the ‘price difference’ account of the product. 
 
Encoding   this  ensure  to  have  always  the  price  difference  that  is  exactly  the  difference 
between the stock value and the supplier price. 
 

2.7.5 Stock Ownership


The  default  ownership  is  defined  by  the  location  of  type  internal.  An  “internal”  location 
does   not  refer  to  the  localization  of  the  location  but  to  the  ownership  (for  inventory 
valuations). The localization of a location is defined by it’s parent and hierarchy structure. 
 
So,  you  can  have  “Partner” locations  in your warehouse and “Internal” locations outside of 
your  warehouse.  Thus,  the  following  locations  are  usually  of  the  type  internal; Bins, input, 
picked, packed, output.  
 
But  ownership  can  also defined  on  the  quant  (products in my stock belonging to someone 
else).  If  a  ownership  is  defined  on  the  quant,  it  takes  precedence  on  the  “internal”  stock 

40/51 
locations. → this has impact of accounting entries and costing. 
 

2.7.6 Implementation
 
The journal entries generation and price adjustment must be private methods on the 
quants, not on the stock.move. We should move all methods on the quant object. 
 

2.8 Multi-Company
 

2.8.1 Explanation of the current problem


 
When  you  transfer  goods  inter­company  in  OpenERP  now,  you  have  one  cost  price  over 
all  the  companies  for  the  same  product,  so  this  means  the  valuation  can  only  be  done  in 
one  way  for  all  companies. This mean that it’s not possible share  a product if the company 
currencies  aren’t  the  same,  if  the  cost  price  for  each  company  aren’t  the  same,  if  the 
valuation methods of each company aren’t the same... 
 

2.8.2 Things to do to in order to solve this problem


 
Note:  we  though  about  this  before  designing   the  Quants  table.  There  may  be  things  to 
review in it. 
 
When  you  transfer  goods  inter­company  from  A  to  B,  you  should  be  able  to  do  the 
necessary  calculations  for  going  out  of  A  and  the  necessary  calculations  for  the  goods 
arriving in company B.  
 
This involves following changes in OpenERP 
● Valuation,  cost  method  and  cost  price  (standard_price)  fields  become  properties = 
will be different according to the company they are viewed in.  
● This  has  influences  on  a  lot of PSQL reports, where calculations  are made with the 
standard  price of the product. For each we need a solution case by case: in the pos 
reports  we  remove  it,   for  product  margins  we  calculate  it  afterwards  with  a 
functional  field  as this  report  is  basically  calculated fields on the product, in case of 
mrp in / out we change the standard_price with the price on the move... 
● Inter­company  stock  moves  disappear.  They  have  to  pass  through  a  transit 
location.  The  company  of  the  stock  move  becomes  the  company  of  the  internal 
location.  This  allow  us  to  store  the  cost  price  on  the  stock   move  in  the  company 
currency   (in  other  words,  we  disallow  situations  where  a  stock  move  is  shared  in 
between 2 companies that haven’t the same currency) 
○ ok constraint 
○ transit location insuffisant, il faut enlever ca, il faut SO et PO 
● When  calculating  prices  on  moves  and  changing  the  cost  price  of  a company, it is 
important   to  have  the  force_company  in  the  context  when  executing  the  price 

41/51 
calculation  method. That way if you validate a stock  move from another company, it 
will  create   the  valuations  according  to  the  methods  and  prices  of  the  company  of 
the stock move. 
The  owner  of  the  stock  of an  internal  location  is  the  company of the location. If the 
owner  is  an  external  company,  the  type  is  not  internal  (and  it’s  address  can  be 
specified on the location) 
● vérifier  que  le  mass  import  de  records  avec des champs property fonctionne => ce 
qu’on  veut  avoir c’est  produit  |  cost  price  in  company  A  |  cost  price  in  company B. 
→  It  does  not  work; a  simple  solution would be to import several lists (one for each 
company) 
● on  doit  avoir  que  tous  les  champs  sur  la  fiche  produit   sont  dans  la  devise  de  la 
compagnie  MAIS  on  garde  le  comportement  actuel  pour  le  sale  price  parce  que 
c’est pas la problématique adressée ici 
● vérifier  le  price_get  a  cause  du  changement  en  champ  property  et  éventuellement 
modifier  la  facon  de  gèrer  le  prix  d’achat par défaut (ne plus baser cela par rapport 
au cost price car c’est débile) 
 

2.9 Burst Process


 
Could  be  done  with  the  current  wizard  to  process  a  picking  (all  lines  are  created  with  bar 
code   scanner  rather  than  a default  value,  then  we  detect  differences  between  what  have 
been  done  (records  in  the wizard) and what should  have been done (picking) to create the  
backorder) 
 
To   be  developed  in  the  specific  interface  of  picking/packing,  using  the  same  technology 
than what we did for the POS. → mostly covered by the packing section. 
 

2.10 Dates Management


To be discussed 
Master Datas 
● Lead  time  at  supplier  level  (split  with  transport  mode  &  leadtime)  and  product 
category potentially 
● Supporting features  for  automatic  update  should  be  included  in OpenERP solution 
to  reduce  the  data  keyboard  while  supporting  users’  daily activities (e.g.  update of 
product/supplier  prices  at  supplier  catalogue  load  or   RfQ  validation)  →  why  not 
ising import/export with predefined formats? 
 
Date mgmt 
● ajouter  la  date  demandée  par le client / date confirmée au niveau du header=> KPI 
pour connaître notre performance / celle du supplier 
○ champ  related  sur  le  stock  move  qui  pointe  sur  un  nouveau  champ  du 
picking (recopié depuis le PO/SO: data demandée par le client) 
● Allow  to  change a  processed  date  by  the  user  (today  openerp  scratch  the  date on 
the  packing confirmation,  we may  have  process  a  pack  on  friday  and  encode it on 

42/51 
monday in the system => We should be able to put a date in the past) 
○ permettre de setter la date done du move 
● planned date on the picking must be computed accordingly to the picking policy 
○ date la plus proche ou la plus éloignée selon le cas 
● vues a revoir pour permettre d’encoder la scheduled date sur les pickings 
● grouper  les stock move dans les pickings de manière intelligente, pour pas avoir un 
picking contenant des move avec 2 mois d’écart par exemple 
● add  the  scheduled  date  on  the  PO  line  (computed  as  date  planned  on  the  PO  + 
lead time of the product) 
 
 

2.11 Replenishment strategy


 
Replenishment  strategy  is  based  on  two  criteria:  date   and   quantity  both  can  be  fixed  or 
variable. 
 

The  replenishment rule needs to be assigned to a product Category or to a product and for 
a  Stock  Location or  a  warehouse  (as  in  standard  when  a  rule  is set for  a  parent  location, 
the  inventories  taking  into  account  in  the  replenishment  calculation  includes  the  children 
locations*).  A  hierarchy  has  to be followed: if the replenishment rule is assigned at product 
level,  this  one  will  be  used  if  no  rule  is  assigned;  system  will  use  the  one  of the  product 
category if existing. If not, no replenishment rule will be applied. 
 
­  Date  (frequency   and  start  of  policy applying)  can  be  determined  at  category/class  level 
(and of course at product level). 
­  Variable  quantity  calculation  method  can  be  selected  at  category/class  level  (and  of 
course at product level). 
­ Fixed quantities have to be defined at product level on standard UoM. 
 
The previous choices will imply one of the below policies:  
 
Combined  Fixed Date  Variable Date 
Combinedpolic

Fixed Quantity   Automatic Supply  Min/Max or Reorder point 
Variable  Order Cycle  “Opportunist” Supply or 
Quantity  Threshold value 
 
→  These  should  be an  improvement  of  orderpoints,  not  a  new  concept.  Eg  for  improving 
order point: 
● Quantity to Order: Fixed / Replenish Until Max 
○ define a max 
○ or define a fixed qty 
● Cycle: 
43/51 
○ Every day (current behaviour) / Week / Month 
○ Like   the  current  features  on  recurring  meeting:  day/hour  of   week,  day  of 
month, X weeks, … 
● Based on: 
○ Minimum Qty 
○ Other for opportunist supply 
 
Note  that  I  am  not  sure  that  the  Cycle  should  be  implemented  at  the  orderpoint  ​
level.  It 
may  be  more  efficient  to  implement  cycle  in  the  PO  process  (or  procurement).  →  e.g.  I 
want  to  order  to  this  supplier  on  mondays.  (whatever  if  needs   come  from  MTO, 
procurements or orderpoints) 
 
Safety stock in “absolute” quantity or on based period quantity should be set if needed. 
 

2.12 KPI

To   evaluate  activities  and  measure  “performance”  of  any  Supply  chain,  indicators  are 
requested. 
Indicators  analyze needs to be quick and easy  to be useful. The idea is then to provide a 
tool  to  create  a kind of dashboard with personalized indicators selection with appropriate 
reference values optionally. 
Example of basic KPIs: 
● Cycle time of Purchase orders  
● Supplier punctuality (Percentage of PO lines on time/late) 
● Cycle time of Sales orders (average)  
● Total stock value: value for all internal location, by location, by view… 
● Value of quantity expired / loss  
● Nb of references of non moving stocks,  
● Volume  of  POs   (Number  of  POs,  Total  number  of  PO’s  line  ,  Total  amount  of 
POs (monthly/annual) ; Number of lines received  
● Volume  of  Shipment  (by  destination,  by  transport  mode,  by  month /  annual.)  ; 
Number of lines shipped  
 
If  it’s  ok   for  C2C,  I  propose that this  analysis  do  not  cover  reporting  and KPI.  We  should 
better  focus  on  the  main  flows. You  should  just  verify  that  our  solution  fits  your  reporting 
need. 
 
Reports are an implementation effort, not an analysis effort. 
 

2.13 Purchase Order Workflow and Procurements


 
The  problem:  when  do  we  close  the  workflow  of  the   purchase  order  (As  the  SO  close 
when  ship  is  done,  not  when  packing  is  done).   Do  we  consider that a  purchase  order  is 

44/51 
received if we refused products during quality control, after the reception? 
 
We should make the difference between: 
● The purchase order is closed (reception has been made) 
● The  procurement  is  fulfilled  (product arrived  where  I  expected  it,  e.g.  in  the stock, 
after the quality control) 
 
In  this  regard,  if  you  receive  all  the  products  you  purchased but you refuse some after the 
quality  control:  the  purchase  order is considered as received (you received everything) but 
the  procurement  is  not  (products  did  not  arrive  in  the  stock).  Depending  on  how  you 
handle this, you may trigger: 
● return of products + request for refund 
● return of products + reviewed expected invoice 
● return of products + ask for new products 
● scrap of products + … 
 
So,  a  purchase order is  marked  as  “received”  when you received all the products (the first 
operation), even if you decide to scrap, return or introduce a claim after. 
 
In   case  of  chained  moves, the  purchase  order  is  “Received”  when  the  first  reception  has 
been  done.  In  case  of  backorders,  the  purchase   order  is  “Received”  when  the  last 
backorder  has  been  closed  (received  or  cancelled)  If  one  reception  is  done,  the  PO  is 
closed. If all receptions are cancelled, the PO is cancelled. 
 
If  further  operations  (like  quality  control)  requires  that  you  send   back  products  to  your 
supplier, it should be another request: 
● new expected incoming shipment 
● change in the expected invoice 
 
We think the current workflow of the purchase order is correct in that regard. 
 
But  no  other  workflow  should  rely  on  the  workflow  of a purchase  order to know if products 
arrived  or  not.  The  procurement  workflow  should  rely  on  the   reception  of  the  product 
(stock.move) rather than the purchase order for stockable/consumable products. 
 
The  procurement  should  be  changed  in  order  to  “listen”  to  the  stock.move  instead  of  the 
purchase order 
 

Use Case: Reception → Quality Control → Stock (pull)


 
This  flow  is  different  if   it’s  in  pull  (po  created  from  a  procurement)  or  in  push.  (manual 
purchase  order).  The  scenario  is  different  according  to  how  you  handle  refused  products. 
This scenario: receive less (or return refused products), expect less on the invoice. 
 
Two operations are created by pull rules: 
● Incoming Shipment (linked to a PO) 
45/51 
● Quality Control (chained to shipment rule, with a procurement on stock) 
 
When receiving all the products: 
● Incoming Shipment: “Done” 
● Purchase Order: “Received” 
● Procurement on Stock: In Progress 
 
Quality Control (Partial Transfer to stock of validated products): (1/2) 
● Some procurements closed (according to products) 
● Some procurement still in progress 
 
Quality Control (Return remaining products to Supplier) (2/2) 
● By cancelling the backorder (quality control → stock): 
○ Procurements on stock becomes “MTS”, chain between moves broken 
● Change the draft invoice that you expect to receive 
● By returning the backorder: 
○ New shipment to the supplier created 
→ we can create a wizard that record these 3 steps automatically. 
 
Other Possibility (Ask supplier to exchange the products) (2/2) 
● Keep backorder open 
● By returning the backorder: 
○ New outgoing shipment to the supplier created 
○ New incoming shipment created with a procurement to fulfill quality 
→ we can create a wizard that record these 2 steps automatically. 
 
So, the main idea: 
● The purchase order is marked as received (which is true, we received products) 
● But new documents keep track of the fact the supplier still owns us stuff: 
○ Products to be exchanged: 
■ new outgoing shipment 
■ new incoming shipment still open 
○ Reduced invoice expected 
 

Modularity
 
The different features should be splitted across different modules: 
● stock: Inventory Management (+ most basic operations) (including the stock 
packing web UI) 
● stock_location: Warehouse Management 
● stock_picking_wave: Picking Waves 
 
 
Feature  Module 

46/51 
Push  stock_location 

Pull  stock_location (basic pull rule in stock) 

Put Away  stock_location 

Removal  stock (simple strategies) 
stock_location (advanced strategies) 
 
 
Most advanced routing operations should be placed in the module stock_location 
wherever it’s possible without bloating too much the code. 
 
The idea is that a company that manages a warehouse without routes inside this 
warehouse would use only stock and not stock_location. So, they do not need push/pull 
rules, putaway strategies and removal strategies. (stock just include the basic removal 
strategy on the product) 
 
Removal strategy should be in the stock module because the mechanism of reservation of 
quants is based on the removal strategy. More advanced removal strategies than FIFO 
can be in the stock_location module. 
 

List of Corner cases to take care of


 

Negative Quants
 
Negative quants are generated when the user forces the validation of a stock.move from a 
location having no products (quants) available. 
 
Negative stocks are a problem because: 
● You can not do the accounting valuation 
● You have to create a quant without having the right data about it (lot, cost, …) 
 
In this situation, we create a negative quant in the source location that is the opposite than 
the positive quant generated at the destination location. This negative quant should be 
reconciled with a positive quant arriving in this location (having a cost, …) During the 
reconciliation, the right data are set on the quant related to the negative one (costs, …) 
 
So, we need an automatic reconciliation system to link negative quants with newly created 
positive quants no yet assigned to another operation. 

Identified Issues
 
Our solution does not handle: 

47/51 
● Reception   of  handling  units  (e.g.  palets)  without  knowing  the  exact  content  and 
filling  the  content  afterwards.  We  chose  not  to  support  this  case  in  this  analysis to 
keep   things  simple.  This  leaves  two  possible  implementations:   1/  receive  all 
“expected”  products  according  to  the  PO  or  delivery  note  and  update  numbers 
afterwards. 2/ Record the detailed reception afterwards. 
● Computation  of  the  best  route  between  two  locations:  we   support  several 
possibilities  for  removal  or  putaway  but not  several  routes  between  two locations. 
(one  has  always  priority  on  another  one  using  sequences)  It’s  not  covered  by  this 
analysis as we think it’s better not to implement it for now on. 
● A  scheduler  that  proposes  to  move  Bins  instead   of  products/handling  units.  It’s 
possible  to   move  BINS  (=locations)  manually,  but  our  scheduling  tool  will  always 
propose  to  move  packs  or  products  rather  than  BIN.  We   also  have   no  transfer 
order for BINs. 
 
There  are  probably  lots  of  others  small  needs  that  are  not  covered  by this  analysis.  Our 
goal  is to propose a solution for solid foundations, not to cover all possible logistic scenarii. 
If foundations are strong, it should not be complex to add more features in extra modules. 
 

Misc points
1. MTS/MTO should be managed at the stock.move level 
 
  ­ remove MTS/MTO from sale order lines, replace it by a route_id field 
  ­ remove MTS/MTO from procurements (a procurement is always MTO) 
  ­ put MTS/MTO on the stock.move 
  ­ add route_id in procurement.group 
  ­ add "sale", a fields.boolean on procurement in sale module (this 
route is selectable in the sale.order) 
 
The MTS/MTO selection field on the sale order line is replaced by a 
route_id field on sale.order.line (with domain [('sale','=',True)]) 
 
This would allow to select "Drop­Shipping" at the sale order line by 
selecting "Drop­Shipping" route. 
 
We consider that all procurements are MTO.  
For tasks, add a field.boolean on product.product "Create Task Automatically". The 
procurement will use this field to know if it's a task or nothing. 
 
The default on stock.move is MTS 
 
 

48/51 
2. procurements are created by MTO stock.move, not by pull rules 
 
Create procurements based on stock.move as MTO (when the move is 
confirmed). If a stock.move is MTS, no procurement is created. 
 
A pull rule should not create a procurement on the source location of a 
stock.move (­­> the procurement is automatically created by the 
stock.move itself) 
 
The scheduler should look to all confirmed stock.move and try to reserve 
them. (to test further) 
 
 
3. Merge trunk­wmsimplement­seduce­fp into trunk­wmsimplement­seduce 
 
So that we have only one branch: trunk­wmsimplement­seduce­fp (did opposite) 
 
4. Cleaning 
 
[QDP] Remove file: stock/stock_fifo_lifo.py 
Remove module stock_location_sale 
 
 
5. Module sale 
 
The "sale" module should create the procurement, not sale_stock 
The sale_stock module should be removed to the minimum: 
  ­ property handling 
  ­ views (like open delivery orders) 
 
6. Groups: 
 
when a stock.move is confirmed, if no picking_id is associated; 
  ­ find a confirmed picking when same source_destination and group_id 
  ­ if no group_id or no picking exists: create picking 
if the stock.move is MTO, create a procurement at the source location. 
 
Create group when picking is created without group (picking confirm) 
 
[JCO] 7. MRP 

49/51 
 
No need to create a stock.picking before the manufacturing order, the 
removal strategy will do the job. Remove this extra step,  
remove stock_auto_picking module. 
 
8. Purchase 
 
Merge the code of CSN that makes the difference between "Draft Purchase 
Orders" and "Request for Quotation". 
 
When a procurement have to buy something, it tries to add the line to an 
existing purchase order that is still in "Draft Purchase" for the same 
supplier. 
 
[QDP] 9. Clean Stock.picking Invoicing 
 
Remove all invoice_... stuff from stock module. 
 
Just create one method in sale_stock allowing to create an invoice from 
a stock.picking. ­­> no more hooks. 
 
[QDP] 10. Costing 
Change costing method on product: average/standard/real costs 
implement the stock valuation 
 
11. do not link stock.move with sale order lines 
 
beacause it's not needed, procurement group does the trick 

50/51 
 

Raised points to include in the doc


 
● ease the computation of virtual stock at a given date → explained in the quants 
section: sum of quants+move not done. 
● do we need to NOT manage bins as sub­location because it totally explodes the 
number of locations to manage (there are no difference between exploding the 
number of bins or locations) 
○ Bin should help manage volume of product (to know that big one goes here, 
small here 
○ Help to manage the packaging / packing 
○ Ex:  
■ Bin A2 : one palet of 10  boxes of 100 product A 
■ Bin A1 :  256 Product A In bulk 
○ We think bin should be locations, not a separate concepts as their 
behaviour is exactly the same than locations: inventories on bin, 
source/destination of a move, capacity constraints, subject to removal or put 
away strategies, etc. 
● Packing and packaging management => Know how are packaged to 10’000 
Product A (boxes of 100, palet,...) => The goal is to optimize the packing operation 
when deliver → tooltip added in the picking screen on a product 
● Need a scenario on how we deal with a quantity propagation in chained moves: 
TODO 
● When do we close the workflow of the purchase order (As the SO close when ship 
is done): → check 2.13 
○ In case of one step reception 
○ In case of 2 steps (supplier ­> input ­> stock) 
○ In case of quality check (supplier ­> input ­> quality ­> stock) 
○ In case of cross­docking (supplier ­> input ­> cross­docking) 
● On packing operation, think to take care of the carrier/transporter => You want 
probably to group by customer AND carrier when organizing your packing → 
Explained in the waving strategies. 
● comment gèrer la notion de ownership ? info sur les Quants ou info sur la location? 
qd et­ce que ca doit être valorisé (si ca doit l’être)? → info sur la location → 7.2.5 
● improve the replenishment management 
○ Can you provide an example of what would you like to improve? 
 
Link to the docs (draft) written by Camptocamp before putting it here in this current doc: 
https://docs.google.com/document/d/1u7i2_llgqzSbNbS4R6eVGjr4o59jfwvMeALDLml_RG
E/edit?usp=sharing 

51/51 

You might also like