2
\$\begingroup\$

I was sent here from StackOverflow to get some insight on how I can improve my code. I'm a beginner and the program is not streamlined at all.

What the program does:

  1. Takes an input of the Retail Price
  2. Takes an input of Supplier Price
  3. Takes an input of Cost per acquisition
  4. Takes an input of number of installments the store offers with no interest for the customer

What to take into consideration: The installments don't follow exact increments. The numbers are as follows: 0 (doesn't offer finance), 2 to 12, 15, 18 and 24 installments. What I would like the program to do is to either allow the person to pick the number of installments from a list OR if for example they input a number of installments that doesn't exist (like 13) it would show them only the closest available number of installments (in the case of 13 or 14 it would be from 0 to 12, skipping 1 as 1 is the same as 0. 16-23 would only show up to 15 and else would show 24 as that is the maximum number of installments).

I took into account that a lot of these print statements can be generated from a list or a dict but as a beginner the concepts are still a little confusing to me, hence I'm asking for your help.

#Product Retail Price
product_retail_price = float(input("Valor do produto na loja em Reais (Formato 00.00): "))

#Costs
product_cost = float(input("Valor do produto no fornecedor em Reais (Formato 00.00): "))
cpa = float(input("Custo por aquisição (Formato 00.00): "))
fee_shopify = (product_retail_price / 100)*2
fee_mercadopago = (product_retail_price / 100)*4.99
fee_finance_2 = (product_retail_price / 100)*2.03
fee_finance_3 = (product_retail_price / 100)*4.06
fee_finance_4 = (product_retail_price / 100)*6.09
fee_finance_5 = (product_retail_price / 100)*7.64
fee_finance_6 = (product_retail_price / 100)*8.92
fee_finance_7 = (product_retail_price / 100)*10.06
fee_finance_8 = (product_retail_price / 100)*10.62
fee_finance_9 = (product_retail_price / 100)*11.23
fee_finance_10 = (product_retail_price / 100)*12.41
fee_finance_11 = (product_retail_price / 100)*13.60
fee_finance_12 = (product_retail_price / 100)*14.80
fee_finance_15 = (product_retail_price / 100)*18.47
fee_finance_18 = (product_retail_price / 100)*22.23
fee_finance_24 = (product_retail_price / 100)*23.83

#Calculations
parcelas = int(input("Número de parcelas sem juros (Formato: 0-24): "))
base_profit = round(product_retail_price - product_cost - fee_shopify - fee_mercadopago - cpa, 2)
profit_2 = round(base_profit - fee_finance_2 - cpa, 2)
profit_3 = round(base_profit - fee_finance_3 - cpa, 2)
profit_4 = round(base_profit - fee_finance_4 - cpa, 2)
profit_5 = round(base_profit - fee_finance_5 - cpa, 2)
profit_6 = round(base_profit - fee_finance_6 - cpa, 2)
profit_7 = round(base_profit - fee_finance_7 - cpa, 2)
profit_8 = round(base_profit - fee_finance_8 - cpa, 2)
profit_9 = round(base_profit - fee_finance_9 - cpa, 2)
profit_10 = round(base_profit - fee_finance_10 - cpa, 2)
profit_11 = round(base_profit - fee_finance_11 - cpa, 2)
profit_12 = round(base_profit - fee_finance_12 - cpa, 2)
profit_15 = round(base_profit - fee_finance_15 - cpa, 2)
profit_18 = round(base_profit - fee_finance_18 - cpa, 2)
profit_24 = round(base_profit - fee_finance_24 - cpa, 2)

#Print Values
print("\n")

if parcelas in [0,1]:
    print(f"Lucro à vista: R${base_profit}")
elif parcelas == 2:
    print(f"Lucro à vista: R${base_profit}")
    print(f"Lucro parcelado 2x: R${profit_2}")
elif parcelas == 3:
    print(f"Lucro à vista: R${base_profit}")
    print(f"Lucro parcelado 2x: R${profit_2}")
    print(f"Lucro parcelado 3x: R${profit_3}")
