Untitled
unknown
ruby
a year ago
39 kB
13
Indexable
require_relative '../../../app/LA/entities/aggregator_value_vo'
require_relative '../../lib/outbound_request_type_utility'
require_relative '../factories/external_client_factory'
class TransferListWsnLocationAggregation < TransferListWidLocationAggregation
TRANSACTION_NAMESPACE_LIST = [StorageNamespaceEnum::SHIP_GROUPS, StorageNamespaceEnum::RESERVATIONS,
StorageNamespaceEnum::INVENTORY_ITEMS]
RESERVE_RESOURCE_LOCK_TTL = 300
RESERVE_RESOURCE_LOCK_WAIT_TIME = 1000
RESERVE_RESOURCE_LOCK_RETRY_COUNT = 3
RESERVE_RESHUFFLE_LIMIT = 500
INVENTORY_ITEM = "InventoryItem"
def initialize(warehouse_id)
@warehouse_id = warehouse_id
end
# request1 = {"wsn_to_pick" => 'wsn_entered', "partial_pick" => true,
# 'source_loaction_id' => 'source_location'}
def resolve_unpicked_items(pickable_items, transfer_list, picked_inventories = [], flow = nil)
transfer_list_items = []
pickable_items = pickable_items.is_a?(Array) ? pickable_items : pickable_items.nil? ? [] : [pickable_items]
tote_label_id_map = get_tote_label_id_map(pickable_items)
movement_request_vo = movement_request_service.get_vos_by_ids([transfer_list.movement_request_id]).first
outbound_request_type = (WorkFlowEntityType::OUTBOUND_REQUEST == movement_request_vo.group_type)
transfer_list_items << pickable_items.collect do |pickable_item|
list_items = []
wsn = pickable_item[:wsn_to_pick]
if wsn
wh_serial_number = wsn_service.validate_and_fetch_wsn(wsn)
begin
inventory_item = InventoryModuleDataService.
get_inventory_item_by_wh_serial_number_id_and_quantity!(wh_serial_number.id, 1)
rescue ActiveRecord::RecordNotFound => e
inventory_item = nil
end
list_items << if inventory_item.present?
validate_scanned_wsn_warehouse(inventory_item, transfer_list, wsn)
validate_duplicate_wsn(inventory_item, transfer_list, wsn)
item = transfer_list_service.
get_transfer_list_item_by_transfer_list_id_and_inventory_item_id(transfer_list.id,
inventory_item.id)
picked_inventories << item[:inventory_item_id] if item.present?
item.present? ? item : validate_picked_item_and_swap(pickable_item, transfer_list, wsn,
inventory_item, outbound_request_type,
picked_inventories, flow)
else
# change incoming payload
swap_wsns(wsn, pickable_item[:source_loaction_id], transfer_list, picked_inventories, flow)
end
else
wid = pickable_item[:wid]
product_detail_vo = get_product_details_by_wid(wid)
product_detail_id = product_detail_vo[0][:id]
imei_array = pickable_item[:imei]
quantity = pickable_item[:quantity].to_i
tote = pickable_item[:tote]
shelf = pickable_item[:source_loaction_id]
logger.debug("Processing WID: #{wid},Product Detail ID: #{product_detail_id} , Quantity: #{quantity},TOTE: #{tote}, Shelf : #{shelf} IMEI_Array, :#{imei_array}")
wsn_vos = []
if imei_array.present?
imei_array.each do |imei|
next if imei.nil?
wsn_vo = wh_serial_number_data_service.get_wsn_vos_by_attribute_name_and_attribute_values_and_product(WhSerialNumberAttributeNameEnum::SERIAL_NUMBER, imei, product_detail_id)
unless wsn_vo.empty?
wsn_vos += wsn_vo
end
end
end
missing_quantity = quantity - wsn_vos.size
new_wsns = []
if missing_quantity > 0
# Creating missing WSNs in a single API call
idempotence_key = "#{product_detail_id}_#{tote}_#{shelf}_#{transfer_list.id}_#{missing_quantity}"
payload = {
product_detail_id: product_detail_id,
idempotence_key: idempotence_key,
quantity: missing_quantity
}
begin
new_wsn_vos = b2b_warehouse_client.create_wsn_v1(payload)
if new_wsn_vos.is_a?(Array) && new_wsn_vos.any?
new_wsns = new_wsn_vos.map { |vo| vo['display_id'] }
else
logger.error("Unexpected wsn_vo response structure or empty response: #{new_wsn_vos.inspect}")
raise "WSN creation failed due to invalid response structure"
end
rescue StandardError => e
logger.error("Failed to create WSN VOs for payload: #{payload}. Error: #{e.message}")
raise "WSN creation failed : #{e.message}"
end
end
all_wsns = (wsn_vos.map { |vo| vo.display_id } + new_wsns).take(quantity)
all_wsns.each_with_index do |wsn, i|
wh_serial_number = wsn_service.validate_and_fetch_wsn(wsn)
begin
inventory_item = InventoryModuleDataService.
get_inventory_item_by_wh_serial_number_id_and_quantity!(wh_serial_number.id, 1)
rescue ActiveRecord::RecordNotFound => e
inventory_item = nil
end
list_items << if inventory_item.present?
validate_scanned_wsn_warehouse(inventory_item, transfer_list, wsn)
validate_duplicate_wsn(inventory_item, transfer_list, wsn)
item = transfer_list_service.
get_transfer_list_item_by_transfer_list_id_and_inventory_item_id(transfer_list.id,
inventory_item.id)
picked_inventories << item[:inventory_item_id] if item.present?
item.present? ? item : validate_picked_item_and_swap(pickable_item, transfer_list, wsn,
inventory_item, outbound_request_type,
picked_inventories, flow)
else
# change incoming payload
swap_wsns(wsn, pickable_item[:source_loaction_id], transfer_list, picked_inventories, flow)
end
end
end
list_items.flatten!
if pickable_item[:imei].present?
list_items.each_with_index do |item_taken, i|
item_taken[:imei] = i < pickable_item[:imei].length ? pickable_item[:imei][i] : nil
end
end
list_items.each do |item|
item[:tote_id] = tote_label_id_map[pickable_item[:tote]] unless pickable_item[:tote].nil?
end
list_items
end
transfer_list_items.flatten
end
# request1 = {"wsn_to_put" => 'wsn_entered', "partial_pick" => true,
# 'destination_location_id' => 'destination_location'}
def resolve_putable_items(putable_items, transfer_list, puted_inventories=[])
transfer_list_items = []
putable_items = putable_items.is_a?(Array) ? putable_items : putable_items.nil? ? [] : [putable_items]
tote_label_id_map = get_tote_label_id_map(putable_items)
transfer_list_items << putable_items.collect do |putable_item|
list_items = []
wsn = putable_item[:wsn_to_put]
tote_label = putable_item[:tote] unless tote_label_id_map.nil?
wh_serial_number = wsn_service.validate_and_fetch_wsn(wsn)
inventory_item = InventoryModuleDataService.
get_inventory_item_by_warehouse_id_and_wh_serial_number_id(transfer_list.warehouse_id, wh_serial_number.id)
raise SupplyChainError.new(:message => "Inventory item with wsn: #{wsn} is not found") if inventory_item.blank?
item = transfer_list_service.get_transfer_list_item_by_transfer_list_id_and_inventory_item_id(transfer_list.id,
inventory_item.id)
raise SupplyChainError.new(:message => "Wsn #{wsn} does not belong to this TL") if item.blank?
if (!tote_label.nil? && item[:tote_id] != tote_label_id_map[tote_label])
raise SupplyChainError.new(:message => "Wsn #{wsn} does not belong to tote #{tote_label}")
end
item[:destination_location_id] =
get_and_validate_destination_location(putable_item[:destination_location_id], transfer_list.destination_area,
@warehouse_id).id
list_items << item
puted_inventories << item[:inventory_item_id]
list_items.flatten
end
transfer_list_items.flatten
end
# return inventory item ids corresponding to wsn
def validate_and_resolve_inventory_item_to_pack(transfer_list, input, input_type)
wsns = input.collect { |items| items[input_type] }.flatten
wsn_id_map = Hash[wsns.map { |wsn| [wsn_service.get_wsn_vo_by_display_id(wsn).id, wsn] }]
inventory_item_id_maps = Hash[wsn_id_map.keys.map { |wh_serial_number_id| [inventory_service.get_vo_by_wsn_id(wh_serial_number_id).id, wh_serial_number_id] }]
inventory_items_in_tl = transfer_list_service.get_inventory_items_by_transfer_list_id(transfer_list.id).collect { |item| item[:inventory_item_id] }
inventory_items_not_in_tl = inventory_item_id_maps.keys - inventory_items_in_tl
if inventory_items_not_in_tl.present?
wsns_not_in_tl = inventory_items_not_in_tl.collect do |inventory_item_id|
wsn_id_map[inventory_item_id_maps[inventory_item_id]]
end
raise WsnNotPartOfPicklistError.new(wsns_not_in_tl)
end
movement_request = movement_request_service.get_vos_by_ids([transfer_list.movement_request_id]).first
outbound_request_items_for_tl = outbound_request_service.get_item_vos_by_outbound_request_id_inventory_item_ids(movement_request.group_id, inventory_items_in_tl).select { |item| item.status == OutboundRequestItemStatusEnum::IN_CONSIGNMENT }
inventory_item_ids = outbound_request_items_for_tl.collect(&:inventory_item_id)
unpacked_inventory_item_ids = inventory_item_ids - inventory_item_id_maps.keys
[inventory_item_id_maps.keys, unpacked_inventory_item_ids]
end
def item_aggregator_fields
['aggregator_value_id', 'status', 'source_location_id', 'destination_location_id', 'tote_id']
end
def putable_items_aggregator_fields
['tote_id', 'aggregator_value_id', 'status']
end
def is_serialized
false
end
def is_inv_swap_enabled_for_flow(outbound_request_type)
outbound_request_type = OutboundRequestTypeUtility.get_outbound_request_type(outbound_request_type)
config_hash = WarehouseService.settings.inventory_swapping_allowed_flows
if config_hash['ALL'].present? && (config_hash['ALL'].include?('ALL') || config_hash['ALL'].include?(outbound_request_type))
true
else
config_hash[@warehouse_id].present? && (config_hash[@warehouse_id].include?('ALL') || config_hash[@warehouse_id].include?(outbound_request_type))
end
end
def is_inv_swap_enabled_for_area(source_area)
storage_areas = WarehouseService.settings.inventory_swapping_restricted_areas
return storage_areas.none?{ |area| area == source_area }
end
private
def get_ready_to_pick_and_relabel_needed_inv_items(transfer_list_id)
ready_to_pick_tl_items =
transfer_list_service.get_inventory_item_id_and_transfer_list_item_by_transfer_list_id_and_item_status(
transfer_list_id, TransferListStatusEnum::READY_TO_PICK)
raise TransferListItemNotFoundError.new('No pickable items in this TL') if ready_to_pick_tl_items.empty?
inventory_service
.get_relabelling_required_map_for_inventory_item_ids(ready_to_pick_tl_items.collect{ |tli| tli[:inventory_item_id] })
.select{ |_k, v| v }.keys
end
def swap_inventories(wsn, storage_location, transfer_list, picked_inventories, picked_inv_item_vo, flow = nil)
# method to swap inventories for a outbound request
wid = wsn_service.get_wid_for_wsn(wsn)
is_relabeled = false
# get reserved inventory
reserved_inv_item_vo, transfer_list_items_map =
if storage_location.present?
begin
get_inventory_item_vo_using_aggregator(wsn, storage_location.first, transfer_list, wid, picked_inventories, is_relabeled)
rescue TransferListItemNotFoundError
seller_wid = wid_seller_mapping_data_service.get_fki_to_seller_wids_hash([wid])[wid]
raise TransferListItemNotFoundError.new("WSN : #{wsn} , Storage_location: #{storage_location} not available to pick") if seller_wid.nil?
is_relabeled = true
get_inventory_item_vo_using_aggregator(wsn, storage_location.first, transfer_list, seller_wid, picked_inventories, is_relabeled)
end
else
get_inventory_item_vo(wsn, transfer_list, wid, picked_inventories)
end
fetch_and_swap_inventories(transfer_list, picked_inv_item_vo, reserved_inv_item_vo, transfer_list_items_map, flow)
[transfer_list_items_map]
end
def fetch_and_swap_inventories(transfer_list, picked_inv_item_vo, reserved_inv_item_vo, transfer_list_items_map, flow = nil)
# method to fetch and swap inventory items
logger.info("Starting inventory swap - inventory id #{reserved_inv_item_vo.id} with #{picked_inv_item_vo.id}")
ResourceLock.hold!(ResourceLockNamespaceEnum::RESHUFFLE_RESOURCE_LOCK_NAME, {:warehouse_id => @warehouse_id}, nil,
RESERVE_RESOURCE_LOCK_TTL, RESERVE_RESOURCE_LOCK_WAIT_TIME, RESERVE_RESOURCE_LOCK_RETRY_COUNT) do
shard_manager.using_transaction(TRANSACTION_NAMESPACE_LIST) do
shard_manager.using_shard_for_warehouse_id(@warehouse_id) do
# picked and reserved inventory are in different storage location
if reserved_inv_item_vo.storage_location_id != picked_inv_item_vo.storage_location_id
update_aggregator_value(picked_inv_item_vo, reserved_inv_item_vo, transfer_list)
end
if picked_inv_item_vo.atp == 1
swap_if_inventory_is_promisable(picked_inv_item_vo, reserved_inv_item_vo, flow)
else
swap_if_inventory_is_not_promisable(picked_inv_item_vo, reserved_inv_item_vo)
end
# update in_transit info for inventory items
inventory_service.update_in_transit(reserved_inv_item_vo.id, 0, flow)
inventory_service.update_in_transit(picked_inv_item_vo.id, 1, flow)
# update inventory in return object
transfer_list_items_map[:inventory_item_id] = picked_inv_item_vo.id
end
end
end
logger.info("Completed inventory swap - inventory id #{reserved_inv_item_vo.id} with #{picked_inv_item_vo.id}")
transfer_list_items_map
end
def swap_if_inventory_is_promisable(picked_inv_item_vo, reserved_inv_item_vo, flow = nil)
# swapping inventory if picked inventory atp = 1
# update atp for inventory item
inventory_service.change_atp(picked_inv_item_vo.id, -1, flow)
inventory_service.change_atp(reserved_inv_item_vo.id, 1, flow)
# update outbound request item, movement request item and transfer list item for reserved inventory
update_inventory_in_reservations(picked_inv_item_vo, reserved_inv_item_vo)
end
def swap_if_inventory_is_not_promisable(picked_inv_item_vo, reserved_inv_item_vo)
# get outbound request item for picked inventory
picked_inv_outbound_request_item_vo = outbound_request_service.get_by_inventory_item_id(picked_inv_item_vo.id).
find { |item| ![OutboundRequestItemStatusEnum::CANCELLED, OutboundRequestItemStatusEnum::COMPLETED, OutboundRequestItemStatusEnum::LOST].include? item.status}
if picked_inv_outbound_request_item_vo.present?
# update outbound request item for picked inventory
update_inventory_in_outbound_request_item(picked_inv_outbound_request_item_vo, reserved_inv_item_vo)
# update movement request / task for picked inventory
update_picked_inventory_reservation(picked_inv_item_vo, reserved_inv_item_vo, picked_inv_outbound_request_item_vo.outbound_request_id)
else
# get transfer request item for picked inventory
picked_inv_transfer_request_item_vo = transfer_request_service.get_item_vo_by_inventory_item_id(picked_inv_item_vo.id).
find { |item| ![TransferRequestItemStatusEnum::CANCELLED, TransferRequestItemStatusEnum::COMPLETED, TransferRequestItemStatusEnum::LOST].include? item.status}
if picked_inv_transfer_request_item_vo.present?
# update transfer request item for picked inventory
update_inventory_in_transfer_request_item(picked_inv_transfer_request_item_vo, reserved_inv_item_vo)
# update movement request / task for picked inventory
update_picked_inventory_reservation(picked_inv_item_vo, reserved_inv_item_vo, picked_inv_transfer_request_item_vo.transfer_request_id)
else
raise InvalidInputError.new("Picked inventory #{picked_inv_item_vo.id} is reserved for flow other than Outbound/Transfer")
end
end
# update outbound and movement request item for reserved inventory
update_inventory_in_reservations(picked_inv_item_vo, reserved_inv_item_vo)
end
def update_inventory_in_reservations(picked_inv_item_vo, reserved_inv_item_vo)
# method to update picked inv in outbound request, movement request and transfer list tables
reserved_inv_outbound_request_item_vo = outbound_request_service.get_by_inventory_item_id(reserved_inv_item_vo.id).
find { |item| ![OutboundRequestItemStatusEnum::CANCELLED, OutboundRequestItemStatusEnum::COMPLETED, OutboundRequestItemStatusEnum::LOST].include? item.status}
reserved_inv_movement_request_item_vo = movement_request_service.get_movement_request_item_vos_by_inventory_item_ids([reserved_inv_item_vo.id]).
find { |item| ![MovementRequestItemStatusEnum::CANCELLED, MovementRequestItemStatusEnum::COMPLETED, MovementRequestItemStatusEnum::LOST].include? item.status}
reserved_inv_transfer_list_item_vo = transfer_list_service.get_transfer_list_items_by_movement_request_item_ids([reserved_inv_movement_request_item_vo.id]).first
update_inventory_in_outbound_request_item(reserved_inv_outbound_request_item_vo, picked_inv_item_vo)
update_inventory_in_movement_request_item(reserved_inv_movement_request_item_vo, picked_inv_item_vo)
update_details_in_transfer_list_item(reserved_inv_transfer_list_item_vo, picked_inv_item_vo)
end
def update_aggregator_value(picked_inv_item_vo, reserved_inv_item_vo, transfer_list)
# update aggregator_value in transfer list
reserved_inv_transfer_list_item_hash = transfer_list_service.get_transfer_list_item_by_transfer_list_id_and_inventory_item_id(transfer_list.id, reserved_inv_item_vo.id)
aggregator_value_hash = add_new_aggregator_value(transfer_list.id, picked_inv_item_vo.wid, picked_inv_item_vo.storage_location_id)
update_hash = {:aggregator_value_id => aggregator_value_hash[:id]}
transfer_list_service.update_transfer_list_item(reserved_inv_transfer_list_item_hash[:id], update_hash)
end
def add_new_aggregator_value(transfer_list_id, wid, storage_location_id)
# add new aggregator_value for picked inventory
storage_location_vo = storage_location_service.get_vos_by_ids([storage_location_id]).first
value = "#{storage_location_vo.label}|#{wid}"
insert_hash = {
:transfer_list_id => transfer_list_id,
:value => value
}
aggregator_value_dao.bulk_insert([insert_hash])
aggregator_value_dao.get_record_by_transfer_list_id_and_value(transfer_list_id, value)
end
def update_picked_inventory_reservation(picked_inv_item_vo, reserved_inv_item_vo, reservation_id)
# method to update movement request item / task for picked inventory item
# get movement request item for picked inv
picked_inv_movement_request_item_vo = movement_request_service.get_movement_request_item_vos_by_inventory_item_ids([picked_inv_item_vo.id]).
find { |item| ![MovementRequestItemStatusEnum::CANCELLED, MovementRequestItemStatusEnum::COMPLETED, MovementRequestItemStatusEnum::LOST].include? item.status}
if picked_inv_movement_request_item_vo.present?
# update movement request item for reserved inv
update_inventory_in_movement_request_item(picked_inv_movement_request_item_vo, reserved_inv_item_vo)
begin
# check if transfer list present for picked inventory. (If not present do nothing)
picked_inv_transfer_list_item_vo = transfer_list_service.get_transfer_list_items_by_movement_request_item_ids([picked_inv_movement_request_item_vo.id]).first
if picked_inv_transfer_list_item_vo.present?
update_details_in_transfer_list_item(picked_inv_transfer_list_item_vo, reserved_inv_item_vo)
end
rescue
nil
end
else
# get task item for picked inventory
picked_inv_task_item_vo = TaskModuleDataService::Task.where(:group_id => reservation_id,
:work_item_id => picked_inv_item_vo.id,
:work_item_type => INVENTORY_ITEM)
if picked_inv_task_item_vo.present?
# update task item for picked inventory
update_inventory_in_tasks(picked_inv_task_item_vo, reserved_inv_item_vo)
end
end
end
def update_inventory_in_outbound_request_item(outbound_request_item_vo, inventory_item_vo)
# update inventory in outbound request item
update_item_hash = {:inventory_item_id => inventory_item_vo.id, :source_storage_location_id => inventory_item_vo.storage_location_id}
outbound_request_service.update_outbound_request_item(outbound_request_item_vo.id, update_item_hash)
end
def update_inventory_in_transfer_request_item(transfer_request_item_vo, inventory_item_vo)
# update inventory in transfer request item
update_item_hash = {:inventory_item_id => inventory_item_vo.id, :from_storage_location_id => inventory_item_vo.storage_location_id}
transfer_request_service.update_items_by_ids(transfer_request_item_vo.id, update_item_hash)
end
def update_inventory_in_movement_request_item(movement_request_item_vo, inventory_item_vo)
# update inventory in movement request item
update_item_hash = {:inventory_item_id => inventory_item_vo.id, :source_storage_location_id => inventory_item_vo.storage_location_id}
movement_request_service.update_items_by_ids(movement_request_item_vo.id, update_item_hash)
end
def update_details_in_transfer_list_item(transfer_list_item_vo, inventory_item_vo)
# update inventory in transfer list item
update_item_hash = {:source_location_id => inventory_item_vo.storage_location_id}
transfer_list_service.update_transfer_list_item(transfer_list_item_vo.id, update_item_hash)
end
def update_inventory_in_tasks(tasks_vos, inventory_item_vo)
# update inventory in tasks
update_item_hash = {:work_item_id => inventory_item_vo.id}
for tasks_vo in tasks_vos
TaskModuleDataService::Task.where(:id => tasks_vo.id).first.update_attributes!(update_item_hash)
transfer_task_data_vo = TaskModuleDataService::TransferTaskData.where(:task_id => tasks_vo.id).first
if transfer_task_data_vo.present?
if transfer_task_data_vo.source_location_id.present?
update_hash = {:source_location_id => inventory_item_vo.storage_location_id}
TaskModuleDataService::TransferTaskData.where(:id => transfer_task_data_vo.id).first.update_attributes!(update_hash)
end
end
end
end
def swap_wsns(wsn, storage_location, transfer_list, picked_inventories, flow = nil)
wid = wsn_service.get_wid_for_wsn(wsn)
is_relabeled = false
begin
relabelling_inventory_item_ids = get_ready_to_pick_and_relabel_needed_inv_items(transfer_list.id)
relabelling_inventory_item_vos = relabelling_inventory_item_ids.empty? ? [] : inventory_service.get_vos_by_ids(relabelling_inventory_item_ids)
fki_to_alpha_seller_map = inventory_service.get_fki_to_alpha_wid_map(relabelling_inventory_item_vos.collect(&:wid).uniq)
rescue Warehouse::RecordNotFoundError => e
fki_to_alpha_seller_map = {}
end
inventory_item_vo, transfer_list_items_map =
if storage_location.present?
begin
get_inventory_item_vo_using_aggregator(wsn, storage_location.first, transfer_list, wid, picked_inventories, is_relabeled)
rescue TransferListItemNotFoundError
#seller_wid = wid_seller_mapping_data_service.get_fki_to_seller_wids_hash([wid])[wid]
seller_wid = fki_to_alpha_seller_map[wid]
raise TransferListItemNotFoundError.new("WSN : #{wsn} , Storage_location: #{storage_location} not available to pick") if seller_wid.nil?
is_relabeled = true
get_inventory_item_vo_using_aggregator(wsn, storage_location.first, transfer_list, seller_wid, picked_inventories, is_relabeled)
end
else
get_inventory_item_vo(wsn, transfer_list, wid, picked_inventories)
end
UtilityFactory.inventory_utility.fetch_and_swap_wsn(inventory_item_vo, wsn, is_relabeled, flow)
[transfer_list_items_map]
end
def get_inventory_item_vo_using_aggregator(wsn, storage_location, transfer_list, wid, picked_inventories, expected_relabel_status = false)
aggregation_value = storage_location + '|' + wid
begin
aggregator_value_vo = transfer_list_service.get_aggregator_value_vo_by_transfer_list_id_and_value(
transfer_list.id, aggregation_value)
rescue Warehouse::RecordNotFoundError => e
raise TransferListItemNotFoundError.new("WSN : #{wsn} , Storage_location: #{storage_location} not available to pick")
end
transfer_list_items_maps = transfer_list_service.
get_inventory_item_id_and_transfer_list_item_by_transfer_list_id_and_item_status_and_aggregator_value_id(transfer_list.id,
TransferListItemStatusEnum::READY_TO_PICK,
aggregator_value_vo.id)
relabel_status_map = inventory_service.get_relabelling_required_map_for_inventory_item_ids(
transfer_list_items_maps.collect{ |map| map[:inventory_item_id] })
transfer_list_items_map = transfer_list_items_maps.detect do |map|
(picked_inventories.exclude? map[:inventory_item_id]) &&
(relabel_status_map[map[:inventory_item_id]] == expected_relabel_status)
end
if transfer_list_items_map.present?
picked_inventories << transfer_list_items_map[:inventory_item_id]
else
raise TransferListItemNotFoundError.new("WSN : #{wsn} , Storage_location: #{storage_location} not available to pick")
end
raise TransferListItemNotFoundError.new("WSN : #{wsn} , Storage_location: #{storage_location} not available to pick") unless transfer_list_items_map.present?
[inventory_service.get_vos_by_ids([transfer_list_items_map[:inventory_item_id]]).first, transfer_list_items_map]
end
def get_inventory_item_vo(wsn, transfer_list, wid, picked_inventories)
transfer_list_items_map_list =
transfer_list_service.get_inventory_item_id_and_transfer_list_item_by_transfer_list_id_and_item_status(
transfer_list.id, TransferListItemStatusEnum::READY_TO_PICK)
inventory_item_vo = if transfer_list_items_map_list.present?
inventory_item_vos = inventory_service.get_vos_by_ids(transfer_list_items_map_list.collect { |item| item[:inventory_item_id] })
inventory_item_vos.detect { |item_vo| (item_vo.wid == wid && (picked_inventories.exclude? item_vo.id))}
else
nil
end
if inventory_item_vo.present?
picked_inventories << inventory_item_vo.id
else
raise TransferListItemNotFoundError.new("WSN : #{wsn} not available to pick")
end
[inventory_item_vo, transfer_list_items_map_list.detect{ |map| map[:inventory_item_id] == inventory_item_vo.id }]
end
def is_inventory_reserved_or_in_transit_out_of_current_TL(inventory_item, current_transfer_list)
is_inv_locked_outside_of_TL = ((inventory_item.atp == 1 && inventory_item.in_transit == false) ? false : true)
if is_inv_locked_outside_of_TL
inventory_TL = transfer_list_service.get_trasfer_list_for_inventory_item(inventory_item)
is_inv_locked_outside_of_TL = false if inventory_TL.present? && inventory_TL.id == current_transfer_list.id
end
return is_inv_locked_outside_of_TL
end
def validate_wsn_reserved(inventory_item, wsn, transfer_list, outbound_request_type = true)
unless inventory_item.area == transfer_list.source_area
raise WarehouseService::InvalidInputError.new("WSN:#{wsn} is in location #{inventory_item.area}, cannot pick from location #{transfer_list.source_area}")
end
return true if inventory_item.atp == 1 && inventory_item.in_transit == false
if inventory_item.in_transit == true and !allow_in_transit_swapping(inventory_item, wsn, transfer_list, outbound_request_type)
raise WarehouseService::InvalidInputError.new("WSN:#{wsn} is already reserved")
end
outbound_request_items = outbound_request_service.get_item_vos_by_inventory_item_id(inventory_item.id)
if outbound_request_type
outbound_request = movement_request_service.get_outbound_request_for_movement_request_id(transfer_list.movement_request_id)
if outbound_request_items.present?
outbound_request_items.each do |item|
next if item.outbound_request_id == outbound_request.id
outbound_request_item_reserved_against_wsn_flow?(item, wsn)
end
end
else
outbound_request_items.each{|item| outbound_request_item_reserved_against_wsn_flow?(item, wsn)}
WsnService.validate_picked_item_against_blocking_entities(inventory_item)
end
end
def allow_in_transit_swapping(inventory_item, wsn, transfer_list, outbound_request_type)
# method to check if in_transit swapping of inventory is allowed
if outbound_request_type
outbound_request_vo = movement_request_service
.get_outbound_request_for_movement_request_id(transfer_list.movement_request_id)
# validate warehouse, flow and area
unless is_in_transit_swap_enabled_for_flow(outbound_request_vo.outbound_request_type) and \
is_in_transit_swap_enabled_for_area(transfer_list.source_area)
return false
end
# check if scanned inventory in same location as reserved inventory in TL
begin
storage_location_vo = storage_location_service.get_vos_by_ids([inventory_item.storage_location_id]).first
aggregator_value = "#{storage_location_vo.label}|#{inventory_item.wid}"
aggregator_value_vo = transfer_list_service
.get_aggregator_value_vo_by_transfer_list_id_and_value(transfer_list.id, aggregator_value)
rescue Warehouse::RecordNotFoundError
raise WarehouseService::InvalidInputError
.new("Scanned WSN:#{wsn} is in different location than TL - #{transfer_list.display_id}")
end
# check if TL item in ready to pick state for scanned wid
begin
transfer_list_items_vos = transfer_list_service
.get_transfer_list_items_by_transfer_list_id_and_gregator_value_id_and_status(
transfer_list.id,
aggregator_value_vo.id,
TransferListStatusEnum::READY_TO_PICK)
unless transfer_list_items_vos.present?
return false
end
rescue Warehouse::RecordNotFoundError
raise WarehouseService::InvalidInputError
.new("WID:#{inventory_item.wid} in location #{storage_location_vo.label} already picked for TL - #{transfer_list.display_id}")
end
# check if scanned inventory not yet picked
movement_request_item_vo = movement_request_service
.get_movement_request_item_vos_by_inventory_item_ids(inventory_item.id)
.map{ |item| item if [MovementRequestItemStatusEnum::CREATED,
MovementRequestItemStatusEnum::PROCESSING].include? item.status}
.compact.first
unless movement_request_item_vo.present?
return false
end
transfer_list_item_vo = transfer_list_service
.get_transfer_list_items_by_movement_request_item_ids(movement_request_item_vo.id).first
allowed_transfer_list_item_status = [TransferListItemStatusEnum::CREATED,
TransferListItemStatusEnum::READY_TO_PICK,
TransferListItemStatusEnum::CANCELLED]
unless allowed_transfer_list_item_status.include? transfer_list_item_vo.status
return false
end
log.info("In transit swapping of WSN - #{wsn} and Inventory - #{inventory_item.id} and TL - #{transfer_list.display_id}")
return true
end
return false
end
def is_in_transit_swap_enabled_for_flow(outbound_request_type)
config_hash = WarehouseService.settings.in_transit_inventory_swap_allowed_flows
config_hash[outbound_request_type].present? &&
(config_hash[outbound_request_type].include?('ALL') || config_hash[outbound_request_type].include?(@warehouse_id))
end
def is_in_transit_swap_enabled_for_area(source_area)
storage_areas = WarehouseService.settings.in_transit_inventory_swap_allowed_areas
storage_areas.include? source_area
end
def get_fki_to_seller_wids_hash(fki_wids)
# catching exception here to keep the usage cleaner
begin
wid_seller_mapping_data_service.get_fki_to_seller_wids_hash(fki_wids)
rescue Warehouse::RecordNotFoundError
nil
end
end
def outbound_request_item_reserved_against_wsn_flow?(item, wsn)
if (([OutboundRequestStatusEnum::CANCELLED, OutboundRequestStatusEnum::COMPLETED].exclude? item.status) &&
picked_item_reserved_against_wsn_flow?(item.outbound_request_id))
raise WarehouseService::InvalidInputError.new("WSN:#{wsn} is already reserved for outbound request #{item.outbound_request_id}")
end
end
def picked_item_reserved_against_wsn_flow?(outbound_request_id)
outbound_request = outbound_request_service.get_vos_by_ids([outbound_request_id]).first
OutboundRequestEnums.get_serialized_pick_flows.include?(outbound_request.outbound_request_type.to_s)
end
def validate_duplicate_wsn(inventory_item, transfer_list, wsn)
transfer_list_items = transfer_list_service.find_transfer_list_items_by_inventory_item_id(inventory_item.id)
transfer_list_items.each do |transfer_list_item|
if transfer_list_item.status == TransferListItemStatusEnum::PICKED
transfer_list_for_item = transfer_list_item.transfer_list_id == transfer_list.id ? transfer_list : transfer_list_service.get_vo_by_id(transfer_list_item.transfer_list_id)
raise WarehouseService::InvalidInputError.new("WSN:#{wsn} is already picked for TL#{transfer_list_item.transfer_list_id}") if
transfer_list.movement_request_id == transfer_list_for_item.movement_request_id
end
end
end
def validate_scanned_wsn_warehouse(inventory_item, transfer_list, wsn)
unless inventory_item.warehouse_id == transfer_list.warehouse_id
raise InvalidInputError.new("WSN #{wsn} belongs to warehouse #{inventory_item.warehouse_id}")
end
end
def validate_picked_item_and_swap(pickable_item, transfer_list, wsn, inventory_item, outbound_request_type, picked_inventories, flow = nil)
if WarehouseService.settings.kalash_warehouses.include?(@warehouse_id)
block_swap_for_kalash = is_inventory_reserved_or_in_transit_out_of_current_TL(inventory_item, transfer_list)
err_msg = "Cannot pick #{wsn} for TL id #{transfer_list.id}. Choose a different WSN to pick. Scanned wsn has zero atp or it is in-transit for another process." if block_swap_for_kalash
raise WarehouseService::InvalidInputError.new(err_msg) if err_msg.present?
end
validate_wsn_reserved(inventory_item, wsn, transfer_list, outbound_request_type)
WsnService.validate_picked_item_not_reserved_against_wsn_flow(inventory_item)
if outbound_request_type
outbound_request_vo = movement_request_service.get_outbound_request_for_movement_request_id(transfer_list.movement_request_id)
if is_inv_swap_enabled_for_flow(outbound_request_vo.outbound_request_type) && is_inv_swap_enabled_for_area(transfer_list.source_area)
swap_inventories(wsn, pickable_item[:source_loaction_id], transfer_list, picked_inventories, inventory_item, flow)
else
swap_wsns(wsn, pickable_item[:source_loaction_id], transfer_list, picked_inventories, flow)
end
else
swap_wsns(wsn, pickable_item[:source_loaction_id], transfer_list, picked_inventories, flow)
end
end
def get_product_details_by_wid(wid)
product_details_dao.get_by_wid(wid)
end
def wsn_service
BusinessServiceFactory.get_wsn_service
end
def storage_zone_service
BusinessServiceFactory.storage_location_service(@warehouse_id)
end
def transfer_list_service
BusinessServiceFactory.get_transfer_list_service(@warehouse_id)
end
def inventory_service
BusinessServiceFactory.inventory_service(@warehouse_id)
end
def outbound_request_service
BusinessServiceFactory.get_outbound_request_service(@warehouse_id)
end
def movement_request_service
BusinessServiceFactory.get_movement_request_service(@warehouse_id)
end
def wid_seller_mapping_data_service
DataServiceFactory.get_wid_seller_mapping_data_service
end
def relabel_status_service
BusinessServiceFactory.get_inventory_relabel_status_service(@warehouse_id)
end
def shard_manager
ShardManager.new
end
def transfer_request_service
BusinessServiceFactory.get_transfer_request_service(@warehouse_id)
end
def storage_location_service
BusinessServiceFactory.storage_location_service(@warehouse_id)
end
def product_details_dao
DAOFactory.get_dao(StorageNamespaceEnum::PRODUCT_DETAIL, [@warehouse_id])[@warehouse_id]
end
def b2b_warehouse_client
ExternalClientFactory.get_b2b_warehouse_client
end
def wh_serial_number_data_service
BusinessServiceFactory.get_wh_serial_number_data_service
end
def aggregator_value_dao
DAOFactory.get_dao("aggregator_values", [@warehouse_id])[@warehouse_id]
end
end
Editor is loading...
Leave a Comment