import flet as ft import requests from datetime import datetime from config import API_BASE_URL class ReportPage: def __init__(self, page: ft.Page, dashboard): self.page = page self.dashboard = dashboard self.start_date = ft.Text() self.end_date = ft.Text() # self.client_filter = ft.TextField(label="Client", expand=True) # self.transporter_filter = ft.TextField(label="Transporter", expand=True) self.status_text = ft.Text("") self.results_text = ft.Text("") self.rows = [] self.rows_copy = [] self.total = ft.Text("Total: ", weight=ft.FontWeight.BOLD) self.data_table = ft.DataTable( columns=[ ft.DataColumn(label=ft.Text("Order #")), ft.DataColumn(label=ft.Text("Client")), ft.DataColumn(label=ft.Text("Transporter")), ft.DataColumn(label=ft.Text("Date")), ft.DataColumn(label=ft.Text("Paid (€)")), ft.DataColumn(label=ft.Text("Received (€)")), ft.DataColumn(label=ft.Text("Profit (€)")), ], rows=[], border=ft.border.all(1, ft.Colors.GREY_300), expand=True ) self.all_clients = [] self.all_transporters = [] self.create_table_rows_data() self.clients_filter = ft.Dropdown( options=[ ft.dropdown.Option(text = client['name'], key=client['name']) for client in self.all_clients ], width=250, label="Clients", hint_text= "Select client", on_change= self.filter_by_client ) self.clients_filter_placeholder = ft.Container(content=self.clients_filter) self.transporters_filter = ft.Dropdown( options=[ ft.dropdown.Option(text = transporter['name'], key=transporter['name']) for transporter in self.all_transporters ], width=250, label="Transporters", hint_text= "Select transporter", on_change= self.filter_by_transporter ) self.transporters_filter_placeholder = ft.Container(content=self.transporters_filter) def get_orders(self): try: token = self.page.client_storage.get("token") headers = {"Authorization": f"Bearer {token}"} response = requests.get(f"{API_BASE_URL}/orders/list", headers=headers) return response.json() if response.status_code == 200 else [] except Exception as e: print("Error loading orders:", e) def get_client(self, id): try: token = self.page.client_storage.get("token") headers = {"Authorization": f"Bearer {token}"} response = requests.get(f"{API_BASE_URL}/clients/{id}", headers=headers) if response.json() not in self.all_clients: self.all_clients.append(response.json()) return response.json() if response.status_code == 200 else None except Exception as e: print("Error loading clients:", e) def get_transporter(self, id): try: token = self.page.client_storage.get("token") headers = {"Authorization": f"Bearer {token}"} response = requests.get(f"{API_BASE_URL}/transporters/{id}", headers=headers) if response.json() not in self.all_transporters: self.all_transporters.append(response.json()) return response.json() if response.status_code == 200 else None except Exception as e: print("Error loading transporters:", e) def fetch_report(self, e): total = 0 data = self.search_input.value self.rows_copy = self.rows self.data_table.rows.clear() buffer = [] for r in self.rows_copy: if data in r[1]: row = ft.DataRow( cells=[ ft.DataCell(ft.Text(r[0])), ft.DataCell(ft.Text(r[1])), ft.DataCell(ft.Text(r[2])), ft.DataCell(ft.Text(r[3])), ft.DataCell(ft.Text(r[4])), ft.DataCell(ft.Text(r[5])), ft.DataCell(ft.Text(r[6])), ], ) self.data_table.rows.append(row) buffer.append(r) total += r[6] self.rows_copy = buffer self.data_table.update() self.total.value = f"Total: {total}" self.total.update() def create_table_rows_data(self): all_orders = self.get_orders() total = 0 for order in all_orders: # Skip non-active orders from reports #print(order.get('status')) if order.get('status') != 'active': continue order_number = order['order_number'] client_name = self.get_client(order['client_id'])['name'] transporter_name = self.get_transporter(order['transporter_id'])['name'] order_date = order['created_at'].split("T")[0] paid = order['paid_price'] received = order['received_price'] try: profit = round(float(received) - float(paid), 2) except: profit = 0.00 row = ft.DataRow( cells=[ ft.DataCell(ft.Text(order_number)), ft.DataCell(ft.Text(client_name)), ft.DataCell(ft.Text(transporter_name)), ft.DataCell(ft.Text(order_date)), ft.DataCell(ft.Text(paid)), ft.DataCell(ft.Text(received)), ft.DataCell(ft.Text(profit)), ], ) row_data = [order_number, client_name, transporter_name, order_date, paid, received, profit] self.rows.append(row_data) self.data_table.rows.append(row) total += profit self.total.value = f"Total: {total}" self.rows_copy = self.rows def on_reset_btn_click(self, e): # --- Recreate Clients dropdown to avoid sticky selection text on Flet 0.28.3 --- try: client_options = list(self.clients_filter.options) except Exception: client_options = [] new_clients_dd = ft.Dropdown( options=client_options, width=250, label="Clients", hint_text="Select client", on_change=self.filter_by_client, value=None, ) self.clients_filter = new_clients_dd self.clients_filter_placeholder.content = self.clients_filter self.clients_filter_placeholder.update() # --- Recreate Transporters dropdown --- try: transporter_options = list(self.transporters_filter.options) except Exception: transporter_options = [] new_transporters_dd = ft.Dropdown( options=transporter_options, width=250, label="Transporters", hint_text="Select transporter", on_change=self.filter_by_transporter, value=None, ) self.transporters_filter = new_transporters_dd self.transporters_filter_placeholder.content = self.transporters_filter self.transporters_filter_placeholder.update() self.page.update() self.rows_copy = list(self.rows) total = 0 self.data_table.rows.clear() for r in self.rows_copy: row = ft.DataRow( cells=[ ft.DataCell(ft.Text(r[0])), ft.DataCell(ft.Text(r[1])), ft.DataCell(ft.Text(r[2])), ft.DataCell(ft.Text(r[3])), ft.DataCell(ft.Text(r[4])), ft.DataCell(ft.Text(r[5])), ft.DataCell(ft.Text(r[6])), ], ) self.data_table.rows.append(row) total += r[6] self.data_table.update() self.total.value = f"Total: {total}" self.total.update() self.start_date.value = "" self.start_date.update() self.end_date.value = "" self.end_date.update() def on_start_date_click(self, e): self.start_date.value = e.control.value.strftime('%Y-%m-%d') self.start_date.update() total = 0 self.data_table.rows.clear() buffer = [] data = datetime.strptime(self.start_date.value, '%Y-%m-%d') for r in self.rows_copy: obj_date = datetime.strptime(r[3], '%Y-%m-%d') if data <= obj_date: row = ft.DataRow( cells=[ ft.DataCell(ft.Text(r[0])), ft.DataCell(ft.Text(r[1])), ft.DataCell(ft.Text(r[2])), ft.DataCell(ft.Text(r[3])), ft.DataCell(ft.Text(r[4])), ft.DataCell(ft.Text(r[5])), ft.DataCell(ft.Text(r[6])), ], ) self.data_table.rows.append(row) buffer.append(r) total += r[6] self.rows_copy = buffer self.data_table.update() self.total.value = f"Total: {total}" self.total.update() def on_end_date_click(self, e): self.end_date.value = e.control.value.strftime('%Y-%m-%d') self.end_date.update() total = 0 self.data_table.rows.clear() buffer = [] data = datetime.strptime(self.end_date.value, '%Y-%m-%d') for r in self.rows_copy: obj_date = datetime.strptime(r[3], '%Y-%m-%d') if data >= obj_date: row = ft.DataRow( cells=[ ft.DataCell(ft.Text(r[0])), ft.DataCell(ft.Text(r[1])), ft.DataCell(ft.Text(r[2])), ft.DataCell(ft.Text(r[3])), ft.DataCell(ft.Text(r[4])), ft.DataCell(ft.Text(r[5])), ft.DataCell(ft.Text(r[6])), ], ) self.data_table.rows.append(row) buffer.append(r) total += r[6] self.rows_copy = buffer self.data_table.update() self.total.value = f"Total: {total}" self.total.update() def filter_by_client(self, e): total = 0 self.data_table.rows.clear() buffer = [] for r in self.rows_copy: #print(r[1]) #print(self.clients_filter.value) if r[1] == self.clients_filter.value: row = ft.DataRow( cells=[ ft.DataCell(ft.Text(r[0])), ft.DataCell(ft.Text(r[1])), ft.DataCell(ft.Text(r[2])), ft.DataCell(ft.Text(r[3])), ft.DataCell(ft.Text(r[4])), ft.DataCell(ft.Text(r[5])), ft.DataCell(ft.Text(r[6])), ], ) self.data_table.rows.append(row) buffer.append(r) total += r[6] self.rows_copy = buffer self.data_table.update() self.total.value = f"Total: {total}" self.total.update() def filter_by_transporter(self, e): total = 0 self.data_table.rows.clear() buffer = [] for r in self.rows_copy: #print(r[2]) #print(self.transporters_filter.value) if r[2] == self.transporters_filter.value: row = ft.DataRow( cells=[ ft.DataCell(ft.Text(r[0])), ft.DataCell(ft.Text(r[1])), ft.DataCell(ft.Text(r[2])), ft.DataCell(ft.Text(r[3])), ft.DataCell(ft.Text(r[4])), ft.DataCell(ft.Text(r[5])), ft.DataCell(ft.Text(r[6])), ], ) self.data_table.rows.append(row) buffer.append(r) total += r[6] self.rows_copy = buffer self.data_table.update() self.total.value = f"Total: {total}" self.total.update() def get_client_access(self): token = self.page.client_storage.get("token") headers = {"Authorization": f"Bearer {token}"} response = requests.get(f"{API_BASE_URL}/profile/", headers=headers, timeout=10) user = response.json() if user['user_role'] == 'user': return True else: id = self.page.session.get("user_id") response = requests.get(f"{API_BASE_URL}/company_user/access/{id}", headers=headers) return True if response.json()['report'] == 1 else False def build(self): return ft.Container( content=ft.Column( [ ft.Row( [ ft.Text("Reports", size=24, weight=ft.FontWeight.BOLD), self.total ], alignment=ft.MainAxisAlignment.SPACE_BETWEEN ), ft.Row( [ self.start_date, ft.ElevatedButton( "Start Date", on_click=lambda _: self.page.open(ft.DatePicker( first_date=datetime(year=2000, month=10, day=1), last_date=datetime(year=2025, month=10, day=1), on_change=self.on_start_date_click, )), width=120, icon=ft.Icons.CALENDAR_MONTH ), self.end_date, ft.ElevatedButton( "End Date", on_click=lambda _: self.page.open(ft.DatePicker( first_date=datetime(year=2000, month=10, day=1), last_date=datetime(year=2025, month=10, day=1), on_change=self.on_end_date_click, )), width=120, icon=ft.Icons.CALENDAR_MONTH ), ft.Text(), self.clients_filter_placeholder, self.transporters_filter_placeholder, ft.ElevatedButton("Reset", on_click=self.on_reset_btn_click, width=120), ] ), ft.Column( [ ft.Row( [ self.data_table, self.status_text, ], expand=True, ) ], alignment=ft.MainAxisAlignment.START, scroll=ft.ScrollMode.ADAPTIVE, expand=True, ) ], expand=True, alignment=ft.MainAxisAlignment.START, ), expand=True ) if self.get_client_access() else ft.Container( content=ft.Column( [ ft.Row( [ ft.Text("Reports", size=24, weight=ft.FontWeight.BOLD), ], alignment=ft.MainAxisAlignment.SPACE_BETWEEN ), ft.Row( [ ft.Text( "You do not have access to this page content", size=24, weight=ft.FontWeight.BOLD, color=ft.Colors.RED ) ], alignment=ft.MainAxisAlignment.CENTER ), ft.Text("") ], alignment=ft.MainAxisAlignment.SPACE_BETWEEN, expand=True ), expand=True )