elif parcelas == 4:
    print(f"Lucro à vista: R${base_profit}")
    print(f"Lucro parcelado 2x: R${profit_2}")
    print(f"Lucro parcelado 3x: R${profit_3}")
    print(f"Lucro parcelado 4x: R${profit_4}")
elif parcelas == 5:
    print(f"Lucro à vista: R${base_profit}")
    print(f"Lucro parcelado 2x: R${profit_2}")
    print(f"Lucro parcelado 3x: R${profit_3}")
    print(f"Lucro parcelado 4x: R${profit_4}")
    print(f"Lucro parcelado 5x: R${profit_5}")
elif parcelas == 6:
    print(f"Lucro à vista: R${base_profit}")
    print(f"Lucro parcelado 2x: R${profit_2}")
    print(f"Lucro parcelado 3x: R${profit_3}")
    print(f"Lucro parcelado 4x: R${profit_4}")
    print(f"Lucro parcelado 5x: R${profit_5}")
    print(f"Lucro parcelado 6x: R${profit_6}")
elif parcelas == 7:
    print(f"Lucro à vista: R${base_profit}")
    print(f"Lucro parcelado 2x: R${profit_2}")
    print(f"Lucro parcelado 3x: R${profit_3}")
    print(f"Lucro parcelado 4x: R${profit_4}")
    print(f"Lucro parcelado 5x: R${profit_5}")
    print(f"Lucro parcelado 6x: R${profit_6}")
    print(f"Lucro parcelado 7x: R${profit_7}")
elif parcelas == 8:
    print(f"Lucro à vista: R${base_profit}")
    print(f"Lucro parcelado 2x: R${profit_2}")
    print(f"Lucro parcelado 3x: R${profit_3}")
    print(f"Lucro parcelado 4x: R${profit_4}")
    print(f"Lucro parcelado 5x: R${profit_5}")
    print(f"Lucro parcelado 6x: R${profit_6}")
    print(f"Lucro parcelado 7x: R${profit_7}")
    print(f"Lucro parcelado 8x: R${profit_8}")
elif parcelas == 9:
    print(f"Lucro à vista: R${base_profit}")
    print(f"Lucro parcelado 2x: R${profit_2}")
    print(f"Lucro parcelado 3x: R${profit_3}")
    print(f"Lucro parcelado 4x: R${profit_4}")
    print(f"Lucro parcelado 5x: R${profit_5}")
    print(f"Lucro parcelado 6x: R${profit_6}")
    print(f"Lucro parcelado 7x: R${profit_7}")
    print(f"Lucro parcelado 8x: R${profit_8}")
    print(f"Lucro parcelado 9x: R${profit_9}")
elif parcelas == 10:
    print(f"Lucro à vista: R${base_profit}")
    print(f"Lucro parcelado 2x: R${profit_2}")
    print(f"Lucro parcelado 3x: R${profit_3}")
    print(f"Lucro parcelado 4x: R${profit_4}")
    print(f"Lucro parcelado 5x: R${profit_5}")
    print(f"Lucro parcelado 6x: R${profit_6}")
    print(f"Lucro parcelado 7x: R${profit_7}")
    print(f"Lucro parcelado 8x: R${profit_8}")
    print(f"Lucro parcelado 9x: R${profit_9}")
    print(f"Lucro parcelado 10x: R${profit_10}")
elif parcelas == 11:
    print(f"Lucro à vista: R${base_profit}")
    print(f"Lucro parcelado 2x: R${profit_2}")
    print(f"Lucro parcelado 3x: R${profit_3}")
    print(f"Lucro parcelado 4x: R${profit_4}")
    print(f"Lucro parcelado 5x: R${profit_5}")
    print(f"Lucro parcelado 6x: R${profit_6}")
    print(f"Lucro parcelado 7x: R${profit_7}")
    print(f"Lucro parcelado 8x: R${profit_8}")
    print(f"Lucro parcelado 9x: R${profit_9}")
    print(f"Lucro parcelado 10x: R${profit_10}")
    print(f"Lucro parcelado 11x: R${profit_11}")
