# Profit Margin Calculator in Python (with installments)

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_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")

• Aaaaaaaaaaa! Have you missed the chapter about loops? :-o Commented Jul 24, 2018 at 15:13
• 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 Commented Jul 24, 2018 at 21:10
• @t3chb0t I'm afraid he missed also the chapter about dictionaries.
– N74
Commented Jul 24, 2018 at 22:05
• I did make a dictionary for this but not sure how I would use it in this case. Commented Jul 24, 2018 at 22:32
• 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} Commented Jul 24, 2018 at 22:32

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}",
"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

#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

#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 -
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.

• 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! :) Commented Jul 25, 2018 at 17:13