def getProfit(): if request.method == 'POST': year_filter = request.values.get('year') quotes = dbSession.query(Quote).filter( Project.company_name == current_user.company_name).filter( Project.status_name == 'Paid').filter( Project.finalize == True).filter( Quote.project_id == Project.project_id) # Filter Quotes by year if 0 is not given if year_filter != '0' and year_filter is not None: year_filter = int(year_filter) quotes = quotes.filter( extract('year', Project.end_date) == year_filter) quotes = quotes.order_by(Project.end_date).all() profits = [] projects = [] for quote in quotes: project = dbSession.query(Project).filter( Project.project_id == quote.project_id).one() projects.append(project.project_name) profits.append(quote.profit) dictionary = {"projects": projects, "profits": profits} return jsonify(dictionary) return bad_request('Request is not a POST request')
def calculateQuote(project, misc_modifier, gst_rate): layout_id = project.layout_selected appearance_id = project.appearance_selected layout = dbSession.query(Layout).filter( Layout.layout_id == layout_id).one() appearance = dbSession.query(Appearance).filter( Appearance.appearance_id == appearance_id).one() appearance_value, removal_value, gate_single_value, gate_double_value = Appearances.getAppearanceValues( appearance) # Get layout info and pass to parser parsed = DiagramParser.parse(layout.layout_info) # Pass parsed layout to calculate prices for each object prices = QuoteCalculation.prices(parsed, appearance_value, removal_value, gate_single_value, gate_double_value) # Calculate subtotal, gst, and total subtotal = PriceCalculation.subtotal(prices) if misc_modifier is not None: subtotal += misc_modifier gst = subtotal * gst_rate total = subtotal + gst # PDF Should be generated too return subtotal, gst, total
def sendQuote(): """Email a quote to a customer""" proj_id = request.args.get('proj_id') custEmail = request.json['email'] pdf = None if "pdf" in request.json: if request.json["pdf"] != "": pdf = request.json["pdf"] project = dbSession.query(Project).filter( Project.project_id == proj_id).one() customer = dbSession.query(Customer).filter( Customer.customer_id == project.customer_id).one() company = dbSession.query(Company).filter( Company.company_name == project.company_name).one() message = Messages.quoteMessage(customer, company) layout = dbSession.query(Layout).filter( Layout.layout_id == project.layout_selected).one() parsed = DiagramParser.parse(layout.layout_info) if pdf: attachment = pdf else: attachmentString = Messages.quoteAttachment(project, customer, parsed) attachment = Email.makeAttachment(Messages.quotePath, attachmentString) if attachment is not None: Email.send(app, mail, project.company_name, custEmail, "Your quote", message, "Quote", attachment) return "{}"
def projectdetails(project_id): """Retrieve project details""" if request.method == "GET": project = dbSession.query(Project).filter( Project.project_id == project_id).one() selectedLayout = project.layout_selected selectedAppearance = project.appearance_selected layouts = Layouts.getLayouts(project_id) json_layouts = [i.serialize for i in layouts] parsedLayouts = [DiagramParser.parse(i.layout_info) for i in layouts] displayStrings = [] json_appearances = Appearances.getAppearanceList(project_id) customer = dbSession.query(Customer).filter( Customer.customer_id == project.customer_id).one() customerName = customer.first_name customerId = customer.customer_id for layout in parsedLayouts: if layout is None: displayStrings.append([]) else: displayStrings.append(layout.displayStrings()) # Get relative path to project pictures imgPath = repr(os.path.join('..', Pictures.pictureDir, '')) tbnPath = repr(os.path.join('..', Pictures.thumbnailDir, '')) heights = [i.height for i in Estimates.getHeights()] styles = [i.style for i in Estimates.getStyles()] colours = [i.colour for i in Estimates.getColours()] company = dbSession.query(Company).filter( Company.company_name == current_user.company_name).one() companyName = company.company_name supplierEmail = company.supplier_email quote = dbSession.query(Quote).filter( Quote.project_id == project_id).first() if quote is None: quotePdf = "" supplyPdf = "" else: quotePdf = quote.quote_pdf supplyPdf = quote.supply_pdf lst = [ imgPath, tbnPath, json_layouts, json_appearances, companyName, selectedLayout, selectedAppearance, displayStrings, customerName, customerId, heights, styles, colours, supplierEmail, quotePdf, supplyPdf ] return jsonify(lst)
def acceptUser(): """ accepts user, in app.py because of userDatastore """ if request.method == 'POST': user_id = request.values.get("user_id") user = dbSession.query(User).filter(User.id == user_id).all() userDatastore.activate_user(user[0]) user[0].active = True dbSession.commit() users = dbSession.query(User).filter(User.active == False).all() return jsonify(users)
def uploadPrice(): """ Parses the given csv file into fencing materials prices for a given company """ company_name = current_user.company_name if request.method == 'POST': priceFile = request.files['prices'] if not priceFile: return bad_request('Invalid price file uploaded') stream = io.StringIO(priceFile.stream.read().decode("UTF8"), newline=None) csv_input = csv.reader(stream) # Clear materials list? This will cause issues for appearances due to ForeignKeys dbSession.query(Material).filter( Material.company_name == current_user.company_name).delete() category = '' for row in csv_input: if row[2] == 'My Price' and row[4] == 'Pieces in Bundle': # Category category = row[0] if row[0] != '' and row[2] == '' and row[4] == '': # Category category = row[0] if row[1].startswith('$') and row[2].startswith('$'): # Material try: my_price = Decimal(row[2][1:]) except: print( 'My Price value could not be converted into a Decimal, default to 0' ) my_price = 0 try: pieces_in_bundle = Decimal(row[4]) except: print( 'Pieces in bundle value could not be converted into a number, default to 1' ) pieces_in_bundle = 1 material_name = row[0] note = row[5] # Insert data into db newMaterial = Material(material_name=material_name, my_price=my_price, pieces_in_bundle=pieces_in_bundle, category=category, note=note, company_name=current_user.company_name) dbSession.add(newMaterial) # Otherwise, ignore row dbSession.commit() return created_request('Prices were changed') return bad_request('Request is not a POST request')
def removeProject(proj_id): """Delete image files""" pictures = dbSession.query(Picture).filter( Picture.project_id == proj_id).all() for image in pictures: Pictures.deleteImageHelper(image.file_name) Pictures.deleteImageHelper(image.thumbnail_name) """Cascade delete all information related to project""" project = dbSession.query(Project).filter( Project.project_id == proj_id).one() dbSession.delete(project) dbSession.commit()
def removeCustomer(cust_id): """Helper function for deleteproject()""" #Get all projects projects = dbSession.query(Project).filter(Project.customer_id == cust_id) for proj in projects: removeProject(proj.project_id) # Cascade delete all information related to project cust = dbSession.query(Customer).filter( Customer.customer_id == cust_id).one() dbSession.delete(cust) dbSession.commit()
def getActiveUsers(): """ Returns a list of active users""" if request.method == 'GET': users = dbSession.query(User).filter(User.active == True).filter(User.id != current_user.id).all() if len(users) == 0: return bad_request("No active users were found") return jsonify(users)
def getQuoteInfo(): quote = dbSession.query(Quote).all() dbSession.commit() return quote
def test_noQuote(self): """ Tests for adding a user """ # Test if there are no user self.tearDown() noQuote = dbSession.query(Quote).all() assert len(noQuote) == 0
def calculateExpense(material_types, material_amounts, gst_rate): categories = [ 'metal_post', 'metal_u_channel', 'metal_lsteel', 'plastic_t_post', 'plastic_corner_post', 'plastic_line_post', 'plastic_end_post', 'plastic_gate_post', 'plastic_rail', 'plastic_u_channel', 'plastic_panel', 'plastic_collar', 'plastic_cap', 'gate_hinge', 'gate_latch' ] subtotal = 0 materials = dbSession.query(Material).filter( Material.company_name == current_user.company_name) # For each category in the dictionary, use the material_id and query for data # number of materials needed / number of materials per bundle * price of material for category in categories: amount = material_amounts[category] if amount == "": amount = 0 else: amount = int(amount) material = materials.filter( Material.material_id == int(material_types[category])).one() subtotal += math.ceil( amount / material.pieces_in_bundle) * material.my_price # Calculate gst gst = subtotal * gst_rate total = subtotal + gst # PDF Should be generated too return subtotal, gst, total
def getStatusList(): """ Returns the list of statuses """ if request.method == "GET": statuses = dbSession.query(Status).all() if len(statuses) == 0: return bad_request("No statuses were found") return jsonify(statuses)
def getInactiveUsers(): """ Returns a list of inactive users""" if request.method == 'GET': users = dbSession.query(User).filter(User.active == False).all() if len(users) == 0: return bad_request("No inactive users were found") return jsonify(users)
def saveAppearance(): """For saving or updating apperance options""" project_id = request.args.get('proj_id') appearance_id = None if 'appearanceId' in request.json: appearance_id = request.json['appearanceId'] appearance_name = request.json['name'] style = request.json['style'] height = request.json['height'] border_colour = request.json['borderColor'] panel_colour = request.json['panelColor'] base_price = request.json['basePrice'] appearance_id = updateAppearanceInfo(project_id, appearance_id, appearance_name, style, height, border_colour, panel_colour, base_price) if "saveSelection" in request.json: project = dbSession.query(Project).filter( Project.project_id == project_id).one() project.appearance_selected = appearance_id dbSession.commit() return "{" + '"appearanceId": {appearance_id}'.format( appearance_id=appearance_id) + "}"
def editcompany(): company = dbSession.query(Company).filter( Company.company_name == current_user.company_name).one() supplierEmail = company.supplier_email office = company.office phone = company.phone web = company.web disclaimer = company.disclaimer if supplierEmail is None: supplierEmail = "" if office is None: office = "" if phone is None: phone = "" if web is None: web = "" if disclaimer is None: disclaimer = "" return render_template("editcompany.html", company=company.company_name, supplierEmail=supplierEmail, office=office, phone=phone, web=web, disclaimer=disclaimer)
def editgst(): company = dbSession.query(Company).filter( Company.company_name == current_user.company_name).one() gst = round(PriceCalculation.gstPercent() * Decimal("100"), 0) return render_template("editgst.html", company=company.company_name, gst=str(gst))
def finalizeQuote(): if request.method == 'POST': """ Given a project ID and a boolean finalize. Turn finalize to false if finalize is False. Generate and save the quote and material expenses if finalize is True Customer quote is calculated for each fence by the following formula. quote = length * (style + height + base price + (border colour + panel colour) / 2) """ project_id = request.values.get('proj_id') # A dictionary with keywords and values of material_ids material_types = json.loads(request.values.get('material_types')) # A dictionary with keywords and values of the amount of material needed material_amounts = json.loads(request.values.get('material_amounts')) misc_modifier_label = request.values.get('misc_modifier_label') # A flat rate which allows the user to alter the subtotal of the quote misc_modifier = request.values.get('misc_modifier') if misc_modifier == "": misc_modifier = 0 else: misc_modifier = int(misc_modifier) payment = request.values.get('payment') notes = request.values.get('notes') description = request.values.get('description') project = dbSession.query(Project).filter( Project.project_id == project_id).one() if project is None: print('Project does not exist') return bad_request('Project does not exist') if material_types is None or material_amounts is None: print('Material Parameters not given') return bad_request('Material Parameters not given') if project.finalize: print('Project has already been finalized') return bad_request('Project has already been finalized') project.finalize = True try: newQuote = generateQuote(project, material_types, material_amounts, misc_modifier, payment, notes, misc_modifier_label, description) dbSession.add(newQuote) dbSession.commit() except BaseException as e: raise e print('Error in saving the quote') return bad_request('Error in saving the quote') return created_request('Quote has been generated') print('Request is not a POST request') return bad_request('Request is not a POST request')
def getCustomer(customer_id): """ Returns a response for a single customer of the given customer id """ if request.method == 'GET': customer = dbSession.query(Customer) customer = customer.filter(Customer.customer_id == customer_id).all() if len(customer) == 0: return bad_request("The customer was not found") return jsonify(customer)
def home(): if current_user.has_role('admin'): users = dbSession.query(User).filter( User.active == True) # need to add filter role return render_template("users.html", company="Admin", users=users) else: return render_template("dashboard.html", company=current_user.company_name)
def viewMaterialList(): """Generate and view a material list in a new tab""" proj_id = request.args.get('proj_id') project = dbSession.query(Project).filter( Project.project_id == proj_id).one() layout = dbSession.query(Layout).filter( Layout.layout_id == project.layout_selected).one() parsed = DiagramParser.parse(layout.layout_info) attachmentString = Messages.materialListAttachment(project) attachment = Email.makeAttachment(Messages.materialListPath, attachmentString) if attachment is not None: url = url_for("static", filename=attachment) return jsonify({"url": url}) return jsonify({"reload": 1})
def getProject(project_id): """ Returns a single project of a given project id """ if request.method == "GET": project = dbSession.query(Project) project = project.filter(Project.project_id == project_id).all() if len(project) == 0: return bad_request("The project was not found") return jsonify(project)
def getAppearanceValues(appearance): """ Finds and Returns values related to the given appearance object """ # Get values of selected Appearance using Contains query style_value = dbSession.query(Style).filter( Style.style == appearance.style).filter( Style.company_name == current_user.company_name).one().value height_value = dbSession.query(Height).filter( Height.height == appearance.height).filter( Height.company_name == current_user.company_name).one().value border_colour_value = dbSession.query(Colour).filter( Colour.colour == appearance.border_colour).filter( Colour.company_name == current_user.company_name).one().value panel_colour_value = dbSession.query(Colour).filter( Colour.colour == appearance.panel_colour).filter( Colour.company_name == current_user.company_name).one().value base_price = appearance.base_price # Calculate appearance multiplier for fence quotation appearance_value = style_value + height_value + base_price + ( (border_colour_value + panel_colour_value) / 2) # Get value of fence removal removal_value = dbSession.query(Style).filter( Style.style == 'Removal').filter( Style.company_name == current_user.company_name).one().value # Get values of Gates gate_single_value = dbSession.query(Gate).filter( Gate.gate.contains('Man')).filter( Gate.company_name == current_user.company_name).one().value gate_double_value = dbSession.query(Gate).filter( Gate.gate.contains('RV')).filter( Gate.company_name == current_user.company_name).one().value return appearance_value, removal_value, gate_single_value, gate_double_value
def unfinalizeQuote(): if request.method == 'POST': project_id = request.values.get('proj_id') project = dbSession.query(Project).filter( Project.project_id == project_id).one() quoteToDelete = dbSession.query(Quote).filter( Quote.project_id == project_id) quoteFiles = quoteToDelete.one() deletePDFHelper(quoteFiles.quote_pdf) deletePDFHelper(quoteFiles.supply_pdf) quoteToDelete.delete() project.finalize = False dbSession.commit() return "{}" return bad_request('Request is not a POST request')
def saveLayoutSelection(): """Saving layout on projectinfo page""" project_id = request.args.get("proj_id") selected = request.json["selected"] project = dbSession.query(Project).filter( Project.project_id == project_id).one() project.layout_selected = selected dbSession.commit() return "{}"
def getPictureList(project_id): """ Returns a list of pictures for a given project id""" if request.method == 'GET': pictures = dbSession.query(Picture) pictures = pictures.filter(Picture.project_id == project_id).order_by( desc(Picture.upload_date)).all() if len(pictures) == 0: return bad_request("No pictures were found for this project") return jsonify(pictures)
def saveLayoutName(): """ Update a layout's name """ layout_id = request.json['layoutId'] layout_name = request.json['name'] layout = dbSession.query(Layout).filter( Layout.layout_id == layout_id).one() layout.layout_name = layout_name dbSession.commit() return "{}"
def checkemail(): """ Checks if company exists """ if request.method == 'POST': email = request.values.get("email") check = len(dbSession.query(User).filter(User.email == email).all()) if check == 0: return created_request("Good") return bad_request("Bad")
def checkcompany(): """ Checks if company exists """ if request.method == 'POST': company = request.values.get("name") check = len(dbSession.query(Company).filter(Company.company_name == company).all()) if check == 0: return created_request("Good") return bad_request("Bad")
def test_addCustomer(self): """ Test for adding a customer """ # Test if there are no customers noCustomerTest = dbSession.query(Customer).all() assert len(noCustomerTest) == 0 # Try adding a customer through Customers api Customers.addCustomer('Kat', '*****@*****.**', '541-689-4681', 'Place', 'Fence') oneCustomerTest = dbSession.query(Customer).all() # Test the customer is successfully added assert len(oneCustomerTest) == 1 # Test the information from the found customer result = oneCustomerTest[0].serialize assert result['first_name'] == 'Kat' assert result['email'] == '*****@*****.**' assert result['cellphone'] == '541-689-4681' assert result['company_name'] == 'Fence'