from core.models import Addition,Location,ShipUnit,LocationType,WineLocationValues,Account
from django.db.models import Sum
#from poc.alloc.models import wine_location
# ============ Function Summary
# allocate : put away in location case, bin or rack
# receive: for orders - set status to received, add to temp location
# type_capacity: return total capacity of Bin and Rack location types
# capacity: return the total capacity available for the location type
# bin_capacity_ct : the number of bins with allocation capacity
#
# ==========================================================================
[docs]
def get_account_name(request):
current_user = request.user
return current_user.account
[docs]
def get_account_id(owner):
account_id = Account.objects.get(account=owner)
return account_id.id
return current_user.account
[docs]
def next_case(owner):
type_key = LocationType.objects.get(location_type='Case')
get_cases = Location.objects.filter(type_id=type_key,account=owner).values()
case_ct = get_cases.count()
case_ct = int(case_ct) + 1
case_str = str(case_ct).zfill(4)
case_name = 'CS' + case_str
#print('case name = ',case_name)
return case_name
[docs]
def type_capacity(owner):
#return the capacity of Bin and Rack location types (Bins & Rack)
#get bin and location keys
bin_capacity = capacity(2,owner)
empty_rack_items = empty_rack_slots(owner)
rack_capacity = len(empty_rack_items)
#print('Rack capacity returned',rack_capacity)
return bin_capacity,rack_capacity
[docs]
def capacity(type_key,owner):
#return the total capacity available for the location type
num_ct = 0
max_capacity = 0
tot_max_capacity = 0
#print('1 get capacity for ', type_key)
chk=LocationType.objects.get(pk=type_key) # get objects for this type
max_capacity = chk.location_max_qty #get the max qty for this location type
#print('2. max_capacity = ',max_capacity)
num_ct = Location.objects.filter(type_id=type_key,account=owner).count() # get the number of these locations
#print('3. num_ct',num_ct)
if num_ct == 0:
# print('4.1 num ct = 0',num_ct)
capacity = 0 #used capacity
# print('4.1 capacity = 0',capacity)
tot_max_capacity = max_capacity
# print('4.1 tot max capacity = ',tot_max_capacity)
else:
#print('**** in the else 4.2')
tot_max_capacity = (max_capacity * num_ct)
calc_capacity = Location.objects.filter(type_id=type_key).aggregate(Sum('location_qty'))
capacity = calc_capacity['location_qty__sum'] # sum of all locations
#print('tot max capacity =',tot_max_capacity)
#print('capacity = ',capacity)
available_capacity = tot_max_capacity - capacity
#print('available capacity = ',available_capacity)
return available_capacity
[docs]
def bin_capacity_ct(rqt):
#return the number of bins with enough capacity for the requirement(rqt)
#Note we only need to check count of bins
# get bin type
# get all bins from wine_locations
# If nore than 1 then for each bin check get capacity,
# return values
max_capacity = 0
used_capacity = 0
available_capacity = 0
bins_list = []
bins = LocationType.objects.get(Location_type='Bin').pk
all_bins_ct = bins.count()
print('bin count = ', all_bins_ct)
if all_bins_ct ==1:
qty=bins.location_qty
max_qty = bins.location_max_qty
free_qty = max_qty - qty
if free_qty >0:
bins_list.insert(bins.pk,'free_qty')
elif all_bins_ct > 1:
for n in bins:
qty=n.location_qty
max_qty = n.location_max_qty
free_qty = max_qty - qty
if free_qty > 0:
bins_list.insert(n.pk,'free_qty')
return bins_list
[docs]
def allocate(wine_id,allocation_type,alloc_loc,owner):
# wine_id = unique wine identifier
# Allocation type: Case allocations = create case. Bins and Racks must exist, Create case
# alloc_loc = optional parameter (not needed for cases as the cases id is created dynamically when called )
# owner = account id
# No constraint on number in a cellar
# Fix 28 April for allocation quantity
# Allocation qty for Case and Bin = Quantity - Allocation Quantity
# Allocation qty for Rack = Allocation Quantity + 1 ( racks hold 1 unit)
# Temp Location : reduce Temp Qty by allocation Quantity val
# Set Addition status to part allocated or put away
print('Allocate : Allocation details = ', wine_id,allocation_type,alloc_loc,flush=True)
#Update Wine allocation fields : alloc qty and allocation status
wine = Addition.objects.get(pk=wine_id)
if allocation_type == 'Rack': # Allocate a single bottle
alloc_qty = 1
wine.allocation_qty = wine.allocation_qty + 1
if wine.allocation_qty < wine.quantity : #check if part allocated or not
wine.addition_status = 'Part Allocated'
else:
wine.addition_status = 'Put Away'
else: #Set status to Put away, set allocation qty to remaining number left to allocate as as user may have been allocated some to rack
# For both Bins and cases the allocation quantity is the remaining quantity left to allocate
alloc_qty = wine.quantity - wine.allocation_qty # set alloc qty to delivery quantity
wine.allocation_qty = wine.allocation_qty + alloc_qty
wine.addition_status = 'Put Away'
print('Allocate : wine allocation qty after assignment =',wine.allocation_qty,flush=True)
# Update Wine Object with Allocation Status
try:
wine.save()
print('Allocate Wine object - allocation status updated',flush=True)
except:
print('Wine object update failed',flush=True)
# If a case allocation create a new case with the alloc qty set to the remaining number to allocate
if allocation_type == 'Case': # Create a New Case and update the location quantity
case_name = next_case(owner)
alloc_loc=case_name # set the allocation location to the new case
case_account = get_account_id(owner)
print(case_name,wine.allocation_qty,case_account)
new_case = Location(name = case_name,location_qty=alloc_qty,
type_id = '3',account_id=case_account)
try:
new_case.save()
print('Create New Case - success',flush=True)
except:
print('** Fail to create new case',flush=True)
else : # Update Location details for Bin and Rack allocations
# Get location details and update quantity
loctn = Location.objects.get(name=alloc_loc,account_id=owner)
loctn.location_qty = loctn.location_qty + alloc_qty # add this allocation quantity to current location qty
# save the new location quantity
try: # Save Location
loctn.save()
print( 'Allocate: Location details update Success',flush=True )
print('Location details =',loctn.location_qty,loctn.id,loctn.type,flush=True)
except:
print( 'Allocate - Update Location details - fail line 296',flush=True )
# Update (M2M) addition_location
new_location = Location.objects.get(name=alloc_loc,account_id=owner)
try:
wine.wine_location.add(new_location)
print ('Allocate - save M2M : Success ',flush=True)
except:
print('Allocate: M2M save error',flush=True)
print(' Allocate : allocation quantity var= ',alloc_qty,flush=True)
print(' wine details to save : allocated ',wine.allocation_qty,flush=True)
# get latest wine values , statuses etc.
wine = Addition.objects.get(pk=wine_id)
#Process temp location records
if wine.addition_status == 'Put Away': # delete the temp location record
try:
t = Location.objects.get(type_id=1,name=wine_id,account=owner) # get temp record details for this wine
t.delete()
print('Allocate - Temp object process delete success, wine now put away')
except:
print('Allocate - No temp object in Location table for this wine ')
# Update WineLocation Values
loctn = Location.objects.get(name=alloc_loc,account=owner)
wlv_qty = 0 # set this to 1 if rack else set it it to alloc qty
if allocation_type == 'Rack':
wlv_qty = 1
else:
wlv_qty = alloc_qty
try:
wlv_price = (wine.price + wine.duty + wine.ship_costs)/wine.allocation_qty
print ( 'Allocate - SUCCESS wlv price set')
except:
wlv_price = 0
print ( 'Allocate - ERROR setting wlv price - price set to 0')
new_wlv = WineLocationValues(wine_id=wine.pk,
quantity=wlv_qty,
style=wine.style,
country=wine.country,
vintage=wine.year,
size=wine.size,
price = wlv_price,
location_id=loctn.pk,
location_type=loctn.type,
account=owner)
try:
new_wlv.save()
print('Allocate - Update WineLocationValues New record added')
except:
print('Allocate - Update WineLocationValues Failed line 211')
[docs]
def receive(wine_id):
# set addition status to Received for Ordered wines
# add to temp location
# update wine_location ( see add wine for an example )
wine = Addition.objects.get(pk=wine_id)
qty = wine.quantity # the number of individual bottles
# Build Location update and save
new_location =Location(name = wine.id,
location_qty = qty,
type_id = '1',
)
# save
new_location.save()
wine.wine_location.add(new_location)
wine.addition_status = 'Received'
wine.save()
[docs]
def addition_check(owner):
error_list=[]
status_check = 'success'
ac = owner
#errormsg = str('A list of the errors found when running addition check')
#error_list.append(errormsg)
#error_list.append('\n')
#errormsg = str('Go to \info\audit\errrors to see how to fix each possible error')
#error_list.append(errormsg)
#error_list.append('\n')
total_wine_qty=0
total_wlv_qty =0
addition_records = Addition.objects.filter(quantity__gt=0,addition_status='Put Away')|Addition.objects.filter(quantity__gt=0,addition_status='Tried')
addition_records = addition_records.filter(account_id=ac)
w= WineLocationValues.objects.filter(account_id=ac)
for x in addition_records: # iterate thru additions and check qty against wlv qty
total_wine_qty = total_wine_qty+x.quantity # so we can check total qty of addition matches total wlv
wine_id_qty = x.quantity # now check each addition item
wlv_id_qty=0 # set the id to 0 as we start the process
wcheck = w.filter(wine_id=x.id) # get wlv records for this wine id
wcount = wcheck.count() #count how many records have been found
if wcount > 0: # we have found record(s) so can iterate through each one
wcounter = 0 # wcounter used to see how many wlv records found
for z in wcheck:
wcounter = wcounter +1 # increment counter
wlv_id_qty =wlv_id_qty + z.quantity # get the wlv quantity for this wine
else:
status_check = 'errors'
str_id=str(x.id)
errormsg = 'No Wine Location records found for ' + str(x.name) + ' ID(' + str_id + ') Quantity = ' + str(x.quantity)
error_list.append(errormsg)
#error_list.append('\n')
if wcount != 0:
if wlv_id_qty != wine_id_qty :
status_check = 'errors'
str_id=str(x.id)
errormsg='Location quantity mismatch for ' + str(x.name) + ' ID(' + str_id + ') Quantity = ' + str(x. quantity) + ' Wine Location qty = ' + str(wlv_id_qty) + ' Wine location records are :' + str(wcheck)
error_list.append(errormsg)
error_list.append('\n')
return status_check,error_list
[docs]
def empty_rack_slots(owner):
# iterates through all rack slots for an account building a list of empty slots
empty_slot_list=[] # Create the list
cellar_locations = Location.objects.filter(type_id='4',account=owner) # Get rack slots
for l in cellar_locations: #Iterate through each location
# check if the are any wines in the location
# print(l.name, l.id,l.location_qty,l.account)
wlv = WineLocationValues.objects.filter(location_id = l.id,account=l.account)
if not wlv:
# If no records then this is an empty slot - add to the list
empty_slot_list.append(l.name)
return empty_slot_list