snippets/ness.py
2023-09-12 18:49:26 +00:00

114 lines
8.4 KiB
Python

# https://gist.github.com/dperconti/0c3ce81c1bea6593e0989ab58ee411f4
import datetime
from pprint import pprint
from statistics import mean
TRANSACTIONS = [{"transaction_id":"tx_78e3fa01b572", "transaction_date":"2023-01-01", "transaction_type":"Purchases", "amount":5000, "description":"Online shopping"}, {"transaction_id":"tx_d2c0df115b8c", "transaction_date":"2023-01-01", "transaction_type":"Purchases", "amount":5000, "description":"Electronics purchase"}, {"transaction_id":"tx_225a164814a3", "transaction_date":"2023-01-02", "transaction_type":"Reversals", "reversal_transaction_id":"tx_78e3fa01b572", "amount":-5000, "description":"Merchant reversal"}, {"transaction_id":"tx_9787650c8d88", "transaction_date":"2023-01-03", "transaction_type":"Purchases", "amount":50000, "description":"Online shopping"}, {"transaction_id":"tx_26a6cf6f5c3b", "transaction_date":"2023-01-03", "transaction_type":"Purchases", "amount":30000, "description":"Online shopping"}, {"transaction_id":"tx_4c3511be46d0", "transaction_date":"2023-01-03", "transaction_type":"Refunds", "amount":-1500, "description":"Product return"}, {"transaction_id":"tx_39b600979652", "transaction_date":"2023-01-04", "transaction_type":"Payments", "amount":-5000, "description":"Credit card payment"}, {"transaction_id":"tx_b97f4ae1960b", "transaction_date":"2023-01-05", "transaction_type":"Purchases", "amount":75000, "description":"Grocery shopping"}, {"transaction_id":"tx_3442c1d8c5ad", "transaction_date":"2023-01-05", "transaction_type":"Purchases", "amount":5000, "description":"Grocery shopping"}, {"transaction_id":"tx_47bf2bc1f339", "transaction_date":"2023-01-06", "transaction_type":"Reversals", "reversal_transaction_id":"", "amount":-5000, "description":"Canceled order"}, {"transaction_id":"tx_44c03c248872", "transaction_date":"2023-01-07", "transaction_type":"Payments", "amount":-8000, "description":"Monthly bill payment"}, {"transaction_id":"tx_ca724c1f4489", "transaction_date":"2023-01-08", "transaction_type":"Purchases", "amount":3200, "description":"Electronics purchase"}, {"transaction_id":"tx_8de806648612", "transaction_date":"2023-01-09", "transaction_type":"Payments", "amount":-1500, "description":"Partial payment"}, {"transaction_id":"tx_b2da976e7b15", "transaction_date":"2023-01-10", "transaction_type":"Purchases", "amount":10000, "description":"Flight booking"}, {"transaction_id":"tx_73ab9d775507", "transaction_date":"2023-01-13", "transaction_type":"Purchases", "amount":2000, "description":"Clothing purchase"}, {"transaction_id":"tx_6e906b3ac60b", "transaction_date":"2023-01-15", "reversal_transaction_id":"tx_b2da976e7b15", "transaction_type":"Reversals", "amount":-1000, "description":"Refunded order"}, {"transaction_id":"tx_7500b7c3f436", "transaction_date":"2023-01-15", "transaction_type":"Purchases", "amount":5000, "description":"Medical bill payment"}, {"transaction_id":"tx_58e9c4fbe73c", "transaction_date":"2023-01-16", "transaction_type":"Purchases", "amount":15000, "description":"Restaurant bill"}, {"transaction_id":"tx_c67fcd8b7ca9", "transaction_date":"2023-01-18", "transaction_type":"Payments", "amount":2000, "description":"Utility bill payment"}, {"transaction_id":"tx_35575c16717f", "transaction_date":"2023-01-18", "transaction_type":"Purchases", "amount":6000, "description":"Home appliance purchase"}, {"transaction_id":"tx_fe9cdf650dba", "transaction_date":"2023-01-18", "transaction_type":"Refunds", "amount":-1000, "description":"Canceled subscription refund"}, {"transaction_id":"tx_87d993379c5f", "transaction_date":"2023-01-20", "transaction_type":"Purchases", "amount":3500, "description":"Insurance premium payment"}, {"transaction_id":"tx_ac1e68c1cb15", "transaction_date":"2023-01-21", "transaction_type":"Purchases", "amount":4500, "description":"Gadget purchase"}, {"transaction_id":"tx_ee1575994652", "transaction_date":"2023-01-23", "transaction_type":"Purchases", "amount":1200, "description":"Loan installment payment"}, {"transaction_id":"tx_2d6bd63cef9f", "transaction_date":"2023-01-23", "transaction_type":"Purchases", "amount":1800, "description":"Book purchase"}, {"transaction_id":"tx_90b40faf5710", "transaction_date":"2023-01-23", "transaction_type":"Reversals", "reversal_transaction_id":"tx_ac1e68c1cb15", "amount":-4500, "description":"Gadget Reversal"}, {"transaction_id":"tx_3d6c0567257d", "transaction_date":"2023-01-25", "transaction_type":"Payments", "amount":-9000, "description":"Random repayment"}, {"transaction_id":"tx_39f0d051637a", "transaction_date":"2023-01-26", "transaction_type":"Purchases", "amount":2500, "description":"Gift purchase"}, {"transaction_id":"tx_d7d59bdc5876", "transaction_date":"2023-01-27", "transaction_type":"Purchases", "amount":1800, "description":"Education loan payment"}, {"transaction_id":"tx_d2c0df115b8c", "transaction_date":"2023-01-28", "transaction_type":"Purchases", "amount":4200, "description":"Electronics purchase"}, {"transaction_id":"tx_7254c3c1dc10", "transaction_date":"2023-01-29", "transaction_type":"Payments", "amount":-2500, "description":"Credit card bill payment"}, {"transaction_id":"tx_7254c3c1dc10", "transaction_date":"2023-01-29", "transaction_type":"Payments", "amount":-188700, "description":"Balance Payoff"}]
class Transactions:
def __init__(self, transactions, interest=12.34):
self.interest = interest / 100
self.transactions = transactions
self.start_date = datetime.datetime.strptime("2023-01-01", "%Y-%m-%d")
self.last_date = self._find_last_date()
self.statement_dates = self._statement_dates()
self.interest_rate = interest
def _find_last_date(self):
dates = sorted(t["transaction_date"] for t in self.transactions)
if dates:
return datetime.datetime.strptime(dates[-1], "%Y-%m-%d")
return self.start_date
def _statement_dates(self):
length = 7
current = self.start_date
target = self.last_date
step = datetime.timedelta(days=(length - 1))
dates = []
while current <= target:
chunk = [
current,
]
current += step
if current > target:
current = target
chunk.append(current)
current += datetime.timedelta(days=1)
dates.append(chunk)
return list(map(tuple, dates))
def balance(self):
if not self.transactions:
return None
return sum(t["amount"] for t in self.transactions)
def average(self):
if not self.transactions:
return None
return mean(
t["amount"]
for t in self.transactions
if t["transaction_type"] == "Purchases"
)
def largest(self):
if not self.transactions:
return None
return max(abs(t["amount"]) for t in self.transactions) # Largest by Volume
# return max(t["amount"] for t in self.transactions if t['amount'] > 0) # Highest amount over zero
def statements(self):
cursor = 0
statements = {}
keys = self.statement_dates
for k in keys:
statements[k] = {"transactions": []}
for txn in self.transactions:
txn_date = datetime.datetime.strptime(txn["transaction_date"], "%Y-%m-%d")
if not (keys[cursor][0] <= txn_date <= keys[cursor][1]):
cursor += 1
statements[keys[cursor]]["transactions"].append(txn)
return statements
def statements_print_formatted(self):
total = 0
for start_stop, meta in self.statements().items():
start = datetime.datetime.strftime(start_stop[0], "%Y-%m-%d")
stop = datetime.datetime.strftime(start_stop[1], "%Y-%m-%d")
out = f"Date Range: {start} -> {stop}\n"
for txn in meta["transactions"]:
total += txn["amount"]
out += (
f"* {txn['transaction_date']}"
f": {txn['transaction_type']}"
f"\t{txn['amount']}"
f"\t{total}"
f"\t{txn['description']}"
)
out += "\n"
print(out)
def interview():
txns = Transactions(TRANSACTIONS, interest=12.34)
balance = txns.balance()
average = txns.average()
largest = txns.largest()
pprint(locals())
txns.statements_print_formatted()
# Press the green button in the gutter to run the script.
if __name__ == "__main__":
interview()
# See PyCharm help at https://www.jetbrains.com/help/pycharm/