Source code for reports.views

from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from django.template import loader
from datetime import date,timedelta,datetime
from django.utils.timezone import now
from django.shortcuts import render,redirect,get_object_or_404
from django.urls import reverse,reverse_lazy
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.http import HttpResponse,HttpResponseRedirect,Http404,QueryDict
from django.contrib import messages
from django.db.models import F,Q
import csv,codecs
from django.db import models 
from core.functions import get_account_name,empty_rack_slots,get_account_id,addition_check
from core.models import Account,Addition,Bottle,ShipUnit,Style,WineLocationValues
from core.models import Location,LocationType
from notes.models import Notes
import importlib
from itertools import chain
from core.functions import allocate
from notes.functions import create_note,add_note_message
from .forms import OrderForm

[docs] def winestyles(request,style_rep): #Get all wines of the style selected # iterate through each location type in the template # 8 June - update for Account feature # get account details account_name = get_account_name(request) account_id= Account.objects.get(account=account_name) filter = Style.objects.get(pk = style_rep) wlv = WineLocationValues.objects.filter(style=filter.pk,account=account_id) wlv_count=wlv.count() print('style_rep = ',style_rep) print('filter name = ',filter.name) print('number of wines found =',wlv_count) context = {'style' : filter , 'style_count': wlv_count, 'locationtypes' : LocationType.objects.exclude(pk=1).order_by('pk'), 'wines' : wlv} return render(request, 'reports/winestyles.html',context)
[docs] def stylestest(request): #styles = style.objects.all() #context = {"styles": styles, # } return render(request, 'base/test_select.html')
[docs] @login_required(login_url='login') def audit_report(request): # Create the HttpResponse object with the appropriate CSV header. response = HttpResponse( content_type="text/csv;charset=UTF-8", headers={"Content-Disposition": 'attachment; filename="Cellar Wine Audit.csv"'}, ) with codecs.open('Cellar Wine Audit.csv', 'w', 'utf-8-sig') as csvfile: writer = csv.writer(response) writer.writerow(["Location Type"," Location Name", "Location ID","Wine", "Wine ID","Quantity", "Style","Style ID", "Year","Country","Size"]) report = Addition.objects.prefetch_related('wine_location') style_details =Style.objects.all locations = Location.objects.exclude(type_id='1').order_by('type_id',"name") for l in locations : print(l.name,l.location_qty) if l.location_qty == 0: #report empty locations writer.writerow([l.type, l.name, l.pk, 'empty', '-', '-', '-', '-', '-', '-', ]) else: s=l.addition_set.all() for a in s : style_detail_id = Style.objects.get(name=a.style) writer.writerow([l.type, l.name, l.pk, a.name, a.pk, a.quantity, a.style, style_detail_id.pk, a.year, a.country, a.size, ]) return response
[docs] @login_required(login_url='login') def open_orders(request): # 8 June - update for Account feature # get account details account_name = get_account_name(request) account_id= Account.objects.get(account=account_name) orders = Addition.objects.all().filter(addition_status = 'Ordered',account=account_id) # have used 4 as Received is 5 context = {"orders": orders, } return render(request, 'reports/open_orders.html',context)
[docs] @login_required(login_url='login') def receiveorder(request,id): # Documentation """ Overview Set an Order to Recieved. - Wine status set to received - Create a temp location record - so we can put away (see addtion process). - Create wine.location record to support M2M processes - Update wine note """ #================================ account_name = get_account_name(request) account_id= Account.objects.get(account=account_name) order = Addition.objects.get(pk=id) order.addition_status = 'Received' order.save() temp_location = Location(name = order.id, location_qty = order.quantity, type_id = '1', ) temp_location.save() order.wine_location.add(temp_location) message = 'Wine Received' add_note_message(order.id,message,account_id) #create_note('R',account_id,order.id) message = 'Order for ' + order.name + ' is now ready for put away. Wine Note updated' messages.success(request, message) response = redirect('/') return response
[docs] @login_required(login_url='login') def put_away_list(request): #Added account 8 June account_name = get_account_name(request) account_id= Account.objects.get(account=account_name) #build list of addition records that are received or part allocated received = Addition.objects.filter(addition_status= 'Received',account=account_id ) part_alloc = Addition.objects.filter(addition_status= 'Part Allocated') result_list = list(chain(part_alloc, received)) if len(result_list)==0: message = ' All wines have been put away' # next = 'index' next = '/' messages.success(request, message) #return render(request, './home') return redirect(next) # redirect to put away list after process else: context = { 'content' : result_list, } template = loader.get_template('reports/put_away_list.html') return HttpResponse(template.render(context, request))
#return HttpResponse('Simple Dev screen response')
[docs] def test(request): pass
[docs] def wine_update(request): pass
[docs] @login_required(login_url='login') def add_wine(request): # Documentation """ Retail additions - these wines are received immediately. - set status to received status - add to a temp bin. - temp bin name is the same as as the wine id to suppurt put away # initialise required items so we can check they have been set - create anote with associated text """ # =========================================== # get account details account_name = get_account_name(request) account_id= Account.objects.get(account=account_name) f_add_type = "Retail" valid = 'true' account_name = get_account_name(request) account_id= Account.objects.get(account=account_name) if request.method == "POST": # validate form and if valid add wine f_name = request.POST['name'] f_style = request.POST['winestyle'] f_style_key = (f_style) f_country = request.POST['country'] f_size = request.POST['winesize'] f_vintage = request.POST['vintage'] f_unit_price = request.POST['unit_price'] f_unit_price = float(f_unit_price) f_unit_price = "%.2f" % f_unit_price # convert unit price to monetary format f_del_unit = request.POST['del_unit'] # gives qty in a del unit f_del_qty = request.POST['del_qty'] f_supplier_name = request.POST['supplier_name'] calc_qty = int(f_del_unit) * int(f_del_qty) # - calc qty f_del_unit_type= ShipUnit.objects.get(qty=f_del_unit) # convert the qty to ship type f_order_ref = "Retail" f_duty ="0" f_del_charges ="0" f_del_date = datetime.now() f_abv = ".00" f_vat = "True" f_addition_status = "Received" f_account = account_id ##### prep for addition save ... if valid == 'true': new_wine = Addition(name = f_name, style_id = f_style, country_id= f_country, year=f_vintage, size_id = f_size, price=f_unit_price, abv=f_abv, source = f_supplier_name, duty = f_abv, vat = f_vat, quantity = calc_qty, # check quantity delivery_qty = f_del_qty, delivery_unit_id = f_del_unit_type.id, #> 1 unit implies case order_ref = f_order_ref, ship_costs = f_del_charges, expected_delivery = f_del_date, addition_status = f_addition_status, account = f_account ) #print('account=',f_account) ##### save to addition new_wine.save() ##### Get the new wine details for Note creation w_id= new_wine.id w_account = new_wine.account new_location =Location(name = new_wine.id, location_qty = calc_qty, type_id = '1', ) new_location.save() new_wine.wine_location.add(new_location) #create a note for the wine print('Wine id =',w_id) create_note('A',w_account,w_id) print ('line 276 - params :',account_id,w_id ) #### create user messages # todo - move this logic to functions # bottle_size = Bottle.objects.get(id=f_size) if calc_qty > 1: message =f'{calc_qty} Bottles({bottle_size.cl} cl) of {f_name}' else: message =f'A Bottle({f_size}) of {f_name}' print('addition status = ',f_addition_status ) if f_addition_status == "Received": message = f'{message} added. Now you need to put away in a location.' next = '/' # change to put away when ready else: message = f'{message} ordered.' next = '/' # change to put away when ready messages.success(request, message) return redirect(next) # redirect to put away when ready else: # invalid form print('Error -invalid form No Post') messages.error(request, message) template = loader.get_template('reports/add_wine.html') return HttpResponse(template.render({}, request)) else: # Display Form for 1st time print('Initial Form Display') template = loader.get_template('reports/add_wine.html') return HttpResponse(template.render({}, request))
[docs] @login_required(login_url='login') def put_away(request,wine_id): # Start #Added account 8 June account_name = get_account_name(request) account_id= Account.objects.get(account=account_name) #print('AC ID =',account_id.id) putaway_selection ='empty' bin_selection = 'empty' #populated after Bin chosen and Bin selected capacity_chk = 1 # [todo work out case restrictions] bin_capacity_chk = 0 # Flag set to True if bin capacity available for allocation rack_capacity_chk = 0 # Flag set to True if rack capacity available for allocation wine = Addition.objects.get(id = wine_id) left_to_alloc = wine.quantity-wine.allocation_qty # get the spare bin and rack capacity #free_bin,free_rack = type_capacity(account_id) # gets total spare capacity by type #print('free rack count=',free_rack) binlist = Location.objects.filter(account_id=account_id,type_id=2) free_bin = binlist.count() free_bin = free_bin*99 racklist = empty_rack_slots(account_id) free_rack = len(racklist) print('free_rack =',free_rack) #print('racklist =',racklist) # check bin and rack capacity available # case capacity:1,case & bin:2, case & rack: 4,case, bin and rack = 5 if free_bin > left_to_alloc: capacity_chk = capacity_chk + 1 # Bin capacity = +1 if free_rack > 0 : # allows part allocation to rack(s) and rest to bin/case capacity_chk = capacity_chk + 3 # Rack capacity = +3 context = { 'wine' : wine, 'to_allocate' : left_to_alloc, 'free_bin' : free_bin, 'free_rack' : free_rack, 'capacity_chk' : capacity_chk, 'putaway_selection': putaway_selection, 'binlist': binlist, 'racklist' : racklist } if request.method == "POST": # Get Put away choices # Get putaway type selected if 'putaway_selection' in request.POST: # process the putaway choice putaway_selection = request.POST['putaway_selection'] context.update({'putaway_selection': putaway_selection,}) else: # User has submitted form without selecting a putaway option putaway_selection = False # Process putaway selection if putaway_selection == 'Case': # Create a case and put remaining wine away in the case allocate(wine_id,'Case','opt',account_id) #Create a put away note in cellar notes message = f' {wine.quantity} bottle(s) of {wine.name} put away.' next = 'put_away_list' messages.success(request, message) return redirect(next) # redirect to put away list after process elif putaway_selection == 'Bin': #Display bins and then put remaining wine away in the selected Bin if 'bin_selection' in request.POST: # bin has been selected so allocate remainder to the bin bin_selection = request.POST['bin_selection'] bin_name = Location.objects.get(type_id='2',name=bin_selection,account=account_id.id) allocate(wine_id,'Bin',bin_name.name,account_id) message='Put Away' add_note_message(wine_id,message,account_id) #create_note('P',account_id,wine_id) print('create note type P successful') message = f' {wine.quantity} bottle(s) of {wine.name} put away.' messages.success(request, message) next = 'put_away_list' return redirect(next) # redirect to put away list after process else: # No bin selected, display bins for put away context.update({'putaway_selection': putaway_selection}) template = loader.get_template('reports/putaway.html') return HttpResponse(template.render(context, request)) elif putaway_selection == 'Rack': #Put 1 bottle away in an empty rack slot #print('put away selection = ',putaway_selection) if 'rack_selection' in request.POST: rack_selection = request.POST['rack_selection'] print('rack selection = ',rack_selection) rack_name = Location.objects.get(type_id='4',name=rack_selection,account=account_id) allocate(wine_id,'Rack',rack_name.name,account_id) # get the latest allocation values for wine and update context wine = Addition.objects.get(id = wine_id) context.update({'putaway_selection': putaway_selection,'racklist':racklist, 'wine':wine}) #Create a put away note in cellar notes create_note('P',account_id,wine_id) next = 'put_away_list' return redirect(next) # redirect to put away list after process else: template = loader.get_template('reports/putaway.html') return HttpResponse(template.render(context, request)) #template = loader.get_template('reports/putaway.html') #return HttpResponse(template.render(context, request)) create_note('P',account_id,wine_id) #template = loader.get_template('reports/putaway.html') else: # Putaway type has not been selected message = 'You must select a put away type ' next = 'put_away_list' messages.error(request, message) #return redirect(next) # redirect to put away list after process template = loader.get_template('reports/putaway.html') return HttpResponse(template.render(context, request)) template = loader.get_template('reports/putaway.html') return HttpResponse(template.render(context, request)) context.update({'put_away_selection': putaway_selection}) template = loader.get_template('reports/putaway.html') return HttpResponse(template.render(context, request))
[docs] @login_required(login_url='login') def drink(request,int): ### Account release - Added account details account_name = get_account_name(request) account_id= Account.objects.get(account=account_name) wlv = WineLocationValues.objects.get(pk=int) print('wlv wine id =',wlv.wine) wine = Addition.objects.get(id = wlv.wine_id,account=account_id) location = Location.objects.get(id=wlv.location_id,account=account_id) upd_status = '' note_msg = '' my_flag = '' my_message ='' context = { 'wine' : wine, 'location' : location, 'upd_status' : upd_status, 'note_msg' : note_msg, 'my_flag' : my_flag, 'my_message' : my_message, } # Reduce Addition qty by 1. If qty = 0, set to drunk else Tasted qty = wine.quantity qty = qty -1 if qty < 0: # Check if this is the last bottle to update addition status qty = 0 status = 'Drunk' elif qty == 0: status = 'Drunk' else: status = 'Tried' wine.quantity = qty wine.addition_status= status # Reduce Location Quantity by 1 qty = location.location_qty print ('location qty =',qty,flush=True) qty = qty -1 if qty < 0: qty = 0 location.location_qty = qty try: # Update Wine - Wine, M2M, WLV and add Note try: wine.save() print('wine saved and id =',wine.id,flush=True) except: print ('wine save failed ',flush=True) try: location.save() print('location saved',flush=True) except: print('location save failed ',flush=True) # Update (M2M) addition_location if location.location_qty ==0: try: print ('Remove M2M record',flush=True) wine.wine_location.remove(location) upd_status = 'M2M Update Success' context.update({'upd_status' : upd_status,}) print (' M2M record removed',flush=True) except: print ('Failed in Remove M2M record',flush=True) # Update or delete WineLocationValues # # if qty = 1 then delete ( so we can create new records) # if qty > 1 then reduce by 1 if wlv.quantity == 1: try: wlv.delete() print('Reports - Drink View SUCCESS wlv record deleted') except: print('Reports - Drink View ERROR wlv delete failed') else : #take 1 away wlv_qty = wlv.quantity wlv_qty = wlv_qty -1 wlv.quantity = wlv_qty try: wlv.save() print('Reports - Drink View SUCCESS WLV record updated ',flush=True) except: print('Reports - Drink View ERROR unable to update WLV record',flush=True) # Create Wine Note # try: try: print('call create note',account_id,wine.pk) #create_note('C',account_id,wine.pk) message = 'Wine Drunk' add_note_message(wine.pk,message,account_id) except: print('create note failed !') message = f' {account_id} {wine.name} set to drunk and a tasting note created.' #my_flag = 'I' # go back to winelist next = '/reports/winelist' messages.success(request, message) return redirect(next) # redirect to put away list after process except: print('Drink - notes updates.Fail line 538 in reports view ',flush=True) upd_status = 'Update Failed ! ' message = 'Drink - notes updates.Fail line 538 in reports view' messages.error(request, message) context.update({'update status' : upd_status,}) except: print('Drink - notes updates.Fail line 545 in reports view ',flush=True) upd_status = 'Update Failed ! ' message = 'Drink - notes updates.Fail line 540 in reports view' messages.error(request, message) context.update({'update status' : upd_status,}) return render(request, 'reports/winelist.html')
#template = loader.get_template('reports/drink.html') #return HttpResponse(template.render(context, request))
[docs] @login_required(login_url='login') def createorder(request): # get account details account_name = get_account_name(request) account_id= Account.objects.get(account=account_name) # create object of form context ={} form = OrderForm(request.POST or None, request.FILES or None, initial={'quantity': '0', 'addition_status':'Ordered', 'account': account_id}) context['form'] = form if request.method == 'POST': order_post = OrderForm(request.POST) #print(request.POST) # check if form data is valid if form.is_valid(): order=form.save(commit=False) shipkey = form.cleaned_data.get('delivery_unit') shipqty=ShipUnit.objects.get(ship_unit=shipkey).qty del_unit_qty = form.cleaned_data.get('delivery_qty') order.quantity=int(shipqty) * int(del_unit_qty) order.account =account_id msg = form.cleaned_data.get('order_ref') # save the form data to model order.save() #create a note for the wine w_id= order.id print('Wine id =',w_id) create_note('O',order.account,w_id) print ( 'line 569 - params :',account_id,w_id ) msg = 'Order Ref : ' + form.cleaned_data.get('order_ref') + ' saved.' response = redirect('/') return response else: print('notes update is not valid line 575') context = {'form':form, } return render(request, 'reports/order-form.html',context) return render(request, "reports/order-form.html", context)
[docs] @login_required(login_url='login') def winelist(request): #Added account 8 June account_name = get_account_name(request) account_id= Account.objects.get(account=account_name) wines = WineLocationValues.objects.filter(quantity__gt=0,account=account_id.id) context = {'wines' : wines} return render(request, 'reports/winelist.html',context)
[docs] @login_required(login_url='login') def empty_slots(request): #Updated for Account Release account_name = get_account_name(request) account_id= Account.objects.get(account=account_name) slot_list=empty_rack_slots(account_id) # Create the list num_slots=len(slot_list) context = {'slot_list' : slot_list, 'num_slots': num_slots} return render(request, 'reports/emptyslots.html',context)
[docs] @login_required(login_url='login') def addition_errors(request): #Moved to separate page 16 Aug account_name = get_account_name(request) account_id= Account.objects.get(account=account_name) owner_id= int(account_id.id) addition_status,errors = addition_check(owner_id) return render(request, "reports/addition_error_list.html", {'errors' : errors, })