Files
JuridicBloc/client/pages/settings/payment_and_subscription.py
2026-06-13 21:46:37 +03:00

351 lines
13 KiB
Python

import flet as ft
import requests
from helpers.payment_type import PaymentType
class PaymentAndSubscription:
def __init__(self, page: ft.Page):
self.page = page
self.base_url = self.page.session.store.get('api_base_url')
self.token = self.page.session.store.get('token')
self.selected_payment_id = None
self.selected_sub_id = None
self.payment_type = [
PaymentType().ONE_TIME_ONLY,
PaymentType().SUBSCRIPTION.lower()
]
# Pre-fetch data as in users.py
self.all_payments = self.get_payments_data()
self.all_subscriptions = self.get_subscriptions_data()
self.name = ft.TextField(label = "Denumire")
self.amount = ft.TextField(label="Valoare", suffix="Lei")
self.type = ft.RadioGroup(
content=ft.Row(
[ft.Radio(value=payment, label=payment.upper()) for payment in self.payment_type]
)
)
self.error_text = ft.Text(color=ft.Colors.RED)
self.payments_list = ft.ListView(
controls=self.create_payment_list(self.all_payments, self.on_edit_payment_click),
spacing=10,
expand=True,
padding=10
)
# Elemente pentru Abonamente
self.sub_name = ft.TextField(label="Nume Abonament", width=350)
self.payment_dropdown = ft.Dropdown(
label="Selecteaza Plata",
width=350,
options=[
ft.dropdown.Option(key=str(p['id']), text=f"{p['name']} ({p['amount']} Lei)")
for p in self.all_payments if p['type'].lower() == self.payment_type[1].lower()
]
)
self.months_dropdown = ft.Dropdown(
label="Numar luni",
width=350,
options=[ft.dropdown.Option(str(i)) for i in range(1, 13)]
)
self.sub_error_text = ft.Text(color=ft.Colors.RED)
self.subs_list = ft.ListView(
controls=self.create_subscription_list(self.all_subscriptions, self.on_edit_sub_click),
spacing=10,
expand=True,
padding=10
)
self.add_payment_dialog = ft.AlertDialog(
title=ft.Text("Detalii Plata"),
content=ft.Column(
[
self.name,
self.amount,
ft.Text("Tip plata:", weight=ft.FontWeight.BOLD),
self.type,
self.error_text
],
height=250,
tight=True
),
actions=[
ft.FilledButton("Salveaza", on_click=self.on_save_btn_click),
ft.FilledButton("Cancel", on_click=self.on_cancel_btn_click, bgcolor=ft.Colors.GREY)
]
)
self.add_sub_dialog = ft.AlertDialog(
title=ft.Text("Detalii Abonament"),
content=ft.Column(
[
self.sub_name,
self.payment_dropdown,
self.months_dropdown,
self.sub_error_text
],
height=280,
tight=True
),
actions=[
ft.FilledButton("Salveaza", on_click=self.on_save_sub_click),
ft.FilledButton("Cancel", on_click=self.on_cancel_btn_click, bgcolor=ft.Colors.GREY)
]
)
# --- LOGICA PLATI ---
def add_new_payment_btn_click(self, e):
self.selected_payment_id = None
self.name.value = ''
self.amount.value = ''
self.type.value = None
self.error_text.value = ''
self.add_payment_dialog.title = ft.Text("Adauga plata noua")
self.page.show_dialog(self.add_payment_dialog)
self.page.update()
def on_edit_payment_click(self, payment):
self.selected_payment_id = payment['id']
self.name.value = payment['name']
self.amount.value = str(payment['amount'])
self.type.value = payment['type']
self.error_text.value = ''
self.add_payment_dialog.title = ft.Text("Editeaza plata")
self.page.show_dialog(self.add_payment_dialog)
self.page.update()
def get_payments_data(self):
try:
response = requests.get(
f"{self.base_url}/payments/",
headers={'Authorization': f'Bearer {self.token}'}
)
if response.status_code == 200:
return response.json()
except Exception as e:
print(f"Error fetching payments: {e}")
return []
def get_payments(self):
self.all_payments = self.get_payments_data()
self.payments_list.controls = self.create_payment_list(self.all_payments, self.on_edit_payment_click)
if self.payments_list.page:
self.payments_list.update()
# Actualizăm și opțiunile dropdown-ului pentru abonamente
self.payment_dropdown.options = [
ft.dropdown.Option(key=str(p['id']), text=f"{p['name']} ({p['amount']} Lei)")
for p in self.all_payments if p['type'].lower() == self.payment_type[1].lower()
]
if self.payment_dropdown.page:
self.payment_dropdown.update()
def create_payment_list(self, items, on_click_handler):
return [
ft.Container(
content=ft.Row(
[
ft.Column(
[
ft.Text(p['name'], weight=ft.FontWeight.BOLD),
ft.Text(f"{p['amount']} Lei - {p['type'].upper()}", size=12),
],
alignment=ft.MainAxisAlignment.CENTER,
),
ft.IconButton(
icon=ft.Icons.EDIT,
on_click=lambda e, payment=p: on_click_handler(payment)
)
],
alignment=ft.MainAxisAlignment.SPACE_BETWEEN
),
bgcolor=ft.Colors.BLUE_50,
padding=10,
border_radius=8,
border=ft.Border.all(1, ft.Colors.GREY_300),
ink=True
)
for p in items
]
def on_save_btn_click(self, e):
if not self.name.value or not self.amount.value or not self.type.value:
self.error_text.value = "Toate campurile sunt obligatorii!"
self.error_text.update()
return
print(self.amount.value)
try:
payload = {
"name": self.name.value,
"amount": float(self.amount.value),
"type": self.type.value
}
if self.selected_payment_id:
# Update
url = f"{self.base_url}/payments/update/{self.selected_payment_id}"
response = requests.put(url, json=payload, headers={'Authorization': f'Bearer {self.token}'})
else:
# Create
url = f"{self.base_url}/payments/add"
response = requests.post(url, json=payload, headers={'Authorization': f'Bearer {self.token}'})
if response.status_code in [200, 201]:
self.page.pop_dialog()
self.get_payments()
else:
self.error_text.value = "Eroare la salvare"
self.error_text.update()
except Exception as e:
print(e)
self.error_text.value = "Valoarea trebuie sa fie un numar!"
self.error_text.update()
# --- LOGICA ABONAMENTE ---
def add_new_sub_btn_click(self, e):
self.selected_sub_id = None
self.sub_name.value = ""
# Resetăm dropdown-urile la starea default (fără selecție)
self.payment_dropdown.value = ""
self.months_dropdown.value = ""
self.sub_error_text.value = ""
self.add_sub_dialog.title = ft.Text("Adauga Abonament Nou")
# Forțăm afișarea dialogului cu valorile proaspăt resetate
self.page.show_dialog(self.add_sub_dialog)
self.page.update()
def on_edit_sub_click(self, sub):
self.selected_sub_id = sub['id']
self.sub_name.value = sub['name']
self.payment_dropdown.value = str(sub['pay_and_subs_id'])
self.months_dropdown.value = str(sub['mounts'])
self.sub_error_text.value = ""
self.add_sub_dialog.title = ft.Text("Editeaza Abonament")
self.page.show_dialog(self.add_sub_dialog)
self.page.update()
def get_subscriptions_data(self):
try:
response = requests.get(
f"{self.base_url}/subscriptions/",
headers={'Authorization': f'Bearer {self.token}'}
)
if response.status_code == 200:
return response.json()
except Exception as e:
print(f"Error fetching subscriptions: {e}")
return []
def get_subscriptions(self):
self.all_subscriptions = self.get_subscriptions_data()
self.subs_list.controls = self.create_subscription_list(self.all_subscriptions, self.on_edit_sub_click)
if self.subs_list.page:
self.subs_list.update()
def create_subscription_list(self, items, on_click_handler):
controls = []
for s in items:
# Gasim plata asociata pentru a calcula totalul
payment = next((p for p in self.all_payments if p['id'] == s['pay_and_subs_id']), None)
amount = payment['amount'] if payment else 0
total = amount * (s['mounts'] or 0)
controls.append(
ft.Container(
content=ft.Row(
[
ft.Column(
[
ft.Text(s['name'], weight=ft.FontWeight.BOLD),
ft.Text(f"{s['mounts']} luni x {amount} Lei = {total} Lei Total", size=12, color=ft.Colors.BLUE_700),
],
alignment=ft.MainAxisAlignment.CENTER,
),
ft.IconButton(
icon=ft.Icons.EDIT,
on_click=lambda e, sub=s: on_click_handler(sub)
)
],
alignment=ft.MainAxisAlignment.SPACE_BETWEEN
),
bgcolor=ft.Colors.GREEN_50,
padding=10,
border_radius=8,
border=ft.Border.all(1, ft.Colors.GREEN_200),
ink=True
)
)
return controls
def on_save_sub_click(self, e):
if not self.sub_name.value or not self.payment_dropdown.value or not self.months_dropdown.value:
self.sub_error_text.value = "Toate campurile sunt obligatorii!"
self.sub_error_text.update()
return
payload = {
"name": self.sub_name.value,
"pay_and_subs_id": int(self.payment_dropdown.value),
"mounts": int(self.months_dropdown.value)
}
if self.selected_sub_id:
url = f"{self.base_url}/subscriptions/update/{self.selected_sub_id}"
response = requests.put(url, json=payload, headers={'Authorization': f'Bearer {self.token}'})
else:
url = f"{self.base_url}/subscriptions/add"
response = requests.post(url, json=payload, headers={'Authorization': f'Bearer {self.token}'})
if response.status_code in [200, 201]:
self.page.pop_dialog()
self.get_subscriptions()
else:
self.sub_error_text.value = "Eroare la salvare abonament"
self.sub_error_text.update()
def on_cancel_btn_click(self, e):
self.page.pop_dialog()
def build(self):
return ft.Container(
content=ft.Row(
[
# Coloana Stanga: Plati
ft.Column(
[
ft.Row([
ft.Text("Configurare Plati", size=18, weight=ft.FontWeight.BOLD),
ft.IconButton(ft.Icons.ADD_CIRCLE, on_click=self.add_new_payment_btn_click, icon_color=ft.Colors.BLUE)
], alignment=ft.MainAxisAlignment.SPACE_BETWEEN),
ft.Divider(),
self.payments_list
],
expand=1
),
ft.VerticalDivider(width=1),
# Coloana Dreapta: Abonamente
ft.Column(
[
ft.Row([
ft.Text("Gestiune Abonamente", size=18, weight=ft.FontWeight.BOLD),
ft.IconButton(ft.Icons.ADD_TASK, on_click=self.add_new_sub_btn_click, icon_color=ft.Colors.GREEN)
], alignment=ft.MainAxisAlignment.SPACE_BETWEEN),
ft.Divider(),
self.subs_list
],
expand=1
)
],
expand=True
),
expand=True,
padding=20
)