elif parcelas in [12,13,14]:
    print(f"Lucro à vista: R${base_profit}")
    print(f"Lucro parcelado 2x: R${profit_2}")
    print(f"Lucro parcelado 3x: R${profit_3}")
    print(f"Lucro parcelado 4x: R${profit_4}")
    print(f"Lucro parcelado 5x: R${profit_5}")
    print(f"Lucro parcelado 6x: R${profit_6}")
    print(f"Lucro parcelado 7x: R${profit_7}")
    print(f"Lucro parcelado 8x: R${profit_8}")
    print(f"Lucro parcelado 9x: R${profit_9}")
    print(f"Lucro parcelado 10x: R${profit_10}")
    print(f"Lucro parcelado 11x: R${profit_11}")
    print(f"Lucro parcelado 12x: R${profit_12}")
elif parcelas in [15,16,17]:
    print(f"Lucro à vista: R${base_profit}")
    print(f"Lucro parcelado 2x: R${profit_2}")
    print(f"Lucro parcelado 3x: R${profit_3}")
    print(f"Lucro parcelado 4x: R${profit_4}")
    print(f"Lucro parcelado 5x: R${profit_5}")
    print(f"Lucro parcelado 6x: R${profit_6}")
    print(f"Lucro parcelado 7x: R${profit_7}")
    print(f"Lucro parcelado 8x: R${profit_8}")
    print(f"Lucro parcelado 9x: R${profit_9}")
    print(f"Lucro parcelado 10x: R${profit_10}")
    print(f"Lucro parcelado 11x: R${profit_11}")
    print(f"Lucro parcelado 12x: R${profit_12}")
    print(f"Lucro parcelado 15x: R${profit_15}")
elif parcelas in [18,19,20,21,22,23]:
    print(f"Lucro à vista: R${base_profit}")
    print(f"Lucro parcelado 2x: R${profit_2}")
    print(f"Lucro parcelado 3x: R${profit_3}")
    print(f"Lucro parcelado 4x: R${profit_4}")
    print(f"Lucro parcelado 5x: R${profit_5}")
    print(f"Lucro parcelado 6x: R${profit_6}")
    print(f"Lucro parcelado 7x: R${profit_7}")
    print(f"Lucro parcelado 8x: R${profit_8}")
    print(f"Lucro parcelado 9x: R${profit_9}")
    print(f"Lucro parcelado 10x: R${profit_10}")
    print(f"Lucro parcelado 11x: R${profit_11}")
    print(f"Lucro parcelado 12x: R${profit_12}")
    print(f"Lucro parcelado 15x: R${profit_15}")
    print(f"Lucro parcelado 18x: R${profit_18}")
else: 
    print(f"Lucro à vista: R${base_profit}")
    print(f"Lucro parcelado 2x: R${profit_2}")
    print(f"Lucro parcelado 3x: R${profit_3}")
    print(f"Lucro parcelado 4x: R${profit_4}")
    print(f"Lucro parcelado 5x: R${profit_5}")
    print(f"Lucro parcelado 6x: R${profit_6}")
    print(f"Lucro parcelado 7x: R${profit_7}")
    print(f"Lucro parcelado 8x: R${profit_8}")
    print(f"Lucro parcelado 9x: R${profit_9}")
    print(f"Lucro parcelado 10x: R${profit_10}")
    print(f"Lucro parcelado 11x: R${profit_11}")
    print(f"Lucro parcelado 12x: R${profit_12}")
    print(f"Lucro parcelado 15x: R${profit_15}")
    print(f"Lucro parcelado 18x: R${profit_18}")
    print(f"Lucro parcelado 24x: R${profit_24}")
