805
805
# check if ongoing packing are present, if present, we do not validate the draft one, the shipping is not finished
807
linked_packing_ids = pick_obj.search(cr, uid, [('backorder_id', '=', draft_packing.id)], context=context)
808
for linked_packing in pick_obj.browse(cr, uid, linked_packing_ids, context=context):
809
if linked_packing.state not in ('done','cancel'):
807
linked_packing_ids = pick_obj.search(cr, uid, [('backorder_id', '=', draft_packing.id),
808
('state', 'not in', ['done', 'cancel'])], context=context)
809
if linked_packing_ids:
813
813
# trigger the workflow for draft_picking
1085
1085
_inherit = 'stock.picking'
1086
1086
_name = 'stock.picking'
1088
def unlink(self, cr, uid, ids, context=None):
1090
unlink test for draft
1092
data = self.has_picking_ticket_in_progress(cr, uid, ids, context=context)
1093
if [x for x in data.values() if x]:
1094
raise osv.except_osv(_('Warning !'), _('Some Picking Tickets are in progress. Return products to stock from ppl and shipment and try again.'))
1096
return super(stock_picking, self).unlink(cr, uid, ids, context=context)
1088
1098
def _hook_picking_get_view(self, cr, uid, ids, context=None, *args, **kwargs):
1089
1099
pick = kwargs['pick']
1214
1224
validate or not the draft picking ticket
1227
move_obj = self.pool.get('stock.move')
1216
1229
for draft_picking in self.browse(cr, uid, ids, context=context):
1217
1230
# the validate function should only be called on draft picking ticket
1218
1231
assert draft_picking.subtype == 'picking' and draft_picking.state == 'draft', 'the validate function should only be called on draft picking ticket objects'
1219
1232
#check the qty of all stock moves
1220
1233
treat_draft = True
1221
for move in draft_picking.move_lines:
1222
if move.product_qty != 0.0 and move.state != 'done':
1234
move_ids = move_obj.search(cr, uid, [('picking_id', '=', draft_picking.id),
1235
('product_qty', '!=', 0.0),
1236
('state', 'not in', ['done', 'cancel'])], context=context)
1225
1240
if treat_draft:
1226
1241
# then all child picking must be fully completed, meaning:
1227
1242
# - all picking must be 'completed'
1228
1243
# completed means, we recursively check that next_step link object is cancel or done
1229
# TODO should use has_picking_ticket_in_progress()
1230
for picking in draft_picking.backorder_ids:
1231
# take care, is_completed returns a dictionary
1232
if not picking.is_completed()[picking.id]:
1244
if self.has_picking_ticket_in_progress(cr, uid, [draft_picking.id], context=context)[draft_picking.id]:
1236
1247
if treat_draft:
1237
1248
# - all picking are completed (means ppl completed and all shipment validated)
1907
1918
db_date_format = date_tools.get_db_date_format(cr, uid, context=context)
1909
1920
for obj in self.browse(cr, uid, ids, context=context):
1910
if obj.backorder_ids:
1911
raise osv.except_osv(_('Warning !'), _('You cannot convert a picking which has already been started.'))
1921
# the convert function should only be called on draft picking ticket
1922
assert obj.subtype == 'picking' and obj.state == 'draft', 'the convert function should only be called on draft picking ticket objects'
1923
if self.has_picking_ticket_in_progress(cr, uid, [obj.id], context=context)[obj.id]:
1924
raise osv.except_osv(_('Warning !'), _('Some Picking Tickets are in progress. Return products to stock from ppl and shipment and try again.'))
1913
1926
# log a message concerning the conversion
1914
1927
new_name = self.pool.get('ir.sequence').get(cr, uid, 'stock.picking.out')
1921
1934
# all destination location of the stock moves must be output location of warehouse - lot_output_id
1922
1935
# if corresponding sale order, date and date_expected are updated to rts + shipment lt
1923
1936
for move in obj.move_lines:
1924
vals = {'location_dest_id': obj.warehouse_id.lot_output_id.id,}
1937
# was previously set to confirmed/assigned, otherwise, when we confirm the stock picking,
1938
# using draft_force_assign, the moves are not treated because not in draft
1939
# and the corresponding chain location on location_dest_id was not computed
1940
# we therefore set them back in draft state before treatment
1941
vals = {'state': 'draft'}
1942
# If the move comes from a DPO, don't change the destination location
1944
vals.update({'location_dest_id': obj.warehouse_id.lot_output_id.id})
1925
1946
if obj.sale_id:
1927
1948
shipment_lt = fields_tools.get_field_from_company(cr, uid, object=self._name, field='shipment_lead_time', context=context)
1928
1949
rts = datetime.strptime(obj.sale_id.ready_to_ship_date, db_date_format)
1929
1950
rts = rts + relativedelta(days=shipment_lt or 0)
1930
1951
rts = rts.strftime(db_date_format)
1931
vals.update({'date': rts, 'date_expected': rts})
1952
vals.update({'date': rts, 'date_expected': rts, 'state': 'draft'})
1932
1953
move.write(vals, context=context)
1933
1955
# trigger workflow
1934
1956
self.draft_force_assign(cr, uid, [obj.id])
2454
2476
# check the state of the picking
2455
2477
for picking in self.browse(cr, uid, ids, context=context):
2456
# if draft and all qty are still there, we can cancel it without further checks
2478
# if draft and shipment is in progress, we cannot cancel
2457
2479
if picking.subtype == 'picking' and picking.state in ('draft',):
2458
for move in picking.move_lines:
2459
if move.product_qty != move.sale_line_id.product_uom_qty:
2460
raise osv.except_osv(_('Warning !'), _('The shipment process has already started! Return products to stock from ppl and shipment and try to cancel again.'))
2480
if self.has_picking_ticket_in_progress(cr, uid, [picking.id], context=context)[picking.id]:
2481
raise osv.except_osv(_('Warning !'), _('Some Picking Tickets are in progress. Return products to stock from ppl and shipment and try to cancel again.'))
2461
2482
return super(stock_picking, self).action_cancel(cr, uid, ids, context=context)
2462
2483
# if not draft or qty does not match, the shipping is already in progress
2463
2484
if picking.subtype == 'picking' and picking.state in ('done',):
2724
def default_get(self, cr, uid, fields, context=None):
2726
Set default values according to type and subtype
2731
res = super(stock_move, self).default_get(cr, uid, fields, context=context)
2733
if 'warehouse_id' in context and context.get('warehouse_id'):
2734
warehouse_id = context.get('warehouse_id')
2736
warehouse_id = self.pool.get('stock.warehouse').search(cr, uid, [], context=context)[0]
2737
res.update({'location_output_id': self.pool.get('stock.warehouse').browse(cr, uid, warehouse_id, context=context).lot_output_id.id})
2739
loc_virtual_ids = self.pool.get('stock.location').search(cr, uid, [('name', '=', 'Virtual Locations')])
2740
loc_virtual_id = len(loc_virtual_ids) > 0 and loc_virtual_ids[0] or False
2741
res.update({'location_virtual_id': loc_virtual_id})
2743
if 'type' in context and context.get('type', False) == 'out':
2744
loc_stock_id = self.pool.get('stock.warehouse').browse(cr, uid, warehouse_id, context=context).lot_stock_id.id
2745
res.update({'location_id': loc_stock_id})
2747
if 'subtype' in context and context.get('subtype', False) == 'picking':
2748
loc_packing_id = self.pool.get('stock.warehouse').browse(cr, uid, warehouse_id, context=context).lot_packing_id.id
2749
res.update({'location_dest_id': loc_packing_id})
2750
elif 'subtype' in context and context.get('subtype', False) == 'standard':
2751
loc_packing_id = self.pool.get('stock.warehouse').browse(cr, uid, warehouse_id, context=context).lot_output_id.id
2752
res.update({'location_dest_id': loc_packing_id})
2703
2756
_columns = {'from_pack': fields.integer(string='From p.'),
2704
2757
'to_pack': fields.integer(string='To p.'),
2705
2758
'pack_type': fields.many2one('pack.type', string='Pack Type'),
2724
2777
'is_keep_cool': fields.function(_vals_get, method=True, type='boolean', string='Keep Cool', multi='get_vals',),
2725
2778
'is_narcotic': fields.function(_vals_get, method=True, type='boolean', string='Narcotic', multi='get_vals',),
2726
2779
'sale_order_line_number': fields.function(_vals_get, method=True, type='integer', string='Sale Order Line Number', multi='get_vals_X',), # old_multi get_vals
2780
# Fields used for domain
2781
'location_virtual_id': fields.many2one('stock.location', string='Virtual location'),
2782
'location_output_id': fields.many2one('stock.location', string='Output location'),
2853
class procurement_order(osv.osv):
2855
procurement order workflow
2857
_inherit = 'procurement.order'
2859
def _hook_check_mts_on_message(self, cr, uid, context=None, *args, **kwargs):
2861
Please copy this to your module's method also.
2862
This hook belongs to the _check_make_to_stock_product method from procurement>procurement.py>procurement.order
2864
- allow to modify the message written back to procurement order
2866
message = super(procurement_order, self)._hook_check_mts_on_message(cr, uid, context=context, *args, **kwargs)
2867
procurement = kwargs['procurement']
2868
if procurement.move_id.picking_id.state == 'draft' and procurement.move_id.picking_id.subtype == 'picking':
2869
message = _("Shipment Process in Progress.")