Update app.py
Browse files
    	
        app.py
    CHANGED
    
    | @@ -15,8 +15,8 @@ class InterestCalculatorApp: | |
| 15 | 
             
                                                                                         "Quarterly compounding (1 Mar, 1 Jun, 1 Sep, 1 Dec)"])
         | 
| 16 |  | 
| 17 | 
             
                    # Load TAPAS model
         | 
| 18 | 
            -
                    self. | 
| 19 | 
            -
                    self. | 
| 20 |  | 
| 21 | 
             
                def load_invoices(self, file_path):
         | 
| 22 | 
             
                    try:
         | 
| @@ -29,37 +29,88 @@ class InterestCalculatorApp: | |
| 29 | 
             
                    if self.invoices_df is not None and self.base_rates_df is not None:
         | 
| 30 | 
             
                        st.write("Calculating interest...")
         | 
| 31 | 
             
                        today = datetime.today()
         | 
| 32 | 
            -
                         | 
| 33 | 
            -
                        
         | 
| 34 | 
            -
                        # Tokenize table
         | 
| 35 | 
            -
                        table_text = self.invoices_df.to_csv(index=False)
         | 
| 36 | 
            -
                        table_inputs = self.tapas_tokenizer(table_text, return_tensors="pt", padding=True)
         | 
| 37 | 
            -
                        
         | 
| 38 | 
             
                        for index, invoice in self.invoices_df.iterrows():
         | 
| 39 | 
             
                            due_date = invoice['Due Date']
         | 
| 40 | 
             
                            amount = invoice['Amount']
         | 
| 41 | 
             
                            base_rate = self.get_base_rate(due_date)
         | 
| 42 | 
             
                            effective_rate = base_rate + self.late_payment_interest
         | 
|  | |
|  | |
|  | |
| 43 | 
             
                            interest = self.calculate_compound_interest(due_date, amount, effective_rate, self.compounding_method, today)
         | 
|  | |
| 44 | 
             
                            total_amount_owed = amount + interest
         | 
| 45 | 
             
                            self.invoices_df.loc[index, 'Interest'] = interest
         | 
| 46 | 
             
                            self.invoices_df.loc[index, 'Total Amount Owed'] = total_amount_owed
         | 
| 47 | 
            -
             | 
| 48 | 
            -
                        
         | 
| 49 | 
            -
                        # Get model prediction
         | 
| 50 | 
            -
                        query = "What is the total interest?"
         | 
| 51 | 
            -
                        query_inputs = self.tapas_tokenizer(query, return_tensors="pt", padding=True)
         | 
| 52 | 
            -
                        outputs = self.tapas_model(**table_inputs, **query_inputs)
         | 
| 53 | 
            -
                        total_interest_prediction = self.tapas_tokenizer.decode(outputs.logits.argmax(dim=-1))
         | 
| 54 | 
            -
                        
         | 
| 55 | 
            -
                        st.success(f"Total Interest Calculated: £{total_interest:.2f} (Model Prediction: {total_interest_prediction.strip()})")
         | 
| 56 | 
             
                        st.write(self.invoices_df)
         | 
| 57 | 
             
                    else:
         | 
| 58 | 
             
                        st.error("Please load both invoices and base rates files.")
         | 
| 59 |  | 
| 60 | 
            -
                 | 
|  | |
|  | |
|  | |
| 61 |  | 
| 62 | 
            -
             | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 63 | 
             
                st.title("Interest Calculation App")
         | 
| 64 |  | 
| 65 | 
             
                app = InterestCalculatorApp()
         | 
| @@ -73,3 +124,6 @@ if __name__ == "__main__": | |
| 73 | 
             
                    app.calculate_interest()
         | 
| 74 |  | 
| 75 | 
             
                app.download_boe_rates()
         | 
|  | |
|  | |
|  | 
|  | |
| 15 | 
             
                                                                                         "Quarterly compounding (1 Mar, 1 Jun, 1 Sep, 1 Dec)"])
         | 
