File size: 6,199 Bytes
b54df69
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import streamlit as st
import pandas as pd
from transformers import AutoTokenizer, AutoModelForTableQuestionAnswering

class InterestCalculatorApp:
    def __init__(self):
        self.invoices_df = None
        self.base_rates_df = None
        self.late_payment_interest = st.sidebar.slider("Late Payment Interest Rate (%)", min_value=0.0, max_value=10.0, value=4.0)
        self.compounding_method = st.sidebar.selectbox("Compounding Method", ["x% above Base Rate (daily)", 
                                                                            "x% above Base Rate (annually)",
                                                                             "Quarterly compounding (25 Mar, 24 Jun, 29 Sep, 25 Dec)",
                                                                             "Quarterly compounding (1 Mar, 1 Jun, 1 Sep, 1 Dec)"])

        # Load TAPAS model
        self.tokenizer = AutoTokenizer.from_pretrained("google/tapas-large-finetuned-wtq")
        self.model = AutoModelForTableQuestionAnswering.from_pretrained("google/tapas-large-finetuned-wtq")

    def load_invoices(self, file_path):
        try:
            self.invoices_df = pd.read_excel(file_path, parse_dates=['Due Date'])
            st.success("Invoices loaded successfully.")
        except Exception as e:
            st.error(f"Failed to load invoices: {e}")

    def calculate_interest(self):
        if self.invoices_df is not None and self.base_rates_df is not None:
            st.write("Calculating interest...")
            today = datetime.today()
            interests = []
            for index, invoice in self.invoices_df.iterrows():
                due_date = invoice['Due Date']
                amount = invoice['Amount']
                base_rate = self.get_base_rate(due_date)
                effective_rate = base_rate + self.late_payment_interest
                if due_date > today:
                    interests.append(0)
                    continue
                interest = self.calculate_compound_interest(due_date, amount, effective_rate, self.compounding_method, today)
                interests.append(interest)
                total_amount_owed = amount + interest
                self.invoices_df.loc[index, 'Interest'] = interest
                self.invoices_df.loc[index, 'Total Amount Owed'] = total_amount_owed
            total_interest = sum(interests)
            st.success(f"Total Interest Calculated: £{total_interest:.2f}")
            st.write(self.invoices_df)
        else:
            st.error("Please load both invoices and base rates files.")

    def get_base_rate(self, due_date):
        self.base_rates_df['Date Changed'] = pd.to_datetime(self.base_rates_df['Date Changed'])
        rate_rows = self.base_rates_df[self.base_rates_df['Date Changed'] <= due_date].sort_values(by='Date Changed', ascending=False)
        return rate_rows.iloc[0]['Rate'] if not rate_rows.empty else 0

    def calculate_compound_interest(self, due_date, amount, effective_rate, method, today):
        days = (today - due_date).days
        if 'daily' in method:
            daily_rate = (effective_rate / 100) / 365
            return amount * daily_rate * days
        elif 'annually' in method:
            annual_rate = effective_rate / 100
            return amount * annual_rate * (days / 365)
        elif 'Quarterly compounding' in method:
            return self.calculate_quarterly_interest(due_date, amount, effective_rate, method, today)

    def calculate_quarterly_interest(self, due_date, amount, effective_rate, method, today):
        quarterly_dates = {
            "Quarterly compounding (25 Mar, 24 Jun, 29 Sep, 25 Dec)": [(3, 25), (6, 24), (9, 29), (12, 25)],
            "Quarterly compounding (1 Mar, 1 Jun, 1 Sep, 1 Dec)": [(3, 1), (6, 1), (9, 1), (12, 1)]
        }[method]
        interest = 0
        compounded_amount = amount
        for month, day in quarterly_dates:
            compounding_date = datetime(today.year, month, day)
            if compounding_date > today:
                break
            if compounding_date > due_date:
                days_since_last_compounding = (today - compounding_date).days
                period_rate = effective_rate / 4  # Quarterly rate
                compounded_interest = compounded_amount * ((1 + period_rate) ** (days_since_last_compounding / 365.25) - 1)
                compounded_amount += compounded_interest
                interest += compounded_interest
                due_date = compounding_date
        return interest

    def download_boe_rates(self):
        try:
            headers = {
                'accept-language': 'en-US,en;q=0.9',
                'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36'
            }
            url = 'https://www.bankofengland.co.uk/boeapps/database/Bank-Rate.asp'
            response = requests.get(url, headers=headers)
            if response.status_code == 200:
                df = pd.read_html(response.text)[0]
                df.to_csv('boe_rates.csv', index=False)
                self.base_rates_df = df
                self.base_rates_df['Date Changed'] = pd.to_datetime(self.base_rates_df['Date Changed'], format='%d %b %y')
                st.success("Bank of England rates downloaded successfully.")
            else:
                st.error("Failed to retrieve data from the Bank of England website.")
        except requests.RequestException as e:
            st.error(f"Failed to download rates: {e}")

    def ask_tapas(self, query, table):
        inputs = self.tokenizer(table, query, return_tensors="pt", padding=True)
        outputs = self.model(**inputs)
        predicted_answer = self.tokenizer.decode(outputs.logits.argmax(dim=-1))
        return predicted_answer

def main():
    st.title("Interest Calculation App")

    app = InterestCalculatorApp()

    file_path = st.file_uploader("Upload Invoices File", type=["xlsx"])

    if file_path is not None:
        app.load_invoices(file_path)

    if st.button("Calculate Interest"):
        app.calculate_interest()

    app.download_boe_rates()

if __name__ == "__main__":
    main()