3
\$\begingroup\$

I have written a service which can generate prices from inputs. However, I feel that this can be "refactored" because it is not flexible enough. The code "works" however I feel if I could make this more "observable based." Any pointer will be greatly appreciated.

According to the Angular Style Guide, it is beneficial to inject services into our components as they handle our data in an agnostic way (cool.) I would like to take this to the next level and begin to learn how to refactor my services (maybe into even smaller services ! ) in order to make these functions more "elastic".

As you can see, I am not applying DRY, and other principles as there are many duplicate variables involved.

import { Injectable } from '@angular/core';

export class Term {
    term: number;
    monthly: number;
    mrm: number;
    moneyFactor: number;
    rebatesNT: number;
    rebatesT: number;
    profit: number;
    buying: number;
    residuals: number;
    dmvFee: number;
    docFee: number;
    bankFee: number;
    onePayMF: number;
}

class PriceColumn {
    monthly: any;
    first: any;
    bank: any;
    dmv: any;
    doc: any;
    taxes: any;
    shipping: any;
    capRed: any;
    excFees: any;
    total: any;
    raw?: Term;

}

export class Prices {
    taxUpFront: PriceColumn;
    taxIncluded: PriceColumn;
    taxBankIncluded: PriceColumn;
    firstDue: PriceColumn;
    signAndDrive: PriceColumn;
    onePay: PriceColumn;
}
@Injectable()
export class WorkDealService {
    private taxRate = .08875;


    constructor() {}

    // initilizeLocalVariables(term: Term) {
    // }


    getPriceObject(term: Term, invoice) {
        console.log(term, invoice)

        // this.initilizeLocalVariables(term);
        let price = new Prices();
        price.taxUpFront = this.taxUpFront(term, invoice);
        price.taxIncluded = this.taxIncluded(term, invoice);
        price.taxBankIncluded = this.taxBankIncluded(term, invoice);
        price.firstDue = this.firstDue(term, invoice);
        price.signAndDrive = this.signAndDrive(term, invoice);
        price.onePay = this.onePay(term, invoice);
        return price;
    }



    onePay(term: Term, invoice: number): PriceColumn { // Lines 180-196
        let onePay = new PriceColumn();

        let included = 0;
        let excFees = 0;
        let negEq = 0;
        let msrpDiff = 0;
        let tireTax = 0;
        let shipping = 0;
        let rebates = term.rebatesT + term.rebatesNT;
        let cost = invoice + term.buying;
        // no carpet,exsc fee here
        let selling = cost - rebates + term.profit + negEq + msrpDiff;
        let baseRent = (selling - term.residuals) / term.term;
        let rentInt = (selling + term.residuals) * term.moneyFactor;
        let totalRebatesT = term.rebatesT + term.rebatesNT;
        if (!isNaN(term.onePayMF)) {
            let onePayRentInt = (selling + term.residuals) * term.onePayMF;
            let monthly = this.roundUp(baseRent + onePayRentInt),
                taxes = this.roundUp(((monthly * term.term) + term.bankFee + totalRebatesT) * this.taxRate + tireTax);
            onePay.monthly = monthly;
            onePay.first = (monthly * term.term);
            onePay.bank = term.bankFee;
            onePay.dmv = term.dmvFee;
            onePay.doc = term.docFee;
            onePay.taxes = taxes;
            onePay.shipping = shipping;
            onePay.capRed = included;
            onePay.total = ((monthly * term.term) + term.bankFee + term.dmvFee + term.docFee + taxes + shipping);
        }
        //

        //no total base rt here

        return onePay;
    }