| 16 |  | 
| 17 | 
             
                    # Load TAPAS model
         | 
| 18 | 
            +
                    self.tokenizer = AutoTokenizer.from_pretrained("google/tapas-large-finetuned-wtq")
         | 
| 19 | 
            +
                    self.model = AutoModelForTableQuestionAnswering.from_pretrained("google/tapas-large-finetuned-wtq")
         | 
| 20 |  | 
| 21 | 
             
                def load_invoices(self, file_path):
         | 
| 22 | 
             
                    try:
         | 
|  | |
| 29 | 
             
                    if self.invoices_df is not None and self.base_rates_df is not None:
         | 
| 30 | 
             
                        st.write("Calculating interest...")
         | 
| 31 | 
             
                        today = datetime.today()
         | 
| 32 | 
            +
                        interests = []
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
| 33 | 
             
                        for index, invoice in self.invoices_df.iterrows():
         | 
| 34 | 
             
                            due_date = invoice['Due Date']
         | 
| 35 | 
             
                            amount = invoice['Amount']
         | 
| 36 | 
             
                            base_rate = self.get_base_rate(due_date)
         | 
| 37 | 
             
                            effective_rate = base_rate + self.late_payment_interest
         | 
| 38 | 
            +
                            if due_date > today:
         | 
| 39 | 
            +
                                interests.append(0)
         | 
| 40 | 
            +
                                continue
         | 
| 41 | 
             
                            interest = self.calculate_compound_interest(due_date, amount, effective_rate, self.compounding_method, today)
         | 
| 42 | 
            +
                            interests.append(interest)
         | 
| 43 | 
             
                            total_amount_owed = amount + interest
         | 
| 44 | 
             
                            self.invoices_df.loc[index, 'Interest'] = interest
         | 
| 45 | 
             
                            self.invoices_df.loc[index, 'Total Amount Owed'] = total_amount_owed
         | 
| 46 | 
            +
                        total_interest = sum(interests)
         | 
| 47 | 
            +
                        st.success(f"Total Interest Calculated: £{total_interest:.2f}")
         | 
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
| 48 | 
             
                        st.write(self.invoices_df)
         | 
| 49 | 
             
                    else:
         | 
| 50 | 
             
                        st.error("Please load both invoices and base rates files.")
         | 
| 51 |  | 
| 52 | 
            +
                def get_base_rate(self, due_date):
         | 
| 53 | 
            +
                    self.base_rates_df['Date Changed'] = pd.to_datetime(self.base_rates_df['Date Changed'])
         | 
| 54 | 
            +
                    rate_rows = self.base_rates_df[self.base_rates_df['Date Changed'] <= due_date].sort_values(by='Date Changed', ascending=False)
         | 
| 55 | 
            +
                    return rate_rows.iloc[0]['Rate'] if not rate_rows.empty else 0
         | 
| 56 |  | 
| 57 | 
            +
                def calculate_compound_interest(self, due_date, amount, effective_rate, method, today):
         | 
| 58 | 
            +
                    days = (today - due_date).days
         | 
| 59 | 
            +
                    if 'daily' in method:
         | 
| 60 | 
            +
                        daily_rate = (effective_rate / 100) / 365
         | 
| 61 | 
            +
                        return amount * daily_rate * days
         | 
| 62 | 
            +
                    elif 'annually' in method:
         | 
| 63 | 
            +
                        annual_rate = effective_rate / 100
         | 
| 64 | 
            +
                        return amount * annual_rate * (days / 365)
         | 
| 65 | 
            +
                    elif 'Quarterly compounding' in method:
         | 
| 66 | 
            +
                        return self.calculate_quarterly_interest(due_date, amount, effective_rate, method, today)
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                def calculate_quarterly_interest(self, due_date, amount, effective_rate, method, today):
         | 
