2 I confirm outgoing shipment of 130 kgm Ice-cream.
4 !workflow {model: stock.picking, action: button_confirm, ref: outgoing_shipment}
6 I check shipment details after confirmed.
8 !python {model: stock.picking}: |
9 shipment = self.browse(cr, uid, ref("outgoing_shipment"))
10 assert shipment.state == "confirmed", "Shipment should be confirmed."
11 for move_line in shipment.move_lines:
12 assert move_line.state == "confirmed", "Move should be confirmed."
15 Now I check vitual stock of Ice-cream after confirmed outgoing shipment.
17 !python {model: product.product}: |
18 product = self.browse(cr, uid, ref('product_icecream'), context=context)
19 product.virtual_available == -30, "Vitual stock is not updated."
22 I confirm incomming shipment of 50 kgm Ice-cream.
24 !workflow {model: stock.picking, action: button_confirm, ref: incomming_shipment}
26 I receive 40kgm Ice-cream so I make backorder of incomming shipment for 40 kgm.
28 !python {model: stock.partial.picking}: |
29 context.update({'active_model': 'stock.picking', 'active_id': ref('incomming_shipment'), 'active_ids': [ref('incomming_shipment')]})
31 !record {model: stock.partial.picking, id: partial_incomming}:
34 product_id: product_icecream
35 product_uom: product.product_uom_kgm
36 move_id: incomming_shipment_icecream
37 location_id: location_convenience_shop
38 location_dest_id: location_refrigerator
40 !python {model: stock.partial.picking }: |
41 self.do_partial(cr, uid, [ref('partial_incomming')], context=context)
43 I check backorder shipment after received partial shipment.
45 !python {model: stock.picking}: |
46 shipment = self.browse(cr, uid, ref("incomming_shipment"))
47 backorder = shipment.backorder_id
48 assert backorder, "Backorder should be created after partial shipment."
49 assert backorder.state == 'done', "Backorder should be close after received."
50 for move_line in backorder.move_lines:
51 assert move_line.product_qty == 40, "Qty in backorder does not correspond."
52 assert move_line.state == 'done', "Move line of backorder should be closed."
54 I receive another 10kgm Ice-cream.
56 !record {model: stock.partial.picking, id: partial_incomming}:
59 product_id: product_icecream
60 product_uom: product.product_uom_kgm
61 move_id: incomming_shipment_icecream
62 location_id: location_convenience_shop
63 location_dest_id: location_refrigerator
65 !python {model: stock.partial.picking }: |
66 self.do_partial(cr, uid, [ref('partial_incomming')], context=context)
69 I check incomming shipment after received.
71 !python {model: stock.picking}: |
72 shipment = self.browse(cr, uid, ref("incomming_shipment"))
73 assert shipment.state == 'done', "shipment should be close after received."
74 for move_line in shipment.move_lines:
75 assert move_line.product_qty == 10, "Qty does not correspond."
76 assert move_line.state == 'done', "Move line should be closed."
79 I return last incomming shipment for 10 kgm Ice-cream.
81 !record {model: stock.return.picking, id: return_incomming}:
84 !python {model: stock.return.picking }: |
85 self.create_returns(cr, uid, [ref('return_incomming')], context=context)
87 I cancel incomming shipment after return it.
89 !python {model: stock.picking}: |
90 self.action_cancel(cr, uid, [ref("incomming_shipment")], context=context)
92 I make invoice of backorder of incomming shipment.
94 !python {model: stock.invoice.onshipping}: |
95 shipment = self.pool.get('stock.picking').browse(cr, uid, ref("incomming_shipment"))
96 context.update({'active_model': 'stock.picking', 'active_id': shipment.backorder_id.id, 'active_ids': [shipment.backorder_id.id]})
98 !record {model: stock.invoice.onshipping, id: invoice_incomming}:
101 !python {model: stock.invoice.onshipping }: |
102 self.create_invoice(cr, uid, [ref('invoice_incomming')], context=context)
104 I check invoice state of backorder of incomming shipment.
106 !python {model: stock.picking}: |
107 shipment = self.browse(cr, uid, ref("incomming_shipment"))
108 assert shipment.backorder_id.invoice_state == 'invoiced', 'Invoice state is not upadted.'
110 I check availabile stock after received incomming shipping.
112 !python {model: product.product}: |
113 product = self.browse(cr, uid, ref('product_icecream'), context=context)
114 assert product.qty_available == 140, "Stock does not correspond."
115 assert product.virtual_available == 10, "Vitual stock does not correspond."
117 I split incomming shipment into lots. each lot contain 10 kgm Ice-cream.
119 !python {model: stock.picking}: |
120 shipment = self.browse(cr, uid, ref("incomming_shipment"))
121 move_ids = [x.id for x in shipment.backorder_id.move_lines]
122 context.update({'active_model': 'stock.move', 'active_id': move_ids[0], 'active_ids': move_ids})
124 !record {model: stock.move.split, id: split_lot_incomming}:
126 - name: incoming_lot0
128 - name: incoming_lot1
130 - name: incoming_lot2
132 - name: incoming_lot3
136 !python {model: stock.move.split }: |
137 self.split_lot(cr, uid, [ref('split_lot_incomming')], context=context)
139 I check move lines after spliting
141 !python {model: stock.move}: |
142 lot = self.pool.get('stock.move.split').browse(cr, uid, ref('split_lot_incomming'), context=context)
143 lot_ids = self.pool.get('stock.production.lot').search(cr, uid, [('name','in',[x.name for x in lot.line_ids])])
144 assert len(lot_ids) == 4, 'lots of incomming shipment are not correspond.'
145 move_ids = self.search(cr, uid, [('location_dest_id','=',ref('location_refrigerator')),('prodlot_id','in',lot_ids)])
146 assert len(move_ids) == 4, 'move lines are not correspond per prodcution lot after splited.'
147 for move in self.browse(cr, uid, move_ids, context=context):
148 assert move.prodlot_id.name in ['incoming_lot0', 'incoming_lot1', 'incoming_lot2', 'incoming_lot3'], "lot does not correspond."
149 assert move.product_qty == 10, "qty does not correspond per production lot."
150 context.update({'active_model':'stock.move', 'active_id':move_ids[0],'active_ids': move_ids})
152 I check the stock valuation account entries.
154 !python {model: account.move}: |
155 incomming_shipment = self.pool.get('stock.picking').browse(cr, uid, ref('incomming_shipment'), context=context)
156 account_move_ids = self.search(cr, uid, [('ref','=',incomming_shipment.name)])
157 assert len(account_move_ids), "account move should be created."
158 account_move = self.browse(cr, uid, account_move_ids[0], context=context)
159 assert len(account_move.line_id) == len(incomming_shipment.move_lines) + 1, 'accuont entries are not correspond.'
160 for account_move_line in account_move.line_id:
161 for stock_move in incomming_shipment.move_lines:
162 if account_move_line.account_id.id == stock_move.product_id.property_stock_account_input.id:
163 assert account_move_line.credit == 800.0, "Credit amount does not correspond."
164 assert account_move_line.debit == 0.0, "Debit amount does not correspond."
166 assert account_move_line.credit == 0.0, "Credit amount does not correspond."
167 assert account_move_line.debit == 800.0, "Debit amount does not correspond."
169 I consume 1 kgm ice-cream from each incoming lots into internal production.
171 !record {model: stock.move.consume, id: consume_lot_incomming}:
173 location_id: location_refrigerator
175 !python {model: stock.move.consume}: |
176 self.do_move_consume(cr, uid, [ref('consume_lot_incomming')], context=context)
178 I scrap 10 gm ice-cream from each incoming lots into scrap location.
180 !record {model: stock.move.scrap, id: scrap_lot_incomming}:
183 !python {model: stock.move.scrap}: |
184 self.move_scrap(cr, uid, [ref('scrap_lot_incomming')], context=context)
186 I check stock in scrap location and refrigerator location.
188 !python {model: stock.location}: |
189 ctx = {'product_id': ref('product_icecream')}
190 refrigerator_location = self.pool.get('stock.location').browse(cr, uid, ref('location_refrigerator'), context=ctx)
191 assert refrigerator_location.stock_real == 135.96, 'stock does not correspond in refrigerator location.'
192 scrapped_location = self.browse(cr, uid, ref('stock_location_scrapped'), context=ctx)
193 assert scrapped_location.stock_real == 0.010*4, 'scraped stock does not correspond in scrap location.'
196 I check availabile stock after consumed and scraped.
198 !python {model: product.product}: |
199 product = self.browse(cr, uid, ref('product_icecream'), context=context)
200 assert product.qty_available == 135.96, "Stock does not correspond."
201 assert round(product.virtual_available, 2) == 5.96, "Vitual stock does not correspond."
203 I trace all incoming lots.
205 !python {model: stock.production.lot }: |
206 lot = self.pool.get('stock.move.split').browse(cr, uid, ref('split_lot_incomming'), context=context)
207 lot_ids = self.search(cr, uid, [('name', 'in', [x.name for x in lot.line_ids])])
208 self.action_traceability(cr, uid, lot_ids, context=context)
210 I check outgoing shipment after stock availablity in refrigerator.
212 !python {model: stock.picking}: |
213 shipment = self.browse(cr, uid, ref("outgoing_shipment"), context=context)
214 self.pool.get('stock.move').action_assign(cr, uid, [x.id for x in shipment.move_lines]) #TOFIX: assignment of move lines should be call before testing assigment otherwise picking never gone in assign state
215 #TOFIX: shipment should be assigned if stock available
216 #assert shipment.state == "assigned", "Shipment should be assigned."
217 #for move_line in shipment.move_lines:
218 # assert move_line.state == "assigned", "Move should be assigned."
219 self.force_assign(cr, uid, [shipment.id])
221 I deliver 5kgm Ice-cream to customer so I make partial deliver
223 !python {model: stock.partial.move}: |
224 context.update({'active_model': 'stock.move', 'active_id': ref('outgoing_shipment_icecream'), 'active_ids': [ref('outgoing_shipment_icecream')]})
226 !record {model: stock.partial.move, id: partial_outgoing_icecream}:
229 product_id: product_icecream
230 product_uom: product.product_uom_kgm
231 move_id: outgoing_shipment_icecream
232 location_id: location_refrigerator
233 location_dest_id: location_delivery_counter
235 !python {model: stock.partial.move }: |
236 self.do_partial(cr, uid, [ref('partial_outgoing_icecream')], context=context)
239 I packing outgoing shipment into box per 10kgm with unique tracking lot.
241 !python {model: stock.move}: |
242 stock_split = self.pool.get('stock.split.into')
243 move = self.browse(cr, uid, ref('outgoing_shipment_icecream'), context=context)
244 context.update({'active_model': 'stock.move', 'active_id': move.id, 'active_ids': [move.id]})
245 total_qty = move.product_qty
248 split_id = stock_split.create(cr, uid, {'quantity': split_qty}, context=context)
249 stock_split.split(cr, uid, [split_id], context=context)
250 total_qty -= split_qty
252 I deliver outgoing shipment.
254 !python {model: stock.partial.picking}: |
255 context.update({'active_model': 'stock.picking', 'active_id': ref('outgoing_shipment'), 'active_ids': [ref('outgoing_shipment')]})
257 !record {model: stock.partial.picking, id: partial_outgoing}:
258 picking_id: outgoing_shipment
260 !python {model: stock.partial.picking }: |
261 self.do_partial(cr, uid, [ref('partial_outgoing')], context=context)
264 I check outgoing shipment after deliver.
266 !python {model: stock.picking}: |
267 shipment = self.browse(cr, uid, ref("outgoing_shipment"), context=context)
268 assert shipment.state == "done", "Shipment should be closed."
269 for move_line in shipment.move_lines:
270 assert move_line.state == "done", "Move should be closed."
272 I check availabile stock after deliver.
274 !python {model: product.product}: |
275 product = self.browse(cr, uid, ref('product_icecream'), context=context)
276 assert round(product.qty_available, 2) == 5.96, "Stock does not correspond."
277 assert round(product.virtual_available, 2) == 5.96, "Vitual stock does not correspond."