File size: 6,829 Bytes
b54df69
 
3cddf46
771a15e
3cddf46
b54df69
 
 
3cddf46
 
b54df69
 
 
 
 
d6e934d
 
b54df69
 
 
 
 
 
 
 
 
3cddf46
b54df69
3cddf46
d6e934d
b54df69
 
 
 
 
d6e934d
 
 
b54df69
d6e934d
b54df69
 
 
d6e934d
 
b54df69
 
 
 
d6e934d
 
 
 
b54df69
d6e934d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3cddf46
d6e934d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2532ae2
3cddf46
 
 
 
 
 
bbfaf4f
d6e934d
b54df69
 
 
 
 
 
 
 
 
c7fc47a
 
 
 
 
 
 
 
 
 
b54df69
 
 
771a15e
 
d6e934d
 
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
129
130
131
132
133
134
135
136
137
138
139
140
import streamlit as st
import pandas as pd
import datetime
from transformers import AutoTokenizer, AutoModelForTableQuestionAnswering
import requests

class InterestCalculatorApp:
    def __init__(self):
        self.invoices_df = pd.DataFrame()  # Initialize as empty DataFrame
        self.base_rates_df = pd.DataFrame()  # Initialize as empty DataFrame
        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)"])
        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 not self.invoices_df.empty and not self.base_rates_df.empty:
            st.write("Calculating interest...")
            today = datetime.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.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):
        if not isinstance(table, pd.DataFrame):
            raise TypeError("Expected the table to be a pd.DataFrame, got {}".format(type(table).__name__))
        inputs = self.tokenizer(table=table, queries=[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)

    query = st.text_input("Enter your query:")
    if query:
        if not app.invoices_df.empty:
            st.write("Invoice Data:")
            st.write(app.invoices_df)
            answer = app.ask_tapas(query, app.invoices_df)
            st.write("Answer:", answer)
        else:
            st.warning("Please upload the invoices file first.")

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

    app.download_boe_rates()

if __name__ == "__main__":
    main()