print("\n")
print("AVISO: Lucro calculado usando as taxas atuais do MercadoPago (23/07/2018)")
\$\endgroup\$
  • 3
    \$\begingroup\$ Aaaaaaaaaaa! Have you missed the chapter about loops? :-o \$\endgroup\$ – t3chb0t Jul 24 '18 at 15:13
  • \$\begingroup\$ I didn't no. I used a while loop in my little number game but I'm not sure how I would effectively use a loop in this program. Can you enlighten me please? :D \$\endgroup\$ – Jakub Jul 24 '18 at 21:10
  • 2
    \$\begingroup\$ @t3chb0t I'm afraid he missed also the chapter about dictionaries. \$\endgroup\$ – N74 Jul 24 '18 at 22:05
  • \$\begingroup\$ I did make a dictionary for this but not sure how I would use it in this case. \$\endgroup\$ – Jakub Jul 24 '18 at 22:32
  • \$\begingroup\$ fee_dictionary = {2:2.03,3:4.06,4:6.09,5:7.64,6:8.92,7:10.06,8:10.62,9:11.23,10:12.41,11:13.60,12:14.80,15:18.47,18:22.23,24:23.83} \$\endgroup\$ – Jakub Jul 24 '18 at 22:32
2
\$\begingroup\$

I'd use a code like this:

#Message table 
MESSAGES = {"StoreValueRequest": "Valor do produto na loja em Reais (Formato 00.00): ", 
            "SupplyValueRequest": "Valor do produto no fornecedor em Reais (Formato 00.00): ", 
            "AcquisitionCostRequest": "Custo por aquisição (Formato 00.00): ", 
            "ProfitInCash": "Lucro à vista: {0}", 
            "NumInstallments": "Número de parcelas sem juros (Formato: 0-24): ", 
            "ProfitNInstallments": {2: "Lucro parcelado 2x: {0}", 
                                    3: "Lucro parcelado 3x: {0}", 
                                    4: "Lucro parcelado 4x: {0}", 
                                    5: "Lucro parcelado 5x: {0}", 
                                    6: "Lucro parcelado 6x: {0}", 
                                    7: "Lucro parcelado 7x: {0}", 
                                    8: "Lucro parcelado 8x: {0}", 
                                    9: "Lucro parcelado 9x: {0}", 
                                    10: "Lucro parcelado 10x: {0}", 
                                    11: "Lucro parcelado 11x: {0}", 
                                    12: "Lucro parcelado 12x: {0}", 
                                    15: "Lucro parcelado 15x: {0}", 
                                    18: "Lucro parcelado 18x: {0}", 
                                    24: "Lucro parcelado 24x: {0}"}, 
            "SectionSeparation": "\n", 
            "Disclaimer": "AVISO: Lucro calculado usando as taxas atuais do MercadoPago (23/07/2018)" } 


#Table for the evaluation of fees. The keys are the number of installments 
FEES_BY_INSTALLMENTS = {2: 2.03, 3: 4.06, 4: 6.09, 5: 7.64, 6: 8.92, 7: 10.06, 
                        8: 10.62, 9: 11.23, 10: 12.41, 11: 13.60, 12: 14.80, 
                        15: 18.47, 18: 22.23, 24: 23.83 } 

#Percent points for the fees 
FEE_SHOPIFY = 2 
FEE_MERCADOPAGO = 4.99 

#Number of digits for the rounding of prices 
PRICE_ROUNDING_DIGITS = 2 


def get_user_input():                        
    """Handles the input of parameters from the user interface 

    Args: 

    Returns: 
        product_retail_price: (float) The retail price of the item 
        product_cost: (float) The cost of the item from the supplier 
        cost_per_acquisition: (float) The costs to get the item from the supplier 
        installments (int) Required number of installments 

    Raises: 
        ValueError: The user input values that cannot be converted to numerics 
    """ 

    #Values    
    product_retail_price = float(input(MESSAGES["StoreValueRequest"])) 
    #Costs 
    product_cost = float(input(MESSAGES["SupplyValueRequest"])) 
    cost_per_acquisition = float(input(MESSAGES["AcquisitionCostRequest"])) 
    #Other parameters    
    installments = int(input(MESSAGES["NumInstallments"])) 

    return product_retail_price, product_cost, cost_per_acquisition, installments 


