351 lines
13 KiB
Python
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
|
|
) |