| 69 | 
            +
                    quarterly_dates = {
         | 
| 70 | 
            +
                        "Quarterly compounding (25 Mar, 24 Jun, 29 Sep, 25 Dec)": [(3, 25), (6, 24), (9, 29), (12, 25)],
         | 
| 71 | 
            +
                        "Quarterly compounding (1 Mar, 1 Jun, 1 Sep, 1 Dec)": [(3, 1), (6, 1), (9, 1), (12, 1)]
         | 
| 72 | 
            +
                    }[method]
         | 
| 73 | 
            +
                    interest = 0
         | 
| 74 | 
            +
                    compounded_amount = amount
         | 
| 75 | 
            +
                    for month, day in quarterly_dates:
         | 
| 76 | 
            +
                        compounding_date = datetime(today.year, month, day)
         | 
| 77 | 
            +
                        if compounding_date > today:
         | 
| 78 | 
            +
                            break
         | 
| 79 | 
            +
                        if compounding_date > due_date:
         | 
| 80 | 
            +
                            days_since_last_compounding = (today - compounding_date).days
         | 
| 81 | 
            +
                            period_rate = effective_rate / 4  # Quarterly rate
         | 
| 82 | 
            +
                            compounded_interest = compounded_amount * ((1 + period_rate) ** (days_since_last_compounding / 365.25) - 1)
         | 
| 83 | 
            +
                            compounded_amount += compounded_interest
         | 
| 84 | 
            +
                            interest += compounded_interest
         | 
| 85 | 
            +
                            due_date = compounding_date
         | 
| 86 | 
            +
                    return interest
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                def download_boe_rates(self):
         | 
| 89 | 
            +
                    try:
         | 
| 90 | 
            +
                        headers = {
         | 
| 91 | 
            +
                            'accept-language': 'en-US,en;q=0.9',
         | 
| 92 | 
            +
                            'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36'
         | 
| 93 | 
            +
                        }
         | 
| 94 | 
            +
                        url = 'https://www.bankofengland.co.uk/boeapps/database/Bank-Rate.asp'
         | 
| 95 | 
            +
                        response = requests.get(url, headers=headers)
         | 
| 96 | 
            +
                        if response.status_code == 200:
         | 
| 97 | 
            +
                            df = pd.read_html(response.text)[0]
         | 
| 98 | 
            +
                            df.to_csv('boe_rates.csv', index=False)
         | 
| 99 | 
            +
                            self.base_rates_df = df
         | 
| 100 | 
            +
                            self.base_rates_df['Date Changed'] = pd.to_datetime(self.base_rates_df['Date Changed'], format='%d %b %y')
         | 
| 101 | 
            +
                            st.success("Bank of England rates downloaded successfully.")
         | 
| 102 | 
            +
                        else:
         | 
| 103 | 
            +
                            st.error("Failed to retrieve data from the Bank of England website.")
         | 
| 104 | 
            +
                    except requests.RequestException as e:
         | 
| 105 | 
            +
                        st.error(f"Failed to download rates: {e}")
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                def ask_tapas(self, query, table):
         | 
| 108 | 
            +
                    inputs = self.tokenizer(table, query, return_tensors="pt", padding=True)
         | 
| 109 | 
            +
                    outputs = self.model(**inputs)
         | 
| 110 | 
            +
                    predicted_answer = self.tokenizer.decode(outputs.logits.argmax(dim=-1))
         | 
| 111 | 
            +
                    return predicted_answer
         | 
| 112 | 
            +
             | 
| 113 | 
            +
            def main():
         | 
| 114 | 
             
                st.title("Interest Calculation App")
         | 
| 115 |  | 
| 116 | 
             
                app = InterestCalculatorApp()
         | 
|  | |
| 124 | 
             
                    app.calculate_interest()
         | 
| 125 |  | 
| 126 | 
             
                app.download_boe_rates()
         | 
| 127 | 
            +
             | 
| 128 | 
            +
            if __name__ == "__main__":
         | 
| 129 | 
            +
                main()
         |