    taxUpFront(term: Term, invoice: number): PriceColumn {// Lines 162-178
        console.log(term, invoice)
        let taxUpFront = new PriceColumn();

        let capred = 0;
        let excFees = 0;
        let negEq = 0;
        let msrpDiff = 0;
        let tireTax = 0;
        let shipping = 0;
        let rebates = term.rebatesT + term.rebatesNT;
        let cost = invoice + term.buying;
        let selling = cost - rebates + term.profit - capred + excFees + negEq + msrpDiff;
        let baseRent = (selling - term.residuals) / term.term;
        let rentInt = (selling + term.residuals) * term.moneyFactor;
        let taxUpFrontMonthly = baseRent + rentInt;
        let monthly = this.roundUp(taxUpFrontMonthly);
        let totalRebatesT = term.rebatesT + term.rebatesNT;
        let taxes = this.roundUp(((term.monthly * term.term) + term.bankFee + totalRebatesT + capred - excFees + term.docFee) * this.taxRate + tireTax);

        taxUpFront.monthly = monthly;
        taxUpFront.first = monthly;
        taxUpFront.bank = term.bankFee;
        taxUpFront.dmv = term.dmvFee;
        taxUpFront.doc = term.docFee;
        taxUpFront.taxes = taxes;
        taxUpFront.shipping = shipping;
        taxUpFront.capRed = capred;
        taxUpFront.excFees = (-excFees);
        taxUpFront.total = monthly + term.bankFee + term.dmvFee + term.docFee + taxes + shipping + capred - excFees;
        taxUpFront.raw = term;
        // to do
        console.log(taxUpFront)
        return taxUpFront;
    }
    taxIncluded(term: Term, invoice: number): PriceColumn { // lines 198-218
        let taxIncluded = new PriceColumn(),
            capred = 0,
            excFees = 0,
            negEq = 0,
            msrpDiff = 0,
            tireTax = 0,
            shipping = 0,
            nyTaxRate = 0;

        let rebates = term.rebatesT + term.rebatesNT,
            cost = invoice + term.buying,
            selling = cost - rebates + term.profit - capred + excFees + negEq + msrpDiff,
            baseRent = (selling - term.residuals) / term.term,
            rentInt = (selling + term.residuals) * term.moneyFactor,
            totalTax = (baseRent + rentInt) * term.term * this.taxRate,
            totalRebatesT = term.rebatesT + term.rebatesNT,
            nyTax = totalTax * nyTaxRate,
            totalNYTax = totalTax + nyTax + tireTax,
            monthlyTax = totalNYTax / term.term,
            addLint = totalNYTax * term.moneyFactor,
            monthly = this.roundUp(baseRent + rentInt + monthlyTax + addLint),
            bankFeeTax = term.bankFee * this.taxRate,
            rebatesTax = totalRebatesT * this.taxRate,
            docTax = term.docFee * this.taxRate,
            taxes = this.roundUp(bankFeeTax + rebatesTax + docTax);
        taxIncluded.monthly = taxIncluded.first = monthly;
        taxIncluded.bank = term.bankFee;
        taxIncluded.dmv = term.dmvFee;
        taxIncluded.doc = term.docFee;
        taxIncluded.taxes = taxes;
        taxIncluded.shipping = shipping;
        taxIncluded.capRed = capred;
        taxIncluded.total = (monthly + term.bankFee + term.dmvFee + term.docFee + taxes + shipping + capred);

        return taxIncluded;
    }
    taxBankIncluded(term: Term, invoice: number): PriceColumn { // lines 220-237
        let taxBankIncluded = new PriceColumn(),
            capred = 0,
            excFees = 0,
            negEq = 0,
            msrpDiff = 0,
            tireTax = 0,
            shipping = 0,
            nyTaxRate = 0;

        let rebates = term.rebatesT + term.rebatesNT,
            cost = invoice + term.buying,
            selling = cost - rebates + term.profit - capred + excFees + negEq + msrpDiff + term.bankFee, // added bank
            baseRent = (selling - term.residuals) / term.term,
            rentInt = (selling + term.residuals) * term.moneyFactor,
            totalTax = (baseRent + rentInt) * term.term * this.taxRate,
            totalRebatesT = term.rebatesT + term.rebatesNT,
            nyTax = totalTax * nyTaxRate,
            totalNYTax = totalTax + nyTax + tireTax,
            monthlyTax = totalNYTax / term.term,
            addLint = totalNYTax * term.moneyFactor,
            monthly = this.roundUp(baseRent + rentInt + monthlyTax + addLint),
            bankFeeTax = term.bankFee * this.taxRate,
            rebatesTax = totalRebatesT * this.taxRate,
            docTax = term.docFee * this.taxRate,
            taxes = this.roundUp(rebatesTax + docTax); // not bank
        taxBankIncluded.monthly = taxBankIncluded.first = monthly;
        taxBankIncluded.bank = term.bankFee;
        taxBankIncluded.dmv = term.dmvFee;
        taxBankIncluded.doc = term.docFee;
        taxBankIncluded.taxes = taxes;
        taxBankIncluded.shipping = shipping;
        taxBankIncluded.capRed = capred;
        taxBankIncluded.total = (monthly + term.bankFee + term.dmvFee + term.docFee + taxes + shipping + capred);

        return taxBankIncluded;
    }
    firstDue(term: Term, invoice: number): PriceColumn { // 239-255
        let taxBankIncluded = new PriceColumn(),
            capred = 0,
            excFees = 0,
            negEq = 0,
            msrpDiff = 0,
            tireTax = 0,
            shipping = 0,
            nyTaxRate = 0;
        let included = 0;
        let rebates = term.rebatesT + term.rebatesNT,
            cost = invoice + term.buying,
            selling = cost - rebates + term.profit - capred + excFees + negEq + msrpDiff + term.bankFee
                + term.dmvFee + term.docFee + shipping + rebates, // added dmv, doc, shipping,rebate
            baseRent = (selling - term.residuals) / term.term,
            rentInt = (selling + term.residuals) * term.moneyFactor,
            totalTax = (baseRent + rentInt) * term.term * this.taxRate,
            totalRebatesT = term.rebatesT + term.rebatesNT,
            nyTax = totalTax * nyTaxRate,
            totalNYTax = totalTax + nyTax + tireTax,
            monthlyTax = totalNYTax / term.term,
            addLint = totalNYTax * term.moneyFactor,
            monthly = this.roundUp(baseRent + rentInt + monthlyTax + addLint);
        // bankFeeTax = term.bankFee * taxRate,
        // rebatesTax = totalRebatesT * taxRate,
        // docTax = term.docFee * taxRate,
        // taxes = this.roundUp(rebatesTax + docTax);
        // they are not here
        taxBankIncluded.monthly = taxBankIncluded.first = monthly;
        taxBankIncluded.bank = included;
        taxBankIncluded.dmv = included;
        taxBankIncluded.doc = included;
        taxBankIncluded.taxes = included;
        taxBankIncluded.shipping = included;
        taxBankIncluded.capRed = included;
        taxBankIncluded.total = (monthly);

        return taxBankIncluded;
    }
    signAndDrive(term: Term, invoice: number): PriceColumn { // lines 257-293
        //to do

        let signDrive = new PriceColumn(),
            capred = 0,
            excFees = 0,
            negEq = 0,
            msrpDiff = 0,
            tireTax = 0,
            shipping = 0,
            nyTaxRate = 0;
        let included = 0;
        let rebates = term.rebatesT + term.rebatesNT,
            cost = invoice + term.buying,
            selling = cost - rebates + term.profit - capred + excFees + negEq + msrpDiff + term.bankFee
        let termMinusOne = term.term - 1,
            baseRent = (selling - term.residuals) / termMinusOne,
            rentInt = (selling + term.residuals) * term.moneyFactor,
            totalTax = (baseRent + rentInt) * termMinusOne * this.taxRate,
            totalRebatesT = term.rebatesT + term.rebatesNT,
            nyTax = totalTax * nyTaxRate,
            totalNYTax = totalTax + nyTax + tireTax,
            monthlyTax = totalNYTax / termMinusOne,
            addLint = totalNYTax * term.moneyFactor,
            monthly = this.roundUp(baseRent + rentInt + monthlyTax + addLint);
        selling += monthly;

        // in this case monthly is calulated and added specifically to selling.

        baseRent = (selling - term.residuals) / term.term,
            rentInt = (selling + term.residuals) * term.moneyFactor,
            totalTax = (baseRent + rentInt) * term.term * this.taxRate,
            totalRebatesT = term.rebatesT + term.rebatesNT,
            nyTax = totalTax * nyTaxRate,
            totalNYTax = totalTax + nyTax + tireTax,
            monthlyTax = totalNYTax / term.term,
            addLint = totalNYTax * term.moneyFactor,
            monthly = this.roundUp(baseRent + rentInt + monthlyTax + addLint);


        signDrive.monthly = monthly;
        signDrive.first = included;
        signDrive.bank = included;
        signDrive.dmv = included;
        signDrive.doc = included;
        signDrive.taxes = included;
        signDrive.shipping = included;
        signDrive.capRed = included;
        signDrive.total = (0);
        return signDrive;


    }

      private roundUp(n) {
        return Math.ceil(n * 100) / 100;
    }

}
\$\endgroup\$
  • 1
    \$\begingroup\$ There's nothing wrong with your question, but you already pointed out what can be done differently. After you apply DRY, it will be possible to review the code for further improvements. Right now the changes to be applied are pretty mechanical. \$\endgroup\$ – Igor Soloydenko Sep 8 '17 at 19:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.