def evaluate_profits(product_retail_price, product_cost, cost_per_acquisition, installments): 
    """Handles the evaluation of fees and profits 

    Args: 
        product_retail_price: (float) The retail price of the item 
        product_cost: (float) The cost of the item from the supplier 
        cost_per_acquisition: (float) The costs to get the item from the supplier 
        installments (int) Required number of installments 

    Returns: 
        base_profit: (float) The profit without installments 
        evaluated_profits: (dict) Value of the profit with the given installments 

    Raises: 

    """ 

    fee_shopify = (product_retail_price / 100) * FEE_SHOPIFY 
    fee_mercadopago = (product_retail_price / 100) * FEE_MERCADOPAGO 

    #Evaluates a dictionary of fees for the product. The number of installments 
    #are the keys 
    installment_fees = {k: (product_retail_price / 100) * fee 
                      for k, fee in FEES_BY_INSTALLMENTS.items()} 

    #Calculations 
    base_profit = round(product_retail_price - product_cost - 
                        fee_shopify - fee_mercadopago - 
                        cost_per_acquisition, PRICE_ROUNDING_DIGITS) 

    evaluated_profits = {k: round(base_profit - fee - cost_per_acquisition, 
                         PRICE_ROUNDING_DIGITS) 
                         for k, fee in installment_fees.items()} 

    return base_profit, evaluated_profits 


def output_results(base_profit, evaluated_profits, installments): 
    """Outputs the evaluation results to the user 

    Args: 
        base_profit: (float) The profit without installments 
        evaluated_profits: (dict) Value of the profit with the given installments 
        installments (int) Required number of installments 

    Returns: 

    Raises: 

    """ 

    print(MESSAGES["SectionSeparation"]) 

    print(MESSAGES["ProfitInCash"].format(base_profit))

    #Iterates on the expected messages and only print the appropriate ones 
    #according to the number of installments input by the user 
    for installments_key, format_string in MESSAGES["ProfitNInstallments"].items(): 
        if installments >= installments_key: 
            print(format_string.format(evaluated_profits[installments_key])) 
        else: 
            break 

    print(MESSAGES["SectionSeparation"]) 

    print(MESSAGES["Disclaimer"]) 


if __name__ == '__main__': 
    ( product_retail_price, product_cost, 
      cost_per_acquisition, installments ) = get_user_input() 

    ( base_profit, evaluated_profits ) = evaluate_profits( 
        product_retail_price, product_cost, 
        cost_per_acquisition, installments) 

    output_results(base_profit, evaluated_profits, installments)

I did put all the messages in one structure (well dictionary of dictionaries) at the beginning so that you can localize your messages and use only English in code.

The table of fees is defined in a similar fashion, so that it can be changed if needed without reading all the code.

The evaluation of fees and profits is done with a single function iterated over the range of fees.

The messages to be printed are handled according to the value passed as number of installments.

I separated the logic from the user interface. Placed an import guard so that you can reuse both, would you need it.

All the functions have docstrings so that everyone can read and understand what they are supposed to do.

Now you can add some optimization, and test cases.

\$\endgroup\$
  • \$\begingroup\$ Works perfectly! I'll add just a small while loop in there to not allow people to input the wrong number of installments. I did eventually make the original code into something like this: paste.ofcode.org/ykjkWtrXivZjSHYnj5gUYa but there was an issue if the incorrect number of installments was inserted, where it wouldn't recognize the key and it only displayed up to 12x, even if the installments input was 24. I was trying to make it super short but I guess that's not always the best way! :) \$\endgroup\$ – Jakub Jul 25 '18 at 17:13

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.