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
Beispiel #3
0
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)
Beispiel #5
0
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)
Beispiel #6
0
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()
Beispiel #9
0
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
Beispiel #11
0
    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)
Beispiel #14
0
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)
Beispiel #15
0
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) + "}"
Beispiel #16
0
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)
Beispiel #17
0
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)
Beispiel #20
0
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)
Beispiel #21
0
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)
Beispiel #23
0
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 "{}"
Beispiel #26
0
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 "{}"
Beispiel #28
0
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")
Beispiel #29
0
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'