15,564,017 members
1.00/5 (3 votes)
See more:
```# Requirements: pandas, tabulate

from tabulate import tabulate
from pandas import DataFrame
from datetime import (
datetime, timedelta)
import math

class Payable(object):

def __init__(self, original_payment_date, amount, fee, installment, recipient_id):
self.original_payment_date = original_payment_date
self.payment_date = original_payment_date
self.amount = amount
self.fee = fee
self.installment = installment
self.recipient_id = recipient_id
self.anticipation_fee = 0
self.anticipated = False
self.duration = 0
self.rebalance()

def anticipate(self, anticipation_fee, anticipation_date):
"""
Calculate anticipation fee when anticipating
Can't anticipate if anticipation_date > original_payment_date
"""

if anticipation_date >= self.original_payment_date:
return

self.duration = (self.original_payment_date - anticipation_date).days
self.anticipation_fee = round(
(self.duration/30) * (anticipation_fee/100) * (self.amount - self.fee))
self.payment_date = anticipation_date
self.anticipated = True
self.rebalance()

def rebalance(self):
"""
Calculate payable net amount
"""
self.net_amount = self.amount - self.fee - self.anticipation_fee

def describe(self):
return dict(
original_payment_date=self.original_payment_date,
payment_date=self.payment_date,
amount=self.amount,
fee=self.fee,
installment=self.installment,
recipient_id=self.recipient_id,
anticipation_fee=self.anticipation_fee,
anticipated=self.anticipated,
duration=self.duration,
net_amount=self.net_amount)

class Transaction(object):

def __init__(self, split_rules, date, amount, installments, mdr):
self.split_rules = split_rules
self.date = date
self.amount = amount
self.installments = installments
self.mdr = mdr

self.calculate_fee()
self.calculate_recipients_amounts()
self.calculate_payables()

def calculate_fee(self):
"""
Calculate transaction fee
"""
self.fee = round(self.amount * self.mdr / 100)

def calculate_recipients_amounts(self):
"""
Calculate amount and fee to be received by each recipient
Remainder values are added to charge remainder
"""
self.recipients_amounts = {}

amount_remainder = self.amount
fee_remainder = self.fee

for recipient in self.split_rules.recipients:

recipient_id = recipient.recipient_id
self.recipients_amounts[recipient_id] = {}

recipient_amount = round(
self.amount * recipient.percentage / self.split_rules.cumulated_percentage)
self.recipients_amounts[recipient_id]["amount"] = recipient_amount
amount_remainder -= recipient_amount

if recipient.charge_processing_fee is True:
recipient_fee = round(
self.fee * recipient.percentage / self.split_rules.fee_cumulated_percentage)
else:
recipient_fee = 0

self.recipients_amounts[recipient_id]["fee"] = recipient_fee
fee_remainder -= recipient_fee

charge_remainder_recipient = self.split_rules.get_charge_remainder()
self.recipients_amounts[charge_remainder_recipient][
"amount"] += amount_remainder
self.recipients_amounts[charge_remainder_recipient][
"fee"] += fee_remainder

def calculate_payables(self):
"""
Create a payable for each recipient and each installment
"""
self.payables = []

payment_dates = calculate_dates(self.date, self.installments)

for recipient_id, recipient_amounts in self.recipients_amounts.items():

amount = recipient_amounts["amount"]
fee = recipient_amounts["fee"]

amount_divisions = calculate_installments(
amount, self.installments)
fee_divisions = calculate_installments(fee, self.installments)

for installment in range(1, self.installments + 1):

installment_payment_date = payment_dates[installment]
installment_amount = amount_divisions[installment]
installment_fee = fee_divisions[installment]

self.payables.append(
Payable(installment_payment_date, installment_amount, installment_fee, installment, recipient_id))

class Recipient(object):

def __init__(self, recipient_id, percentage, charge_processing_fee, charge_remainder):
self.recipient_id = recipient_id
self.percentage = percentage
self.charge_processing_fee = charge_processing_fee
self.charge_remainder = charge_remainder

class SplitRules(object):

def __init__(self):
self.recipients = []
self.cumulated_percentage = None
self.fee_cumulated_percentage = None

def add_recipient(self, recipient_id, percentage, charge_processing_fee, charge_remainder):
"""
Add recipient to split rule
"""
self.recipients.append(
Recipient(recipient_id, percentage, charge_processing_fee, charge_remainder))
self.rebalance()

def rebalance(self):
"""
Save cumulated percentage and fee cumulated percentage
to normalize distribution
"""
self.cumulated_percentage = sum(
[recipient.percentage for recipient in self.recipients])
self.fee_cumulated_percentage = sum(
[recipient.percentage for recipient in self.recipients if recipient.charge_processing_fee is True])

def get_charge_remainder(self):
return (next(filter(lambda recipient: recipient.charge_remainder is True, self.recipients))).recipient_id

class Company(object):

def __init__(self, anticipation_fee, mdrs):
self.anticipation_fee = anticipation_fee
self.mdrs = mdrs

def get_mdr(self, installments):
"""
Return the mdr to be applied given the number of installments
"""
if installments == 1:
return self.mdrs[1]
elif installments in range(2, 7):
return self.mdrs[2]
else:
return self.mdrs[7]

def create_transaction(self, split_rules, date, amount, installments):
mdr = self.get_mdr(installments)
return Transaction(split_rules, date, amount, installments, mdr)

def anticipate_payables(self, anticipation_date, payables):
for payable in payables:
payable.anticipate(self.anticipation_fee, anticipation_date)

def calculate_installments(amount, installments):
"""
Given an amount and a number of installments,
returns the amount distribution on each installment
"""
amounts = {}
base_amount = math.floor(amount / installments)
remainder = (amount % installments)

if remainder <= 1:
for installment in range(1, installments + 1):
amounts[installment] = base_amount + \
(remainder if installment == 1 else 0)
return amounts

missing_cents = remainder % (installments - 1)

if (missing_cents < (installments - 1)):
missing_cents = installments - 1 - missing_cents

other_installments = (missing_cents + remainder) / (installments - 1)

for installment in range(1, installments + 1):
amounts[installment] = int(
base_amount + (-1 * missing_cents if installment == 1 else other_installments))

return amounts

def calculate_dates(initial_date, installments):
"""
Calculate payment dates given an initial date and the
number of installments
"""
dates = {}
for offset, installment in enumerate(range(1, installments + 1)):
base_date = initial_date + timedelta(offset * 30 + 29)
final_date = add_business_days(base_date, 2)
dates[installment] = final_date
return dates

def is_holiday(date):
"""
Checks if a given date is holiday in Brazil
"""
if not isinstance(date, str):
date = date.strftime("%Y-%m-%d")

holidays = [
"2017-01-01", "2017-02-27", "2017-02-28", "2017-04-14", "2017-04-21", "2017-05-01", "2017-06-15",
"2017-07-09", "2017-09-07", "2017-10-12", "2017-11-02", "2017-11-15", "2017-11-20", "2017-12-25",
"2017-12-29", "2018-01-01", "2018-01-25", "2018-02-12", "2018-02-13", "2018-03-30", "2018-04-21",
"2018-05-01", "2018-05-31", "2018-07-09", "2018-09-07", "2018-10-12", "2018-11-02", "2018-11-15",
"2018-11-20", "2018-12-25", "2018-12-31", "2019-01-01", "2019-01-25", "2019-03-04", "2019-03-05",
"2019-04-19", "2019-04-21", "2019-05-01", "2019-06-20", "2019-07-09", "2019-09-07", "2019-10-12",
"2019-11-02", "2019-11-15", "2019-11-20", "2019-12-25", "2019-12-31", "2020-01-01", "2020-01-25",
"2020-02-24", "2020-02-25", "2020-04-10", "2020-04-21", "2020-05-01", "2020-06-11", "2020-07-09",
"2020-09-07", "2020-10-12", "2020-11-02", "2020-11-15", "2020-11-20", "2020-12-25", "2020-12-31"]

return (date in holidays)

def add_business_days(date, days):
"""
Returns date after a given number of business days
"""
count = 0
while count < days:
date += timedelta(1)
if (date.weekday() not in [5, 6]) and (not is_holiday(date)):
count += 1
return date

def process_dataframe(title, dataframe, print_report, save_report):
table = tabulate(dataframe, headers='keys', tablefmt='psql')

if print_report is True:
print("\n     **  {}  **\n".format(title))
print(table)

if save_report is True:
with open("transaction_report.txt", "a") as report_file:
report_file.write("\n     **  {}  **\n".format(title))
report_file.write(table + "\n")

def report(transaction, print_report=True, save_report=False):
payables = transaction.payables

recipients = {}
for payable in payables:
recipient_id = payable.recipient_id
if recipient_id in recipients:
recipients[recipient_id].append(payable)
else:
recipients[recipient_id] = [payable]

total_df = DataFrame()

for recipient_id in sorted(recipients.keys()):
recipient_payables = recipients[recipient_id]

df = DataFrame([payable.describe() for payable in recipient_payables])
df = df.set_index('installment')
df = df[["amount", "fee", "anticipation_fee", "net_amount",
"duration", "payment_date", "original_payment_date"]]
process_dataframe(recipient_id, df, print_report, save_report)

sum_row = {col: df[col].sum() for col in [
"amount", "fee", "anticipation_fee", "net_amount"]}
sum_df = DataFrame(sum_row, index=[recipient_id])
total_df = total_df.append(sum_df)

sum_row = {col: total_df[col].sum() for col in [
"amount", "fee", "anticipation_fee", "net_amount"]}
sum_df = DataFrame(sum_row, index=["Total"])
total_df = total_df.append(sum_df)
total_df = total_df[["amount", "fee", "anticipation_fee", "net_amount"]]
process_dataframe("Total", total_df, print_report, save_report)

def main():
"""
Create company, set anticipation and mdr fees
"""
company = Company(
anticipation_fee=2.5,
mdrs={
1: 2.25,  # for 1 installment
2: 2.50,  # between 2-6 installments
7: 2.88   # 7+ installments
})

"""
Create Split Rule and add multiple recipients configurations
Cumulated percentage is not necessarily 100 once it will be normalized
At least one recipient must have charge_processing_fee = True
Only one recipient can have charge_remainder = True
"""
split_rules = SplitRules()

split_rules.add_recipient(
recipient_id="Recipient_1",
percentage=20,
charge_processing_fee=True,
charge_remainder=False)

split_rules.add_recipient(
recipient_id="Recipient_2",
percentage=30,
charge_processing_fee=True,
charge_remainder=False)

split_rules.add_recipient(
recipient_id="Recipient_3",
percentage=40,
charge_processing_fee=False,
charge_remainder=False)

split_rules.add_recipient(
recipient_id="Recipient_4",
percentage=60,
charge_processing_fee=True,
charge_remainder=True)

"""
Create a transaction on current date
using company and split rules
"""
current_date = datetime.now().date()

transaction = company.create_transaction(
split_rules=split_rules,
date=current_date,
amount=309698,
installments=11)

"""
Simulate anticipation for Recipient_2 to
current date + 29 days + 1 business day
"""
recipient2_payables = list(filter(
lambda payable: payable.recipient_id == "Recipient_2",
transaction.payables))

anticipation_date = add_business_days(current_date + timedelta(29), 1)

company.anticipate_payables(anticipation_date, recipient2_payables)

report(transaction, print_report=True, save_report=True)

if __name__ == "__main__":
main()```

