| Line 144... |
Line 144... |
| 144 |
raise InventoryServiceException(108, "Some unforeseen error while updating inventory")
|
144 |
raise InventoryServiceException(108, "Some unforeseen error while updating inventory")
|
| 145 |
session.commit()
|
145 |
session.commit()
|
| 146 |
|
146 |
|
| 147 |
#**Update item availability cache**#
|
147 |
#**Update item availability cache**#
|
| 148 |
for item_id in item_ids:
|
148 |
for item_id in item_ids:
|
| 149 |
__update_item_availability_cache(item_id)
|
149 |
clear_item_availability_cache(item_id)
|
| 150 |
__check_risky_item(item_id)
|
- |
|
| 151 |
|
150 |
|
| 152 |
def __send_alert_for_negative_reserved(item, reserved, warehouse):
|
151 |
def __send_alert_for_negative_reserved(item, reserved, warehouse):
|
| 153 |
itemName = " ".join([str(item.id), str(item.brand), str(item.modelName), str(item.modelNumber), str(item.color)])
|
152 |
itemName = " ".join([str(item.id), str(item.brand), str(item.modelName), str(item.modelNumber), str(item.color)])
|
| 154 |
EmailAttachmentSender.mail('cnc.center@shop2020.in', '5h0p2o2o', 'amar.kumar@shop2020.in', 'Negative reserved: ' + str(reserved) + ' for Item Id: ' + itemName + ' warehouse id: ' + str(warehouse.id), None)
|
153 |
EmailAttachmentSender.mail('cnc.center@shop2020.in', '5h0p2o2o', 'amar.kumar@shop2020.in', 'Negative reserved: ' + str(reserved) + ' for Item Id: ' + itemName + ' warehouse id: ' + str(warehouse.id), None)
|
| 155 |
|
154 |
|
| Line 183... |
Line 182... |
| 183 |
current_inventory_snapshot.reserved = 0
|
182 |
current_inventory_snapshot.reserved = 0
|
| 184 |
# added the difference in the current inventory
|
183 |
# added the difference in the current inventory
|
| 185 |
current_inventory_snapshot.availability = current_inventory_snapshot.availability + quantity
|
184 |
current_inventory_snapshot.availability = current_inventory_snapshot.availability + quantity
|
| 186 |
session.commit()
|
185 |
session.commit()
|
| 187 |
#**Update item availability cache**#
|
186 |
#**Update item availability cache**#
|
| 188 |
__update_item_availability_cache(itemId)
|
187 |
clear_item_availability_cache(itemId)
|
| 189 |
if current_inventory_snapshot.availability < 0:
|
188 |
if current_inventory_snapshot.availability < 0:
|
| 190 |
item = __get_item_from_master(itemId)
|
189 |
item = __get_item_from_master(itemId)
|
| 191 |
__send_alert_for_negative_availability(item, current_inventory_snapshot.availability, get_Warehouse(warehouseId))
|
190 |
__send_alert_for_negative_availability(item, current_inventory_snapshot.availability, get_Warehouse(warehouseId))
|
| 192 |
__check_risky_item(itemId)
|
- |
|
| 193 |
|
191 |
|
| 194 |
def add_bad_inventory(itemId, warehouseId, quantity):
|
192 |
def add_bad_inventory(itemId, warehouseId, quantity):
|
| 195 |
bad_inventory_snapshot = BadInventorySnapshot.get_by(item_id=itemId, warehouse_id=warehouseId)
|
193 |
bad_inventory_snapshot = BadInventorySnapshot.get_by(item_id=itemId, warehouse_id=warehouseId)
|
| 196 |
if not bad_inventory_snapshot:
|
194 |
if not bad_inventory_snapshot:
|
| 197 |
bad_inventory_snapshot = BadInventorySnapshot()
|
195 |
bad_inventory_snapshot = BadInventorySnapshot()
|
| Line 301... |
Line 299... |
| 301 |
reservation.promised_shipping_timestamp = promised_shipping_timestamp
|
299 |
reservation.promised_shipping_timestamp = promised_shipping_timestamp
|
| 302 |
reservation.reserved = quantity
|
300 |
reservation.reserved = quantity
|
| 303 |
|
301 |
|
| 304 |
session.commit()
|
302 |
session.commit()
|
| 305 |
#**Update item availability cache**#
|
303 |
#**Update item availability cache**#
|
| 306 |
__update_item_availability_cache(item_id)
|
304 |
clear_item_availability_cache(item_id)
|
| 307 |
__check_risky_item(item_id)
|
- |
|
| 308 |
return True
|
305 |
return True
|
| 309 |
|
306 |
|
| 310 |
def reduce_reservation_count(item_id, warehouse_id, source_id, order_id, quantity):
|
307 |
def reduce_reservation_count(item_id, warehouse_id, source_id, order_id, quantity):
|
| 311 |
if not warehouse_id:
|
308 |
if not warehouse_id:
|
| 312 |
raise InventoryServiceException(101, "bad warehouse_id")
|
309 |
raise InventoryServiceException(101, "bad warehouse_id")
|
| Line 321... |
Line 318... |
| 321 |
reservation.delete()
|
318 |
reservation.delete()
|
| 322 |
else:
|
319 |
else:
|
| 323 |
reservation.reserved -= quantity
|
320 |
reservation.reserved -= quantity
|
| 324 |
session.commit()
|
321 |
session.commit()
|
| 325 |
#**Update item availability cache**#
|
322 |
#**Update item availability cache**#
|
| 326 |
__update_item_availability_cache(item_id)
|
323 |
clear_item_availability_cache(item_id)
|
| 327 |
__check_risky_item(item_id)
|
- |
|
| 328 |
if current_inventory_snapshot.reserved < 0:
|
324 |
if current_inventory_snapshot.reserved < 0:
|
| 329 |
item = __get_item_from_master(item_id)
|
325 |
item = __get_item_from_master(item_id)
|
| 330 |
__send_alert_for_negative_reserved(item, current_inventory_snapshot.reserved, get_Warehouse(warehouse_id))
|
326 |
__send_alert_for_negative_reserved(item, current_inventory_snapshot.reserved, get_Warehouse(warehouse_id))
|
| 331 |
return True
|
327 |
return True
|
| 332 |
except:
|
328 |
except:
|
| 333 |
print "Unexpected error:", sys.exc_info()[0]
|
329 |
print "Unexpected error:", sys.exc_info()[0]
|
| 334 |
return False
|
330 |
return False
|
| 335 |
|
331 |
|
| 336 |
def get_item_availability_for_location(item_id):
|
332 |
def get_item_availability_for_location(item_id, source_id):
|
| 337 |
item_availability = ItemAvailabilityCache.get_by(itemId=item_id)
|
333 |
item_availability = ItemAvailabilityCache.get_by(itemId=item_id, sourceId = source_id)
|
| 338 |
if item_availability:
|
334 |
if item_availability:
|
| 339 |
return [item_availability.warehouseId, item_availability.expectedDelay, item_availability.billingWarehouseId, item_availability.sellingPrice, item_availability.totalAvailability]
|
335 |
return [item_availability.warehouseId, item_availability.expectedDelay, item_availability.billingWarehouseId, item_availability.sellingPrice, item_availability.totalAvailability]
|
| 340 |
else:
|
336 |
else:
|
| 341 |
__update_item_availability_cache(item_id)
|
337 |
__update_item_availability_cache(item_id, source_id)
|
| - |
|
338 |
##Check risky status for the source
|
| - |
|
339 |
__check_risky_item(item_id, source_id)
|
| 342 |
return get_item_availability_for_location(item_id)
|
340 |
return get_item_availability_for_location(item_id, source_id)
|
| 343 |
|
341 |
|
| 344 |
def clear_item_availability_cache():
|
342 |
def clear_item_availability_cache(item_id = None):
|
| - |
|
343 |
if item_id:
|
| - |
|
344 |
ItemAvailabilityCache.query.filter_by(itemId = item_id).delete()
|
| - |
|
345 |
else:
|
| 345 |
ItemAvailabilityCache.query.delete()
|
346 |
ItemAvailabilityCache.query.delete()
|
| 346 |
session.commit()
|
347 |
session.commit()
|
| 347 |
|
348 |
|
| 348 |
def __update_item_availability_cache(item_id):
|
349 |
def __update_item_availability_cache(item_id, source_id):
|
| 349 |
"""
|
350 |
"""
|
| 350 |
Determines the warehouse that should be used to fulfil an order for the given item.
|
351 |
Determines the warehouse that should be used to fulfil an order for the given item.
|
| 351 |
Algorithm explained at https://sites.google.com/a/shop2020.in/virtual-w-h-and-inventory/technical-details
|
352 |
Algorithm explained at https://sites.google.com/a/shop2020.in/virtual-w-h-and-inventory/technical-details
|
| 352 |
|
353 |
|
| 353 |
It will be ensured that every item has either a preferred vendor specified or at least for one vendor its transfer price should be defined.
|
354 |
It will be ensured that every item has either a preferred vendor specified or at least for one vendor its transfer price should be defined.
|
| Line 377... |
Line 378... |
| 377 |
3. Id of the warehouse which was finally picked up.
|
378 |
3. Id of the warehouse which was finally picked up.
|
| 378 |
|
379 |
|
| 379 |
Parameters:
|
380 |
Parameters:
|
| 380 |
- itemId
|
381 |
- itemId
|
| 381 |
"""
|
382 |
"""
|
| 382 |
item = __get_item_from_master(item_id)
|
383 |
item = __get_item_from_source(item_id, source_id)
|
| 383 |
item_pricing = {}
|
384 |
item_pricing = {}
|
| 384 |
for vendorItemPricing in VendorItemPricing.query.filter_by(item_id=item_id).all():
|
385 |
for vendorItemPricing in VendorItemPricing.query.filter_by(item_id=item_id).all():
|
| 385 |
item_pricing[vendorItemPricing.vendor_id] = vendorItemPricing
|
386 |
item_pricing[vendorItemPricing.vendor_id] = vendorItemPricing
|
| 386 |
|
387 |
|
| 387 |
warehouses = {}
|
388 |
warehouses = {}
|
| Line 433... |
Line 434... |
| 433 |
expectedDelay = 0
|
434 |
expectedDelay = 0
|
| 434 |
else:
|
435 |
else:
|
| 435 |
expectedDelay = int(item.expectedDelay)
|
436 |
expectedDelay = int(item.expectedDelay)
|
| 436 |
|
437 |
|
| 437 |
if total_availability <= 0:
|
438 |
if total_availability <= 0:
|
| 438 |
expectedDelay = expectedDelay + __get_expected_procurement_delay(item)
|
439 |
expectedDelay = expectedDelay + __get_expected_procurement_delay(item.id, item.preferredVendor)
|
| 439 |
expectedDelay = expectedDelay + __get_vendor_holiday_delay(item, expectedDelay)
|
440 |
expectedDelay = expectedDelay + __get_vendor_holiday_delay(item.preferredVendor, expectedDelay)
|
| 440 |
else:
|
441 |
else:
|
| 441 |
if warehouse.transferDelayInHours:
|
442 |
if warehouse.transferDelayInHours:
|
| 442 |
expectedDelay = expectedDelay + warehouse.transferDelayInHours / 24
|
443 |
expectedDelay = expectedDelay + warehouse.transferDelayInHours / 24
|
| 443 |
|
444 |
|
| 444 |
total_availability = 0
|
445 |
total_availability = 0
|
| 445 |
for entry in CurrentInventorySnapshot.query.filter_by(item_id = item_id).all():
|
446 |
for entry in CurrentInventorySnapshot.query.filter_by(item_id = item_id).all():
|
| 446 |
total_availability += entry.availability - entry.reserved
|
447 |
total_availability += entry.availability - entry.reserved
|
| 447 |
|
448 |
|
| 448 |
item_availability_cache = ItemAvailabilityCache.get_by(itemId=item_id)
|
449 |
item_availability_cache = ItemAvailabilityCache.get_by(itemId=item_id, sourceId=source_id)
|
| 449 |
if item_availability_cache is None:
|
450 |
if item_availability_cache is None:
|
| 450 |
item_availability_cache = ItemAvailabilityCache()
|
451 |
item_availability_cache = ItemAvailabilityCache()
|
| 451 |
item_availability_cache.itemId = item_id
|
452 |
item_availability_cache.itemId = item_id
|
| - |
|
453 |
item_availability_cache.sourceId = source_id
|
| 452 |
item_availability_cache.warehouseId = int(warehouse_retid)
|
454 |
item_availability_cache.warehouseId = int(warehouse_retid)
|
| 453 |
item_availability_cache.expectedDelay = expectedDelay
|
455 |
item_availability_cache.expectedDelay = expectedDelay
|
| 454 |
item_availability_cache.billingWarehouseId = billingWarehouseId
|
456 |
item_availability_cache.billingWarehouseId = billingWarehouseId
|
| 455 |
item_availability_cache.sellingPrice = item.sellingPrice
|
457 |
item_availability_cache.sellingPrice = item.sellingPrice
|
| 456 |
item_availability_cache.totalAvailability = total_availability
|
458 |
item_availability_cache.totalAvailability = total_availability
|
| Line 517... |
Line 519... |
| 517 |
max_availability = availability
|
519 |
max_availability = availability
|
| 518 |
total_availability += availability
|
520 |
total_availability += availability
|
| 519 |
|
521 |
|
| 520 |
return [warehouse_retid, total_availability]
|
522 |
return [warehouse_retid, total_availability]
|
| 521 |
|
523 |
|
| 522 |
def __get_expected_procurement_delay(item):
|
524 |
def __get_expected_procurement_delay(item_id, preferredVendor):
|
| 523 |
procurementDelay = 2
|
525 |
procurementDelay = 2
|
| 524 |
try:
|
526 |
try:
|
| 525 |
if item.preferredVendor:
|
527 |
if preferredVendor:
|
| 526 |
delays = VendorItemProcurementDelay.query.filter_by(vendor_id = item.preferredVendor, item_id = item.id).all()
|
528 |
delays = VendorItemProcurementDelay.query.filter_by(vendor_id = preferredVendor, item_id = item_id).all()
|
| 527 |
else:
|
529 |
else:
|
| 528 |
delays = VendorItemProcurementDelay.query.filter_by(item_id = item.id).all()
|
530 |
delays = VendorItemProcurementDelay.query.filter_by(item_id = item_id).all()
|
| 529 |
|
531 |
|
| 530 |
procurementDelay= min([delay.procurementDelay for delay in delays])
|
532 |
procurementDelay= min([delay.procurementDelay for delay in delays])
|
| 531 |
except Exception as e:
|
533 |
except Exception as e:
|
| 532 |
print e
|
534 |
print e
|
| 533 |
return procurementDelay
|
535 |
return procurementDelay
|
| 534 |
|
536 |
|
| 535 |
def __get_vendor_holiday_delay(item, expectedDelay):
|
537 |
def __get_vendor_holiday_delay(preferredVendor, expectedDelay):
|
| 536 |
holidayDelay = 0
|
538 |
holidayDelay = 0
|
| 537 |
try:
|
539 |
try:
|
| 538 |
if item.preferredVendor:
|
540 |
if preferredVendor:
|
| 539 |
holidays = VendorHolidays.query.filter_by(vendor_id = item.preferredVendor).all()
|
541 |
holidays = VendorHolidays.query.filter_by(vendor_id = preferredVendor).all()
|
| 540 |
currentDate = datetime.date.today()
|
542 |
currentDate = datetime.date.today()
|
| 541 |
expectedDate = currentDate + datetime.timedelta(days = expectedDelay)
|
543 |
expectedDate = currentDate + datetime.timedelta(days = expectedDelay)
|
| 542 |
for holiday in holidays:
|
544 |
for holiday in holidays:
|
| 543 |
if holiday.holidayType == HolidayType.WEEKLY and holiday.holidayValue != calendar.SUNDAY:
|
545 |
if holiday.holidayType == HolidayType.WEEKLY and holiday.holidayValue != calendar.SUNDAY:
|
| 544 |
if currentDate.weekday() > holiday.holidayValue:
|
546 |
if currentDate.weekday() > holiday.holidayValue:
|
| Line 755... |
Line 757... |
| 755 |
quantity = 0
|
757 |
quantity = 0
|
| 756 |
|
758 |
|
| 757 |
currentInventorySnapshot = CurrentInventorySnapshot.get_by(item_id = itemId, warehouse_id = warehouseId)
|
759 |
currentInventorySnapshot = CurrentInventorySnapshot.get_by(item_id = itemId, warehouse_id = warehouseId)
|
| 758 |
if currentInventorySnapshot:
|
760 |
if currentInventorySnapshot:
|
| 759 |
currentInventorySnapshot.availability = quantity
|
761 |
currentInventorySnapshot.availability = quantity
|
| 760 |
__update_item_availability_cache(itemId)
|
762 |
clear_item_availability_cache(itemId)
|
| 761 |
__check_risky_item(currentInventorySnapshot.item_id)
|
- |
|
| 762 |
else:
|
763 |
else:
|
| 763 |
add_inventory(itemId, warehouseId, quantity)
|
764 |
add_inventory(itemId, warehouseId, quantity)
|
| 764 |
|
765 |
|
| 765 |
else:
|
766 |
else:
|
| 766 |
raise InventoryServiceException(101, 'VendorMapping not found for: ' + itemKey)
|
767 |
raise InventoryServiceException(101, 'VendorMapping not found for: ' + itemKey)
|
| 767 |
session.commit()
|
768 |
session.commit()
|
| 768 |
|
769 |
|
| 769 |
def reset_availability_for_warehouse(warehouseId):
|
770 |
def reset_availability_for_warehouse(warehouseId):
|
| 770 |
for currentInventorySnapshot in CurrentInventorySnapshot.query.filter_by(warehouse_id=warehouseId).all():
|
771 |
for currentInventorySnapshot in CurrentInventorySnapshot.query.filter_by(warehouse_id=warehouseId).all():
|
| 771 |
currentInventorySnapshot.availability = 0
|
772 |
currentInventorySnapshot.availability = 0
|
| 772 |
__update_item_availability_cache(currentInventorySnapshot.item_id)
|
773 |
clear_item_availability_cache(currentInventorySnapshot.item_id)
|
| 773 |
__check_risky_item(currentInventorySnapshot.item_id)
|
- |
|
| 774 |
session.commit()
|
774 |
session.commit()
|
| 775 |
|
775 |
|
| 776 |
|
776 |
|
| 777 |
def __send_mail(subject, message):
|
777 |
def __send_mail(subject, message):
|
| 778 |
try:
|
778 |
try:
|
| Line 812... |
Line 812... |
| 812 |
def update_vendor_string(warehouseId, vendorString):
|
812 |
def update_vendor_string(warehouseId, vendorString):
|
| 813 |
warehouse = get_Warehouse(warehouseId)
|
813 |
warehouse = get_Warehouse(warehouseId)
|
| 814 |
warehouse.vendorString = vendorString
|
814 |
warehouse.vendorString = vendorString
|
| 815 |
session.commit()
|
815 |
session.commit()
|
| 816 |
|
816 |
|
| 817 |
def __check_risky_item(item_id):
|
- |
|
| 818 |
## We should get the list of strings which will identify to the catalog servers
|
- |
|
| 819 |
client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
|
- |
|
| 820 |
client.validateRiskyStatus(item_id)
|
- |
|
| 821 |
client = CatalogClient("catalog_service_server_host_hotspot", "catalog_service_server_port").get_client()
|
- |
|
| 822 |
client = CatalogClient().get_client()
|
- |
|
| 823 |
|
- |
|
| 824 |
def __get_item_from_master(item_id):
|
817 |
def __get_item_from_master(item_id):
|
| 825 |
client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
|
818 |
client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
|
| 826 |
return client.getItem(item_id)
|
- |
|
| 827 |
|
819 |
return client.getItem(item_id)
|
| - |
|
820 |
|
| - |
|
821 |
def __check_risky_item(item_id, source_id):
|
| - |
|
822 |
## We should get the list of strings which will identify to the catalog servers
|
| - |
|
823 |
if source_id == 1:
|
| - |
|
824 |
client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
|
| - |
|
825 |
client.validateRiskyStatus(item_id)
|
| - |
|
826 |
if source_id == 2:
|
| - |
|
827 |
client = CatalogClient("catalog_service_server_host_hotspot", "catalog_service_server_port").get_client()
|
| - |
|
828 |
client.validateRiskyStatus(item_id)
|
| - |
|
829 |
|
| - |
|
830 |
def __get_item_from_source(item_id, source_id):
|
| - |
|
831 |
if source_id == 1:
|
| - |
|
832 |
client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
|
| - |
|
833 |
return client.getItem(item_id)
|
| - |
|
834 |
if source_id == 2:
|
| - |
|
835 |
client = CatalogClient("catalog_service_server_host_hotspot", "catalog_service_server_port").get_client()
|
| - |
|
836 |
return client.getItem(item_id)
|
| - |
|
837 |
|
| 828 |
|
838 |
|