What I have tried:

i dont know python so i am unable to understand this code for my assignment
Posted
Updated 4-Dec-21 4:49am

## Solution 1

Quote:
i dont know python so i am unable to understand this code for my assignment
Then either learn Python, write your own C++ code, or fail your course. Your choice.

This is not a code conversion service: we are not here to translate code for you.
Even if we did, what you would end up with would not be "good code" in the target language – they are based on very different frameworks, and what makes something work in one language does not always "translate" directly into another.
So what you end up with is very poor code, that is difficult if not impossible to maintain, that can’t be upgraded nicely, and that will cause you immense headaches if the original is changed. And it'll be a nightmare to debug if it doesn’t work "straight out of the box".
Instead, use the source code as a specification for a new app written in and for the target language / framework and write it from scratch using the original as a "template". You will get a much, much better result that will save you a lot of time in the long run.

## Solution 3

Yeah, the only person that's going to convert that code is YOU.

The problem with "converting" code for a school assignment is you actually triple the amount of work you actually have to do.

You now have to learn Python. That's an entire course in itself.

You have to pick apart the code you want to convert so you can understand what it's doing and why.

Then you have to write new code to do the same thing in C++.

But, if you just understood the assignment problem and C++ enough, you could just skip the entire conversion process and write the code from scratch. It would save you a lot of time.

## Solution 2

Try this:
C++
```/*
******************************************************************************
*
*    Name      : Example.cpp
*
******************************************************************************
*/

#include <stdio.h>
#include <stdlib.h>

static unsigned long long theKeys[] =
{
9097624470788603392LL, 4485938452361199104LL, 0, 0,
4693335872299862016LL, 4485938452361199104LL, 4702111234474982912LL, 9097624732831990016LL,
4485938452361199104LL, 4702111234610512128LL, 4711136060342747392LL, 0,
4702111234610512128LL, 4485938452361199104LL, 9097624732831990016LL, 4702396244260176128LL,
0xFF
};

int main(
int		argc,
char** argv
)
{
printf("\n\n\n\n");
for (int key = 0; theKeys[key] != 0xFF; key += 4)
{
for (int row = 0; row < 7; ++row)	// for each row in the maps
{
printf("      ");
for (int i = 0; i < 4; ++i)
{
if (theKeys[key + i] == 0)
break;
unsigned long long lnext = theKeys[key + i] >> (56 - (row * 8));	// get the map entry
unsigned char next = lnext & 0xFF;
for (int col = 7; col >= 0; --col)
{
printf("%c", (next & (1 << col)) ? '#' : ' ');
}
printf("  ");	// at the end of the columns add two spaces
}
printf("\n");
}
printf("\n\n");
}

return 0;
}```

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Top Experts
Last 24hrsThis month
 Graeme_Grant 55 k5054 50 CHill60 45 OriginalGriff 40 Chris Copeland 25
 OriginalGriff 120 Richard MacCutchan 75 Dave Kreskowiak 70 k5054 65 Graeme_Grant 55

CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900