Compare commits
23 Commits
47a76933e2
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 5f6d41a871 | |||
| 4aa36bb5b2 | |||
| f05401c493 | |||
| 29cf5925cc | |||
| 574c1227c1 | |||
| b77aa0f0d7 | |||
| d29b5e9015 | |||
| c54b7bfe78 | |||
| 800a5ea258 | |||
| 43a318a1b1 | |||
| 6c713171ed | |||
| 5a40af5434 | |||
| 8a2bad78fa | |||
| 025236013f | |||
| 4fe190ddad | |||
| ee4913487a | |||
| 14c827af40 | |||
| 17e859bfd0 | |||
| 62675c4df7 | |||
| 9e08497300 | |||
| d1b9855d9c | |||
| d598eaa134 | |||
| deef3a5c0f |
10
UI_V2/.env
10
UI_V2/.env
@@ -1,3 +1,7 @@
|
|||||||
SUPERUSER_EMAIL=macamete.robert@gmail.com
|
NETOPIA_API_KEY=yPYOnzSeU_qdMV5RaMEwvFCkBuQU6PUPijAWja8vY34JuG5SMTLtF7LkcXj8
|
||||||
SUPERUSER_PASSWORD=Inteligent1_eu
|
NETOPIA_POS_SIGNATURE=351D-XRIS-7K5Y-WUZB-Y3IW
|
||||||
SUPERUSER_ROLE=admin
|
NETOPIA_PUBLIC_KEY=-----BEGIN CERTIFICATE-----\nMIIC3zCCAkigAwIBAgIBATANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCUk8xEjAQBgNVBAgTCUJ1Y2hhcmVzdDESMBAGA1UEBxMJQnVjaGFyZXN0MRAwDgYDVQQKEwdORVRPUElBMSEwHwYDVQQLExhORVRPUElBIERldmVsb3BtZW50IHRlYW0xHDAaBgNVBAMTE25ldG9waWEtcGF5bWVudHMucm8wHhcNMjUxMTA0MTUwNTI2WhcNMzUxMTAyMTUwNTI2WjCBiDELMAkGA1UEBhMCUk8xEjAQBgNVBAgTCUJ1Y2hhcmVzdDESMBAGA1UEBxMJQnVjaGFyZXN0MRAwDgYDVQQKEwdORVRPUElBMSEwHwYDVQQLExhORVRPUElBIERldmVsb3BtZW50IHRlYW0xHDAaBgNVBAMTE25ldG9waWEtcGF5bWVudHMucm8wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALwh0/NhEpZFuKvghZ9N75CXba05MWNCh422kcfFKbqP5YViCUBg3Mc5ZYd1e0Xi9Ui1QI2Z/jvvchrDZGQwjarApr3S9bowHEkZH81ZolOoPHBZbYpA28BIyHYRcaTXjLtiBGvjpwuzljmXeBoVLinIaE0IUpMen9MLWG2fGMddAgMBAAGjVzBVMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQ9yXChMGxzUzQflmkXT1oyIBoetTANBgkqhkiG9w0BAQsFAAOBgQCSxX3hnoP+vWmdecz/Oustubp4Q89fV/bGMBztQy8QbnMjKghUKAba/0CGs2MbN2bWCN78mOak8Oi6qNB7/Z6/yKWTJdkwYjXl/C6UQhZ7k11XKINGk3LD9wTiyKsWt1iioNjNN6h8Fqeh4So5ikEzZG7LnvbAz+ct9YBjyHiCLw==\n-----END CERTIFICATE-----
|
||||||
|
NETOPIA_REDIRECT_URL=https://www.tainagustului.ro/payment/redirect
|
||||||
|
NETOPIA_NOTIFY_URL=https://www.tainagustului.ro/api/payments/ipn
|
||||||
|
NETOPIA_CANCEL_URL=https://www.tainagustului.ro/cos
|
||||||
|
NETOPIA_IS_LIVE=false
|
||||||
@@ -8,10 +8,19 @@ class Clients:
|
|||||||
self.user_manager = Users()
|
self.user_manager = Users()
|
||||||
self.company_manager = Company()
|
self.company_manager = Company()
|
||||||
|
|
||||||
self.user_name = ft.TextField(label="Nume si Prenume")
|
self.first_name = ft.TextField(label="Prenume")
|
||||||
|
self.last_name = ft.TextField(label="Nume")
|
||||||
self.email = ft.TextField(label="E-mail")
|
self.email = ft.TextField(label="E-mail")
|
||||||
self.phone = ft.TextField(label="Telefon")
|
self.phone = ft.TextField(label="Telefon")
|
||||||
self.address = ft.TextField(label="Adresa", multiline=True, min_lines=3, max_lines=5)
|
self.address = ft.TextField(
|
||||||
|
label="Strada si numar",
|
||||||
|
multiline=True,
|
||||||
|
min_lines=3,
|
||||||
|
max_lines=5
|
||||||
|
)
|
||||||
|
self.city = ft.TextField(
|
||||||
|
label="Oras"
|
||||||
|
)
|
||||||
self.company_name = ft.TextField(label="Denumire firma")
|
self.company_name = ft.TextField(label="Denumire firma")
|
||||||
self.vat = ft.TextField(label="CUI")
|
self.vat = ft.TextField(label="CUI")
|
||||||
self.register_number = ft.TextField(label="Numar registru comert")
|
self.register_number = ft.TextField(label="Numar registru comert")
|
||||||
@@ -27,10 +36,12 @@ class Clients:
|
|||||||
|
|
||||||
self.client_column = ft.Column(
|
self.client_column = ft.Column(
|
||||||
[
|
[
|
||||||
self.user_name,
|
self.first_name,
|
||||||
|
self.last_name,
|
||||||
self.email,
|
self.email,
|
||||||
self.phone,
|
self.phone,
|
||||||
self.address,
|
self.address,
|
||||||
|
self.city,
|
||||||
ft.Button("Persoana Juridica?", on_click=self.on_is_comopany_btn_click),
|
ft.Button("Persoana Juridica?", on_click=self.on_is_comopany_btn_click),
|
||||||
self.company_placeholder,
|
self.company_placeholder,
|
||||||
ft.Button("Adresa de livrare difera de adresa de domiciliu?", on_click=self.on_second_address),
|
ft.Button("Adresa de livrare difera de adresa de domiciliu?", on_click=self.on_second_address),
|
||||||
@@ -130,12 +141,37 @@ class Clients:
|
|||||||
self.view_second_address_placeholder.controls.clear()
|
self.view_second_address_placeholder.controls.clear()
|
||||||
|
|
||||||
def on_edit_btn_click(self, item):
|
def on_edit_btn_click(self, item):
|
||||||
|
print(item)
|
||||||
self.edit_id = item['id']
|
self.edit_id = item['id']
|
||||||
self.user_name.value = item['name']
|
prenume = ''
|
||||||
|
if '~' in item['name']:
|
||||||
|
prenume = item['name'].split('~')[0]
|
||||||
|
self.first_name.value=prenume
|
||||||
|
|
||||||
|
nume = ''
|
||||||
|
if '~' in item['name']:
|
||||||
|
nume = item['name'].split('~')[1]
|
||||||
|
self.last_name.value=nume
|
||||||
|
|
||||||
|
address = ''
|
||||||
|
if item['address']:
|
||||||
|
if "~" in item['address']:
|
||||||
|
address = item['address'].split("~")[0].split("%")[1]
|
||||||
|
else:
|
||||||
|
address = item['address'].split("%")[1]
|
||||||
|
self.address.value = address
|
||||||
|
|
||||||
|
city = ''
|
||||||
|
if item['address']:
|
||||||
|
if "~" in item['address']:
|
||||||
|
city = item['address'].split("~")[0].split("%")[0]
|
||||||
|
else:
|
||||||
|
city = item['address'].split("%")[0]
|
||||||
|
self.city.value = city
|
||||||
|
|
||||||
self.email.value = item['email']
|
self.email.value = item['email']
|
||||||
self.email.disabled = True
|
self.email.disabled = True
|
||||||
self.phone.value = item['phone']
|
self.phone.value = item['phone']
|
||||||
self.address.value = item['address'].split("~")[0]
|
|
||||||
company = self.company_manager.get_company(item['id'])
|
company = self.company_manager.get_company(item['id'])
|
||||||
if company:
|
if company:
|
||||||
self.company_name.value = company['name']
|
self.company_name.value = company['name']
|
||||||
@@ -168,10 +204,10 @@ class Clients:
|
|||||||
self.page.close(self.confirm_delete_alert)
|
self.page.close(self.confirm_delete_alert)
|
||||||
|
|
||||||
def on_view_btn_click(self, item):
|
def on_view_btn_click(self, item):
|
||||||
self.view_name.value = f"Nume: {item['name']}"
|
self.view_name.value = f"Nume: {item['name'].replace("~", " ")}"
|
||||||
self.view_email.value = f"E-mail: {item['email']}"
|
self.view_email.value = f"E-mail: {item['email']}"
|
||||||
self.view_phone.value = f"Telefon: {item['phone']}"
|
self.view_phone.value = f"Telefon: {item['phone']}"
|
||||||
self.view_address.value = f"Adresa: {item['address'].split("~")[0]}"
|
self.view_address.value = f"Adresa: {item['address'].split("~")[0].replace("%", ", ")}"
|
||||||
company = self.company_manager.get_company(item['id'])
|
company = self.company_manager.get_company(item['id'])
|
||||||
if company:
|
if company:
|
||||||
self.view_company_placeholder.controls.append(ft.Text(""))
|
self.view_company_placeholder.controls.append(ft.Text(""))
|
||||||
@@ -200,7 +236,7 @@ class Clients:
|
|||||||
|
|
||||||
ft.Column(
|
ft.Column(
|
||||||
[
|
[
|
||||||
ft.Text(value=item['name'], weight=ft.FontWeight.BOLD),
|
ft.Text(value=item['name'].replace("~", " "), weight=ft.FontWeight.BOLD),
|
||||||
ft.Text(value=item['email'], size=12)
|
ft.Text(value=item['email'], size=12)
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
@@ -236,7 +272,7 @@ class Clients:
|
|||||||
]
|
]
|
||||||
|
|
||||||
def on_save_btn_click(self, e):
|
def on_save_btn_click(self, e):
|
||||||
user_name = self.user_name.value
|
user_name = self.first_name.value + "~" + self.last_name.value
|
||||||
user_email = self.email.value
|
user_email = self.email.value
|
||||||
user_phone = self.phone.value
|
user_phone = self.phone.value
|
||||||
user_address = self.address.value
|
user_address = self.address.value
|
||||||
@@ -279,8 +315,10 @@ class Clients:
|
|||||||
self.clear_fileds()
|
self.clear_fileds()
|
||||||
|
|
||||||
def clear_fileds(self):
|
def clear_fileds(self):
|
||||||
self.user_name.value = ''
|
self.first_name.value = ''
|
||||||
self.user_name.update()
|
self.first_name.update()
|
||||||
|
self.last_name.value = ''
|
||||||
|
self.last_name.update()
|
||||||
self.email.value = ''
|
self.email.value = ''
|
||||||
self.email.update()
|
self.email.update()
|
||||||
self.phone.value = ''
|
self.phone.value = ''
|
||||||
|
|||||||
80
UI_V2/admin/company_data.py
Normal file
80
UI_V2/admin/company_data.py
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
import flet as ft
|
||||||
|
import json
|
||||||
|
|
||||||
|
class CompanyData:
|
||||||
|
def __init__(self, page: ft.Page):
|
||||||
|
self.page = page
|
||||||
|
self.data =self.load_data()
|
||||||
|
self.comapny_name = ft.TextField(label = "Denumire firma:", value=self.data['company_name'] if self.data else '')
|
||||||
|
self.vat = ft.TextField(label="CUI", value=self.data['vat'] if self.data else '')
|
||||||
|
self.register_number = ft.TextField(label="Numar registru comert", value=self.data['register_number'] if self.data else '')
|
||||||
|
self.company_address = ft.TextField(label="Sediu", value=self.data['address'] if self.data else '')
|
||||||
|
self.error_mseeage = ft.Text("")
|
||||||
|
|
||||||
|
def on_save_btn_click(self, e):
|
||||||
|
|
||||||
|
data = {
|
||||||
|
'company_name': self.comapny_name.value,
|
||||||
|
'vat': self.vat.value,
|
||||||
|
'register_number': self.register_number.value,
|
||||||
|
'address': self.company_address.value
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open('instance/company_data.json', 'w', encoding='utf-8') as f:
|
||||||
|
json.dump(data, f, ensure_ascii=False, indent=4)
|
||||||
|
|
||||||
|
self.page.snack_bar = ft.SnackBar(ft.Text('Datele companiei au fost salvate cu succes!'))
|
||||||
|
self.page.snack_bar.open = True
|
||||||
|
self.page.update()
|
||||||
|
self.error_mseeage.value = "Datele au fost salvate cu succes!"
|
||||||
|
self.error_mseeage.update()
|
||||||
|
except Exception as ex:
|
||||||
|
self.page.snack_bar = ft.SnackBar(ft.Text(f'Eroare la salvare: {ex}'))
|
||||||
|
self.page.snack_bar.open = True
|
||||||
|
self.page.update()
|
||||||
|
|
||||||
|
def load_data(self):
|
||||||
|
try:
|
||||||
|
with open('instance/company_data.json', 'r', encoding='utf-8') as f:
|
||||||
|
data = json.load(f)
|
||||||
|
return data
|
||||||
|
except FileNotFoundError:
|
||||||
|
return {
|
||||||
|
'company_name': '',
|
||||||
|
'vat': '',
|
||||||
|
'register_number': '',
|
||||||
|
'address': ''
|
||||||
|
}
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
self.page.snack_bar = ft.SnackBar(ft.Text('Eroare: fișierul company_data.json este corupt.'))
|
||||||
|
self.page.snack_bar.open = True
|
||||||
|
self.page.update()
|
||||||
|
return None
|
||||||
|
except Exception as ex:
|
||||||
|
self.page.snack_bar = ft.SnackBar(ft.Text(f'Eroare la citirea datelor companiei: {ex}'))
|
||||||
|
self.page.snack_bar.open = True
|
||||||
|
self.page.update()
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def build(self):
|
||||||
|
return ft.Container(
|
||||||
|
content=ft.Column(
|
||||||
|
[
|
||||||
|
ft.Text("Despre noi:", size=18, weight=ft.FontWeight.BOLD),
|
||||||
|
self.comapny_name,
|
||||||
|
self.vat,
|
||||||
|
self.register_number,
|
||||||
|
self.company_address,
|
||||||
|
ft.Text(),
|
||||||
|
ft.Row(
|
||||||
|
[
|
||||||
|
ft.FilledButton("Salveaza", icon=ft.Icons.SAVE, on_click=self.on_save_btn_click)
|
||||||
|
],
|
||||||
|
alignment=ft.MainAxisAlignment.CENTER
|
||||||
|
)
|
||||||
|
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
117
UI_V2/admin/company_details.py
Normal file
117
UI_V2/admin/company_details.py
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
import flet as ft
|
||||||
|
import json
|
||||||
|
|
||||||
|
class CompanyDetails:
|
||||||
|
def __init__(self, page: ft.Page):
|
||||||
|
self.page = page
|
||||||
|
self.data = self.load_data()
|
||||||
|
self.confidentialty_policy = ft.TextField(
|
||||||
|
multiline=True,
|
||||||
|
min_lines=5,
|
||||||
|
max_lines=10,
|
||||||
|
value=self.data['confidentialty_policy'] if self.data else ''
|
||||||
|
)
|
||||||
|
self.delivery_policy = ft.TextField(
|
||||||
|
multiline=True,
|
||||||
|
min_lines=5,
|
||||||
|
max_lines=10,
|
||||||
|
value=self.data['delivery_policy'] if self.data else ''
|
||||||
|
)
|
||||||
|
self.cancel_policy = ft.TextField(
|
||||||
|
multiline=True,
|
||||||
|
min_lines=5,
|
||||||
|
max_lines=10,
|
||||||
|
value=self.data['cancel_policy'] if self.data else ''
|
||||||
|
)
|
||||||
|
self.gdpr = ft.TextField(
|
||||||
|
multiline=True,
|
||||||
|
min_lines=5,
|
||||||
|
max_lines=10,
|
||||||
|
value=self.data['gdpr'] if self.data else ''
|
||||||
|
)
|
||||||
|
self.terms_and_conditions = ft.TextField(
|
||||||
|
multiline=True,
|
||||||
|
min_lines=5,
|
||||||
|
max_lines=10,
|
||||||
|
value=self.data['terms_and_conditions'] if self.data else ''
|
||||||
|
)
|
||||||
|
self.error_mseeage = ft.Text("")
|
||||||
|
|
||||||
|
def on_save_btn_click(self, e):
|
||||||
|
policies = {
|
||||||
|
'confidentialty_policy': self.confidentialty_policy.value,
|
||||||
|
'delivery_policy': self.delivery_policy.value,
|
||||||
|
'cancel_policy': self.cancel_policy.value,
|
||||||
|
'gdpr': self.gdpr.value,
|
||||||
|
'terms_and_conditions': self.terms_and_conditions.value
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open('instance/policies.json', 'w', encoding='utf-8') as f:
|
||||||
|
json.dump(policies, f, ensure_ascii=False, indent=4)
|
||||||
|
|
||||||
|
self.page.snack_bar = ft.SnackBar(ft.Text('Politicile au fost salvate cu succes!'))
|
||||||
|
self.page.snack_bar.open = True
|
||||||
|
self.page.update()
|
||||||
|
self.error_mseeage.value = "Datele au fost salvate cu succes!"
|
||||||
|
self.error_mseeage.update()
|
||||||
|
except Exception as ex:
|
||||||
|
self.page.snack_bar = ft.SnackBar(ft.Text(f'Eroare la salvare: {ex}'))
|
||||||
|
self.page.snack_bar.open = True
|
||||||
|
self.page.update()
|
||||||
|
|
||||||
|
def load_data(self):
|
||||||
|
try:
|
||||||
|
with open('instance/policies.json', 'r', encoding='utf-8') as f:
|
||||||
|
data = json.load(f)
|
||||||
|
return data
|
||||||
|
except FileNotFoundError:
|
||||||
|
return {
|
||||||
|
'confidentialty_policy': '',
|
||||||
|
'delivery_policy': '',
|
||||||
|
'cancel_policy': '',
|
||||||
|
'gdpr': '',
|
||||||
|
'terms_and_conditions': ''
|
||||||
|
}
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
self.page.snack_bar = ft.SnackBar(ft.Text('Eroare: fișierul policies.json este corupt.'))
|
||||||
|
self.page.snack_bar.open = True
|
||||||
|
self.page.update()
|
||||||
|
return None
|
||||||
|
except Exception as ex:
|
||||||
|
self.page.snack_bar = ft.SnackBar(ft.Text(f'Eroare la citirea politicilor: {ex}'))
|
||||||
|
self.page.snack_bar.open = True
|
||||||
|
self.page.update()
|
||||||
|
return None
|
||||||
|
|
||||||
|
def build(self):
|
||||||
|
return ft.Container(
|
||||||
|
content=ft.Column(
|
||||||
|
[
|
||||||
|
ft.Text("Politica de confidențialitate", size=18, weight=ft.FontWeight.BOLD),
|
||||||
|
self.confidentialty_policy,
|
||||||
|
ft.Divider(height=1),
|
||||||
|
ft.Text("Politica de livrare comandă", size=18, weight=ft.FontWeight.BOLD),
|
||||||
|
self.delivery_policy,
|
||||||
|
ft.Divider(height=1),
|
||||||
|
ft.Text("Politica de anulare comandă", size=18, weight=ft.FontWeight.BOLD),
|
||||||
|
self.cancel_policy,
|
||||||
|
ft.Divider(height=1),
|
||||||
|
ft.Text("Politica GDPR (siguranța datelor cu caracter personal)", size=18, weight=ft.FontWeight.BOLD),
|
||||||
|
self.gdpr,
|
||||||
|
ft.Divider(height=1),
|
||||||
|
ft.Text("Termeni și condiții", size=18, weight=ft.FontWeight.BOLD),
|
||||||
|
self.terms_and_conditions,
|
||||||
|
ft.Text(),
|
||||||
|
self.error_mseeage,
|
||||||
|
ft.Row(
|
||||||
|
[
|
||||||
|
ft.FilledButton("Salveaza", icon = ft.Icons.SAVE, on_click=self.on_save_btn_click)
|
||||||
|
],
|
||||||
|
alignment=ft.MainAxisAlignment.CENTER
|
||||||
|
)
|
||||||
|
|
||||||
|
],
|
||||||
|
scroll=ft.ScrollMode.ADAPTIVE
|
||||||
|
)
|
||||||
|
)
|
||||||
@@ -4,6 +4,9 @@ from admin.products import ProductsPage
|
|||||||
from admin.banner import Banner
|
from admin.banner import Banner
|
||||||
from admin.orders import OrdersPage
|
from admin.orders import OrdersPage
|
||||||
from admin.clients import Clients
|
from admin.clients import Clients
|
||||||
|
from admin.fidelity_cards import FidelityCards
|
||||||
|
from admin.settings import Settings
|
||||||
|
from admin.inventory.inventory import Inventory
|
||||||
|
|
||||||
class Dashboard:
|
class Dashboard:
|
||||||
def __init__(self, page: ft.Page):
|
def __init__(self, page: ft.Page):
|
||||||
@@ -52,6 +55,21 @@ class Dashboard:
|
|||||||
selected_icon=ft.Icon(ft.Icons.IMAGE_ROUNDED),
|
selected_icon=ft.Icon(ft.Icons.IMAGE_ROUNDED),
|
||||||
label_content=ft.Text("Banner"),
|
label_content=ft.Text("Banner"),
|
||||||
),
|
),
|
||||||
|
ft.NavigationRailDestination(
|
||||||
|
icon=ft.Icons.CARD_GIFTCARD_OUTLINED,
|
||||||
|
selected_icon=ft.Icon(ft.Icons.CARD_GIFTCARD),
|
||||||
|
label_content=ft.Text("Card de\nfidelitate"),
|
||||||
|
),
|
||||||
|
ft.NavigationRailDestination(
|
||||||
|
icon=ft.Icons.INVENTORY_2_OUTLINED,
|
||||||
|
selected_icon=ft.Icon(ft.Icons.INVENTORY_2),
|
||||||
|
label_content=ft.Text("Inventar"),
|
||||||
|
),
|
||||||
|
ft.NavigationRailDestination(
|
||||||
|
icon=ft.Icons.SETTINGS_APPLICATIONS_OUTLINED,
|
||||||
|
selected_icon=ft.Icon(ft.Icons.SETTINGS_APPLICATIONS),
|
||||||
|
label_content=ft.Text("Setari"),
|
||||||
|
),
|
||||||
ft.NavigationRailDestination(
|
ft.NavigationRailDestination(
|
||||||
icon=ft.Icons.LOGOUT_OUTLINED,
|
icon=ft.Icons.LOGOUT_OUTLINED,
|
||||||
selected_icon=ft.Icon(ft.Icons.LOGOUT_ROUNDED),
|
selected_icon=ft.Icon(ft.Icons.LOGOUT_ROUNDED),
|
||||||
@@ -87,6 +105,18 @@ class Dashboard:
|
|||||||
self.placeholder.content = self.banner.build()
|
self.placeholder.content = self.banner.build()
|
||||||
self.placeholder.update()
|
self.placeholder.update()
|
||||||
case 6:
|
case 6:
|
||||||
|
self.fidelity_cards = FidelityCards(self.page)
|
||||||
|
self.placeholder.content = self.fidelity_cards.build()
|
||||||
|
self.placeholder.update()
|
||||||
|
case 7:
|
||||||
|
self.inventory = Inventory(self.page, self)
|
||||||
|
self.placeholder.content = self.inventory.build()
|
||||||
|
self.placeholder.update()
|
||||||
|
case 8:
|
||||||
|
self.settings = Settings(self.page, self)
|
||||||
|
self.placeholder.content = self.settings.build()
|
||||||
|
self.placeholder.update()
|
||||||
|
case 9:
|
||||||
self.page.client_storage.clear()
|
self.page.client_storage.clear()
|
||||||
self.page.session.clear()
|
self.page.session.clear()
|
||||||
self.page.go('/')
|
self.page.go('/')
|
||||||
|
|||||||
230
UI_V2/admin/fidelity_cards.py
Normal file
230
UI_V2/admin/fidelity_cards.py
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
import flet as ft
|
||||||
|
from dbActions.fidelity_cards import FidelityCards as FC
|
||||||
|
|
||||||
|
class FidelityCards:
|
||||||
|
def __init__(self, page: ft.Page):
|
||||||
|
self.page = page
|
||||||
|
self.fidelity_cards_manager = FC()
|
||||||
|
|
||||||
|
self.all_cards = self.fidelity_cards_manager.get_all_fidelity_cards()
|
||||||
|
self.list_of_cars = ft.ListView(
|
||||||
|
controls=self.create_list(self.all_cards, self.on_delete_btn_click, self.on_edit_btn_click),
|
||||||
|
expand=True,
|
||||||
|
spacing=10
|
||||||
|
)
|
||||||
|
|
||||||
|
self.search_bar = ft.TextField(label = "Cauta dupa numar de telefon", on_submit=self.on_search_btn_click, expand=True)
|
||||||
|
self.search_btn = ft.IconButton(icon=ft.Icons.SEARCH, on_click=self.on_search_btn_click)
|
||||||
|
|
||||||
|
self.card_id = ft.TextField(label="Id card")
|
||||||
|
self.card_type = ft.Dropdown(
|
||||||
|
label='Reducere (%)',
|
||||||
|
options=[
|
||||||
|
ft.dropdown.Option(key='10', text="10%"),
|
||||||
|
ft.dropdown.Option(key='20', text="20%"),
|
||||||
|
ft.dropdown.Option(key='30', text="30%"),
|
||||||
|
],
|
||||||
|
expand=True
|
||||||
|
)
|
||||||
|
self.client_name = ft.TextField(label="Nume client")
|
||||||
|
self.phone_number = ft.TextField(label="Numar telefon")
|
||||||
|
|
||||||
|
self.item_to_be_edit = None
|
||||||
|
self.add_dialog = ft.AlertDialog(
|
||||||
|
title=ft.Text(value = "Adauga card de fidelitate" if self.item_to_be_edit == None else "Actualizeaza card de fidelitate"),
|
||||||
|
content=ft.Column(
|
||||||
|
[
|
||||||
|
self.card_id,
|
||||||
|
self.card_type,
|
||||||
|
self.client_name,
|
||||||
|
self.phone_number
|
||||||
|
],
|
||||||
|
height=250,
|
||||||
|
width=400
|
||||||
|
),
|
||||||
|
actions = [
|
||||||
|
ft.Button("Salveaza", on_click=self.on_save_btn_click, icon=ft.Icons.SAVE),
|
||||||
|
ft.TextButton("Anuleaza", on_click=self.on_cancel_btn_click, icon=ft.Icons.CANCEL)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
self.delete_dialog = ft.AlertDialog(
|
||||||
|
title=ft.Text("Setergeti cardul?"),
|
||||||
|
actions = [
|
||||||
|
ft.Button("Da", on_click=self.on_condifm_delete_btn_click, icon=ft.Icons.DELETE),
|
||||||
|
ft.TextButton("Nu", on_click=self.on_cancel_delete_btn_click, icon=ft.Icons.CANCEL)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
self.item_to_be_delete = None
|
||||||
|
|
||||||
|
|
||||||
|
def on_condifm_delete_btn_click(self, e):
|
||||||
|
self.fidelity_cards_manager.remove_fidelity_card(self.item_to_be_delete)
|
||||||
|
self.page.close(self.delete_dialog)
|
||||||
|
self.update_list()
|
||||||
|
self.item_to_be_delete = None
|
||||||
|
|
||||||
|
def on_cancel_delete_btn_click(self, e):
|
||||||
|
self.page.close(self.delete_dialog)
|
||||||
|
self.item_to_be_delete = None
|
||||||
|
|
||||||
|
def on_save_btn_click(self, e):
|
||||||
|
card_id = self.card_id.value
|
||||||
|
card_type = self.card_type.value
|
||||||
|
client_name = self.client_name.value
|
||||||
|
phone_number = self.phone_number.value
|
||||||
|
|
||||||
|
if self.item_to_be_edit == None:
|
||||||
|
self.fidelity_cards_manager.add_fidelity_card(
|
||||||
|
card_id,
|
||||||
|
card_type,
|
||||||
|
client_name,
|
||||||
|
phone_number
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.fidelity_cards_manager.update_card(
|
||||||
|
self.item_to_be_edit,
|
||||||
|
card_id,
|
||||||
|
card_type,
|
||||||
|
client_name,
|
||||||
|
phone_number
|
||||||
|
)
|
||||||
|
self.item_to_be_edit = None
|
||||||
|
|
||||||
|
#set to defualt
|
||||||
|
self.card_id.value = ''
|
||||||
|
self.card_id.update()
|
||||||
|
self.card_type.value = ''
|
||||||
|
self.card_type.update()
|
||||||
|
self.client_name.value = ''
|
||||||
|
self.client_name.update()
|
||||||
|
self.phone_number.value = ''
|
||||||
|
self.phone_number.update()
|
||||||
|
|
||||||
|
#close popup
|
||||||
|
self.page.close(self.add_dialog)
|
||||||
|
|
||||||
|
#update_list
|
||||||
|
self.update_list()
|
||||||
|
|
||||||
|
def update_list(self):
|
||||||
|
self.all_cards = self.fidelity_cards_manager.get_all_fidelity_cards()
|
||||||
|
self.list_of_cars.controls = self.create_list(
|
||||||
|
self.all_cards,
|
||||||
|
self.on_delete_btn_click,
|
||||||
|
self.on_edit_btn_click
|
||||||
|
)
|
||||||
|
self.list_of_cars.update()
|
||||||
|
|
||||||
|
def on_cancel_btn_click(self, e):
|
||||||
|
self.page.close(self.add_dialog)
|
||||||
|
self.item_to_be_edit = None
|
||||||
|
|
||||||
|
def on_add_btn_click(self, e):
|
||||||
|
self.page.open(self.add_dialog)
|
||||||
|
|
||||||
|
def create_list(self, items, on_click_handler2, on_click_handler3):
|
||||||
|
return [
|
||||||
|
ft.Container(
|
||||||
|
content=ft.Row(
|
||||||
|
[
|
||||||
|
|
||||||
|
ft.Column(
|
||||||
|
[
|
||||||
|
ft.Text(value=f"Nume: {item['client_name']}", weight=ft.FontWeight.BOLD),
|
||||||
|
ft.Row(
|
||||||
|
[
|
||||||
|
ft.Text(value=f"Id card: {item['card_id']};", size=12),
|
||||||
|
ft.Text(value=f"Reducere: {item['card_type']}%;", size=12),
|
||||||
|
ft.Text(value=f"Telefon: {item['phone_number']}", size=12)
|
||||||
|
],
|
||||||
|
spacing=10
|
||||||
|
)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
|
||||||
|
ft.Row(
|
||||||
|
[
|
||||||
|
ft.IconButton(
|
||||||
|
icon=ft.Icons.EDIT,
|
||||||
|
on_click=lambda e, id=item: on_click_handler3(id),
|
||||||
|
),
|
||||||
|
ft.IconButton(
|
||||||
|
icon=ft.Icons.DELETE,
|
||||||
|
on_click=lambda e, id=item['id']: on_click_handler2(id),
|
||||||
|
icon_color=ft.Colors.RED,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
],
|
||||||
|
alignment=ft.MainAxisAlignment.SPACE_BETWEEN,
|
||||||
|
),
|
||||||
|
width=300,
|
||||||
|
bgcolor=ft.Colors.BROWN_50,
|
||||||
|
border = ft.border.all(1, ft.Colors.GREY),
|
||||||
|
padding=10,
|
||||||
|
border_radius=8,
|
||||||
|
)
|
||||||
|
for item in items
|
||||||
|
]
|
||||||
|
|
||||||
|
def on_search_btn_click(self, e):
|
||||||
|
print(self.search_bar.value)
|
||||||
|
|
||||||
|
for card in self.all_cards:
|
||||||
|
buffer = []
|
||||||
|
if self.search_bar.value in card['phone_number']:
|
||||||
|
buffer.append(card)
|
||||||
|
self.list_of_cars.controls = self.create_list(
|
||||||
|
buffer,
|
||||||
|
self.on_delete_btn_click,
|
||||||
|
self.on_edit_btn_click
|
||||||
|
)
|
||||||
|
self.list_of_cars.update()
|
||||||
|
|
||||||
|
#set to default
|
||||||
|
self.search_bar.value = ''
|
||||||
|
self.search_bar.update()
|
||||||
|
|
||||||
|
def on_delete_btn_click(self, id):
|
||||||
|
self.item_to_be_delete = id
|
||||||
|
self.page.open(self.delete_dialog)
|
||||||
|
|
||||||
|
def on_edit_btn_click(self, item):
|
||||||
|
self.page.open(self.add_dialog)
|
||||||
|
self.item_to_be_edit = item['id']
|
||||||
|
self.card_id.value = item['card_id']
|
||||||
|
self.card_id.update()
|
||||||
|
self.card_type.value = item['card_type']
|
||||||
|
self.card_type.update()
|
||||||
|
self.client_name.value = item['client_name']
|
||||||
|
self.client_name.update()
|
||||||
|
self.phone_number.value = item['phone_number']
|
||||||
|
self.phone_number.update()
|
||||||
|
|
||||||
|
def build(self):
|
||||||
|
return ft.Container(
|
||||||
|
content=ft.Column(
|
||||||
|
[
|
||||||
|
ft.Row(
|
||||||
|
[
|
||||||
|
ft.Text("Card de fidelitate", size=18, weight=ft.FontWeight.BOLD),
|
||||||
|
ft.Button("Adauga", icon=ft.Icons.ADD, on_click=self.on_add_btn_click),
|
||||||
|
],
|
||||||
|
alignment=ft.MainAxisAlignment.SPACE_BETWEEN
|
||||||
|
),
|
||||||
|
ft.Row(
|
||||||
|
[
|
||||||
|
self.search_bar,
|
||||||
|
self.search_btn
|
||||||
|
]
|
||||||
|
),
|
||||||
|
self.list_of_cars
|
||||||
|
],
|
||||||
|
alignment=ft.MainAxisAlignment.START,
|
||||||
|
expand=True
|
||||||
|
),
|
||||||
|
expand=True
|
||||||
|
)
|
||||||
Binary file not shown.
BIN
UI_V2/admin/inventory/__pycache__/inventory.cpython-313.pyc
Normal file
BIN
UI_V2/admin/inventory/__pycache__/inventory.cpython-313.pyc
Normal file
Binary file not shown.
BIN
UI_V2/admin/inventory/__pycache__/providers.cpython-313.pyc
Normal file
BIN
UI_V2/admin/inventory/__pycache__/providers.cpython-313.pyc
Normal file
Binary file not shown.
0
UI_V2/admin/inventory/consumption.py
Normal file
0
UI_V2/admin/inventory/consumption.py
Normal file
25
UI_V2/admin/inventory/goods_reception.py
Normal file
25
UI_V2/admin/inventory/goods_reception.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import flet as ft
|
||||||
|
|
||||||
|
class GoodsReception:
|
||||||
|
def __init__(self, page: ft.Page, dashboard, inventory):
|
||||||
|
self.page = page
|
||||||
|
self.dashboard = dashboard
|
||||||
|
self.inventory = inventory
|
||||||
|
|
||||||
|
def on_add_btn_click(self, e):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def build(self):
|
||||||
|
return ft.Container(
|
||||||
|
ft.Column(
|
||||||
|
[
|
||||||
|
ft.Row(
|
||||||
|
[
|
||||||
|
ft.Text("Receptie Marfa", weight=ft.FontWeight.BOLD, size=18),
|
||||||
|
ft.Button("Adauga", icon=ft.Icons.ADD, on_click=self.on_add_btn_click)
|
||||||
|
],
|
||||||
|
alignment=ft.MainAxisAlignment.SPACE_BETWEEN
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
64
UI_V2/admin/inventory/inventory.py
Normal file
64
UI_V2/admin/inventory/inventory.py
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import flet as ft
|
||||||
|
from dbActions.products import Products
|
||||||
|
from admin.inventory.providers import Providers
|
||||||
|
from admin.inventory.goods_reception import GoodsReception
|
||||||
|
|
||||||
|
class Inventory:
|
||||||
|
def __init__(self, page: ft.Page, dashboard):
|
||||||
|
self.page = page
|
||||||
|
self.dashboard = dashboard
|
||||||
|
self.product_manager = Products()
|
||||||
|
|
||||||
|
def on_providers_btn_click(self, e):
|
||||||
|
providers = Providers(self.page, self.dashboard, self)
|
||||||
|
self.dashboard.placeholder.content = providers.build()
|
||||||
|
self.dashboard.placeholder.update()
|
||||||
|
|
||||||
|
def on_goods_btn_click(self, e):
|
||||||
|
goods = GoodsReception(self.page, self.dashboard, self)
|
||||||
|
self.dashboard.placeholder.content = goods.build()
|
||||||
|
self.dashboard.placeholder.update()
|
||||||
|
|
||||||
|
def build(self):
|
||||||
|
return ft.Container(
|
||||||
|
content=ft.Column(
|
||||||
|
[
|
||||||
|
ft.GridView(
|
||||||
|
[
|
||||||
|
ft.Card(
|
||||||
|
content=ft.Container(
|
||||||
|
content=ft.Column(
|
||||||
|
[
|
||||||
|
ft.Icon(name=ft.Icons.FIRE_TRUCK, size=100),
|
||||||
|
ft.Text("Management Furnizori", size=16, weight=ft.FontWeight.BOLD),
|
||||||
|
ft.Button("Furnizori", icon=ft.Icons.FORWARD, on_click=self.on_providers_btn_click)
|
||||||
|
],
|
||||||
|
horizontal_alignment=ft.CrossAxisAlignment.CENTER
|
||||||
|
),
|
||||||
|
padding=10
|
||||||
|
)
|
||||||
|
),
|
||||||
|
ft.Card(
|
||||||
|
content=ft.Container(
|
||||||
|
content=ft.Column(
|
||||||
|
[
|
||||||
|
ft.Icon(name=ft.Icons.INPUT, size=100),
|
||||||
|
ft.Text("Receptie Marfa", size=16, weight=ft.FontWeight.BOLD),
|
||||||
|
ft.Button("Marfa", icon=ft.Icons.FORWARD, on_click=self.on_goods_btn_click)
|
||||||
|
],
|
||||||
|
horizontal_alignment=ft.CrossAxisAlignment.CENTER
|
||||||
|
),
|
||||||
|
padding=10
|
||||||
|
)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
spacing=10,
|
||||||
|
runs_count=4,
|
||||||
|
max_extent=250,
|
||||||
|
child_aspect_ratio=1.0,
|
||||||
|
expand=True,
|
||||||
|
width=1000
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
301
UI_V2/admin/inventory/providers.py
Normal file
301
UI_V2/admin/inventory/providers.py
Normal file
@@ -0,0 +1,301 @@
|
|||||||
|
import flet as ft
|
||||||
|
from dbActions.providers import Providers as DBProviders
|
||||||
|
|
||||||
|
class Providers:
|
||||||
|
def __init__(self, page: ft.Page, dashboard, inventory):
|
||||||
|
self.page = page
|
||||||
|
self.dashboard = dashboard
|
||||||
|
self.inventory = inventory
|
||||||
|
self.providers_manager = DBProviders()
|
||||||
|
|
||||||
|
self.provider_name = ft.TextField(label="Denumire")
|
||||||
|
self.provider_vat = ft.TextField(label="CUI")
|
||||||
|
self.provider_register_number = ft.TextField(label="Numar de inregistrare")
|
||||||
|
self.provider_address = ft.TextField(label = "Sediu")
|
||||||
|
self.contact_name = ft.TextField(label="Nume si prenume")
|
||||||
|
self.contact_number = ft.TextField(label="Telefon")
|
||||||
|
self.contact_email = ft.TextField(label="E-mail")
|
||||||
|
self.add_error_message = ft.Text("",color=ft.Colors.RED)
|
||||||
|
self.status = ft.RadioGroup(
|
||||||
|
content=ft.Row(
|
||||||
|
[
|
||||||
|
ft.Radio(value="Activ", label="Activ"),
|
||||||
|
ft.Radio(value="Inactiv", label="Inactiv"),
|
||||||
|
],
|
||||||
|
alignment=ft.MainAxisAlignment.START
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.status_group = ft.Row(
|
||||||
|
[
|
||||||
|
ft.Text("Status: ", weight=ft.FontWeight.BOLD),
|
||||||
|
self.status
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
self.add_dialog = ft.AlertDialog(
|
||||||
|
title=ft.Text("Adauga furnizor"),
|
||||||
|
content=ft.Column(
|
||||||
|
[
|
||||||
|
ft.Text("Furnizor", size=16, weight=ft.FontWeight.BOLD),
|
||||||
|
self.provider_name,
|
||||||
|
self.provider_vat,
|
||||||
|
self.provider_register_number,
|
||||||
|
self.provider_address,
|
||||||
|
ft.Text("Persoana de contact", size=16, weight=ft.FontWeight.BOLD),
|
||||||
|
self.contact_name,
|
||||||
|
self.contact_number,
|
||||||
|
self.contact_email,
|
||||||
|
self.add_error_message
|
||||||
|
],
|
||||||
|
width=400,
|
||||||
|
height=500
|
||||||
|
),
|
||||||
|
actions=[
|
||||||
|
ft.FilledButton("Salveaza", on_click=self.on_save_btn_click),
|
||||||
|
ft.Button("Cancel", on_click=self.on_cancel_btn_click)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
self.all_providers = self.providers_manager.get_all_providers()
|
||||||
|
self.providers_list = ft.ListView(
|
||||||
|
controls=self.create_list(self.all_providers, self.view_provider, self.edit_provider, self.delete_provider),
|
||||||
|
spacing=10,
|
||||||
|
expand=True
|
||||||
|
)
|
||||||
|
|
||||||
|
self.delete_dialog = ft.AlertDialog(
|
||||||
|
title=ft.Text("Stergeti furnizorul?"),
|
||||||
|
actions = [
|
||||||
|
ft.FilledButton("Da", on_click=self.on_delete_btn_click),
|
||||||
|
ft.Button("Nu", on_click=self.on_cancel_delete_btn_click)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
self.selected_provider_id = None
|
||||||
|
|
||||||
|
self.search = ft.TextField(label="Cauta", on_submit=self.on_search_btn_click, expand=True)
|
||||||
|
|
||||||
|
self.view_provider_name = ft.Text(value="Denumire")
|
||||||
|
self.view_provider_vat = ft.Text(value="CUI")
|
||||||
|
self.view_provider_register_number = ft.Text(value="Numar de inregistrare")
|
||||||
|
self.view_provider_address = ft.Text(value = "Sediu")
|
||||||
|
self.view_contact_name = ft.Text(value="Nume si prenume")
|
||||||
|
self.view_contact_number = ft.Text(value="Telefon")
|
||||||
|
self.view_contact_email = ft.Text(value="E-mail")
|
||||||
|
self.view_created_date = ft.Text(value="Data creare")
|
||||||
|
self.view_status = ft.Text(value="Status")
|
||||||
|
|
||||||
|
self.view_dialog = ft.AlertDialog(
|
||||||
|
title=self.view_provider_name,
|
||||||
|
content=ft.Column(
|
||||||
|
[
|
||||||
|
self.view_provider_vat,
|
||||||
|
self.view_provider_register_number,
|
||||||
|
self.view_provider_address,
|
||||||
|
ft.Text(),
|
||||||
|
ft.Text("Persoana de contact", weight=ft.FontWeight.BOLD),
|
||||||
|
self.view_contact_name,
|
||||||
|
self.view_contact_number,
|
||||||
|
self.view_contact_email,
|
||||||
|
ft.Text(),
|
||||||
|
self.view_created_date,
|
||||||
|
self.view_status
|
||||||
|
],
|
||||||
|
width=400,
|
||||||
|
height=300
|
||||||
|
),
|
||||||
|
actions=[ft.Button("Close", on_click=self.on_close_btn_click)]
|
||||||
|
)
|
||||||
|
|
||||||
|
self.is_editing = None
|
||||||
|
|
||||||
|
def on_delete_btn_click(self, e):
|
||||||
|
self.providers_manager.remove_provider(self.selected_provider_id)
|
||||||
|
self.selected_provider_id = None
|
||||||
|
self.page.close(self.delete_dialog)
|
||||||
|
|
||||||
|
self.all_providers = self.providers_manager.get_all_providers()
|
||||||
|
self.providers_list.controls=self.create_list(self.all_providers, self.view_provider, self.edit_provider, self.delete_provider)
|
||||||
|
self.providers_list.update()
|
||||||
|
|
||||||
|
def on_cancel_delete_btn_click(self, e):
|
||||||
|
self.selected_provider_id = None
|
||||||
|
self.page.close(self.delete_dialog)
|
||||||
|
|
||||||
|
def view_provider(self, item):
|
||||||
|
self.view_provider_name.value = item['provider_name']
|
||||||
|
self.view_provider_vat.value = 'CUI: ' + item['provider_vat']
|
||||||
|
self.view_provider_register_number.value = "Numar de inregistrare: "+item['provider_register_number']
|
||||||
|
self.view_provider_address.value = "Sediu: " + item['provider_address']
|
||||||
|
self.view_contact_name.value = "Nume si prenume: " + item['contact_name']
|
||||||
|
self.view_contact_number.value = "Telefon: " + item['contact_number']
|
||||||
|
self.view_contact_email.value = "E-mail: " + item['contact_email']
|
||||||
|
self.view_created_date.value = "Creat la: " + item['created_at']
|
||||||
|
self.view_status.value = "Status: " + item['status']
|
||||||
|
self.page.open(self.view_dialog)
|
||||||
|
|
||||||
|
def on_close_btn_click(self, e):
|
||||||
|
self.page.close(self.view_dialog)
|
||||||
|
|
||||||
|
|
||||||
|
def delete_provider(self, id):
|
||||||
|
print("Delete ", id)
|
||||||
|
self.selected_provider_id = id
|
||||||
|
self.page.open(self.delete_dialog)
|
||||||
|
|
||||||
|
def on_search_btn_click(self, e):
|
||||||
|
search = self.search.value
|
||||||
|
buffer = []
|
||||||
|
for provider in self.all_providers:
|
||||||
|
if search.lower() in provider['provider_name'].lower():
|
||||||
|
buffer.append(provider)
|
||||||
|
|
||||||
|
self.providers_list.controls=self.create_list(buffer, self.view_provider, self.edit_provider, self.delete_provider)
|
||||||
|
self.providers_list.update()
|
||||||
|
|
||||||
|
|
||||||
|
def create_list(self, items, on_click_handler, on_click_handler2, on_click_handler3):
|
||||||
|
"""Helper to create list items for a column."""
|
||||||
|
return [
|
||||||
|
ft.Container(
|
||||||
|
content=ft.Row(
|
||||||
|
[
|
||||||
|
|
||||||
|
ft.Row(
|
||||||
|
[
|
||||||
|
ft.Icon(name=ft.Icons.FIRE_TRUCK, size=40),
|
||||||
|
ft.Column(
|
||||||
|
[
|
||||||
|
ft.Text(value=f"Denumire: {item['provider_name']}", weight=ft.FontWeight.BOLD),
|
||||||
|
ft.Text(value=f"Status: {item['status']}", size=12)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
|
||||||
|
ft.Row(
|
||||||
|
[
|
||||||
|
ft.IconButton(
|
||||||
|
icon=ft.Icons.PREVIEW,
|
||||||
|
on_click=lambda e, id=item: on_click_handler(id),
|
||||||
|
),
|
||||||
|
ft.IconButton(
|
||||||
|
icon=ft.Icons.EDIT,
|
||||||
|
on_click=lambda e, id=item: on_click_handler2(id),
|
||||||
|
),
|
||||||
|
ft.IconButton(
|
||||||
|
icon=ft.Icons.DELETE,
|
||||||
|
on_click=lambda e, id=item['id']: on_click_handler3(id),
|
||||||
|
icon_color=ft.Colors.RED,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
],
|
||||||
|
alignment=ft.MainAxisAlignment.SPACE_BETWEEN,
|
||||||
|
),
|
||||||
|
width=300,
|
||||||
|
bgcolor=ft.Colors.BROWN_50,
|
||||||
|
border = ft.border.all(1, ft.Colors.GREY),
|
||||||
|
padding=10,
|
||||||
|
border_radius=8,
|
||||||
|
)
|
||||||
|
for item in items
|
||||||
|
]
|
||||||
|
|
||||||
|
def on_add_btn_click(self, e):
|
||||||
|
self.page.open(self.add_dialog)
|
||||||
|
|
||||||
|
def on_save_btn_click(self, e):
|
||||||
|
self.page.close(self.add_dialog)
|
||||||
|
provider = {
|
||||||
|
'provider_name':self.provider_name.value,
|
||||||
|
'provider_vat':self.provider_vat.value,
|
||||||
|
'provider_register_number':self.provider_register_number.value,
|
||||||
|
'provider_address':self.provider_address.value,
|
||||||
|
'contact_name':self.contact_name.value,
|
||||||
|
'contact_number':self.contact_number.value,
|
||||||
|
'contact_email':self.contact_email.value,
|
||||||
|
'add_error_message':self.add_error_message.value
|
||||||
|
}
|
||||||
|
if not self.is_editing:
|
||||||
|
print('Add provider: ', provider)
|
||||||
|
self.providers_manager.add_provider(provider)
|
||||||
|
else:
|
||||||
|
provider['id'] = self.is_editing
|
||||||
|
provider['status'] = self.status.value
|
||||||
|
print('Edit provider: ', provider)
|
||||||
|
self.providers_manager.update_provider(provider)
|
||||||
|
self.is_editing = None
|
||||||
|
|
||||||
|
self.all_providers = self.providers_manager.get_all_providers()
|
||||||
|
self.providers_list.controls=self.create_list(self.all_providers, self.view_provider, self.edit_provider, self.delete_provider)
|
||||||
|
self.providers_list.update()
|
||||||
|
|
||||||
|
self.reset_fields()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def on_cancel_btn_click(self, e):
|
||||||
|
self.page.close(self.add_dialog)
|
||||||
|
self.reset_fields()
|
||||||
|
|
||||||
|
def reset_fields(self):
|
||||||
|
self.provider_name.value = None
|
||||||
|
self.provider_name.update()
|
||||||
|
self.provider_vat.value = None
|
||||||
|
self.provider_vat.update()
|
||||||
|
self.provider_register_number.value = None
|
||||||
|
self.provider_register_number.update()
|
||||||
|
self.provider_address.value = None
|
||||||
|
self.provider_address.update()
|
||||||
|
self.contact_name.value = None
|
||||||
|
self.contact_name.update()
|
||||||
|
self.contact_number.value = None
|
||||||
|
self.contact_number.update()
|
||||||
|
self.contact_email.value = None
|
||||||
|
self.contact_email.update()
|
||||||
|
self.add_error_message.value = None
|
||||||
|
self.add_error_message.update()
|
||||||
|
try:
|
||||||
|
self.add_dialog.content.controls.remove(self.status)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
self.add_dialog.content.height = 500
|
||||||
|
|
||||||
|
def edit_provider(self, item):
|
||||||
|
self.is_editing = item['id']
|
||||||
|
self.provider_name.value = item['provider_name']
|
||||||
|
self.provider_vat.value = item['provider_vat']
|
||||||
|
self.provider_register_number.value = item['provider_register_number']
|
||||||
|
self.provider_address.value = item['provider_address']
|
||||||
|
self.contact_name.value = item['contact_name']
|
||||||
|
self.contact_number.value = item['contact_number']
|
||||||
|
self.contact_email.value = item['contact_email']
|
||||||
|
self.status.value = item['status']
|
||||||
|
self.add_dialog.content.controls.append(self.status_group)
|
||||||
|
self.add_dialog.content.height = 600
|
||||||
|
self.page.open(self.add_dialog)
|
||||||
|
|
||||||
|
def build(self):
|
||||||
|
return ft.Container(
|
||||||
|
ft.Column(
|
||||||
|
[
|
||||||
|
ft.Row(
|
||||||
|
[
|
||||||
|
ft.Text("Furnizori", weight=ft.FontWeight.BOLD, size=18),
|
||||||
|
ft.Button("Adauga", icon=ft.Icons.ADD, on_click=self.on_add_btn_click)
|
||||||
|
],
|
||||||
|
alignment=ft.MainAxisAlignment.SPACE_BETWEEN
|
||||||
|
),
|
||||||
|
ft.Row(
|
||||||
|
[
|
||||||
|
self.search,
|
||||||
|
ft.IconButton(icon=ft.Icons.SEARCH, on_click=self.on_search_btn_click)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
self.providers_list
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
0
UI_V2/admin/inventory/stocks.py
Normal file
0
UI_V2/admin/inventory/stocks.py
Normal file
@@ -3,6 +3,7 @@ from dbActions.orders import Orders
|
|||||||
from dbActions.users import Users
|
from dbActions.users import Users
|
||||||
from dbActions.products import Products
|
from dbActions.products import Products
|
||||||
from helpers.default_user import DefaultUser
|
from helpers.default_user import DefaultUser
|
||||||
|
from helpers.emails import send_gmail
|
||||||
|
|
||||||
class OrdersPage:
|
class OrdersPage:
|
||||||
def __init__(self, page: ft.Page):
|
def __init__(self, page: ft.Page):
|
||||||
@@ -141,7 +142,13 @@ class OrdersPage:
|
|||||||
),
|
),
|
||||||
self.products_column,
|
self.products_column,
|
||||||
ft.Divider(),
|
ft.Divider(),
|
||||||
self.buttons_state
|
ft.Row(
|
||||||
|
[
|
||||||
|
self.buttons_state,
|
||||||
|
ft.Button("Sterge", icon = ft.Icons.DELETE, on_click=self.on_order_delete_btn_click)
|
||||||
|
],
|
||||||
|
alignment=ft.MainAxisAlignment.SPACE_BETWEEN
|
||||||
|
)
|
||||||
],
|
],
|
||||||
expand=True
|
expand=True
|
||||||
)
|
)
|
||||||
@@ -175,6 +182,37 @@ class OrdersPage:
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.delete_order_dialog = ft.AlertDialog(
|
||||||
|
title=ft.Text("Sertgeti?"),
|
||||||
|
actions=[
|
||||||
|
ft.FilledButton(
|
||||||
|
"Da",
|
||||||
|
on_click=self.on_confirm_delete_order
|
||||||
|
),
|
||||||
|
ft.FilledButton(
|
||||||
|
"Nu",
|
||||||
|
on_click=self.on_cancel_delete_order_btn_click,
|
||||||
|
bgcolor=ft.Colors.GREY
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
def on_order_delete_btn_click(self, e):
|
||||||
|
self.page.open(self.delete_order_dialog)
|
||||||
|
|
||||||
|
def on_confirm_delete_order(self, e):
|
||||||
|
self.orders.remove_order(self.selected_order['id'])
|
||||||
|
self.all_orders = self.orders.get_orders()[::-1]
|
||||||
|
self.oll_orders_list.controls = self.create_list(self.all_orders, self.on_order_click)
|
||||||
|
self.oll_orders_list.update()
|
||||||
|
self.selected_order = None
|
||||||
|
self.order_details_placeholder.content = None
|
||||||
|
self.order_details_placeholder.update()
|
||||||
|
self.page.close(self.delete_order_dialog)
|
||||||
|
|
||||||
|
def on_cancel_delete_order_btn_click(self, e):
|
||||||
|
self.page.close(self.delete_order_dialog)
|
||||||
|
|
||||||
def on_radio_value_change(self, e):
|
def on_radio_value_change(self, e):
|
||||||
self.page.open(self.change_state_dialog)
|
self.page.open(self.change_state_dialog)
|
||||||
|
|
||||||
@@ -190,12 +228,22 @@ class OrdersPage:
|
|||||||
self.oll_orders_list.update()
|
self.oll_orders_list.update()
|
||||||
self.order_details_placeholder.content = None
|
self.order_details_placeholder.content = None
|
||||||
self.order_details_placeholder.update()
|
self.order_details_placeholder.update()
|
||||||
#-------------------------------------------> TBI Send information email to customer
|
|
||||||
message = self.message_field.value
|
message = self.message_field.value
|
||||||
self.message_field.value = ''
|
self.message_field.value = ''
|
||||||
self.message_field.update()
|
self.message_field.update()
|
||||||
print(message)
|
print(message)
|
||||||
email = self.customer_email
|
email = self.customer_email
|
||||||
|
status_values = {
|
||||||
|
"on_hold":"in asteptare",
|
||||||
|
"new": "noua",
|
||||||
|
"in_progress":"in lucru",
|
||||||
|
"completed": "la curier",
|
||||||
|
}
|
||||||
|
send_gmail(
|
||||||
|
to_email=email,
|
||||||
|
subject=f"Comanda cumneavoastra este: {status_values[status]}",
|
||||||
|
body=message
|
||||||
|
)
|
||||||
|
|
||||||
def on_cancel_state_btn_click(self, e):
|
def on_cancel_state_btn_click(self, e):
|
||||||
self.buttons_state.value = self.original_status
|
self.buttons_state.value = self.original_status
|
||||||
@@ -230,9 +278,10 @@ class OrdersPage:
|
|||||||
if products:
|
if products:
|
||||||
for product in products:
|
for product in products:
|
||||||
prod = self.products.get(product['prdouct_id'])
|
prod = self.products.get(product['prdouct_id'])
|
||||||
print(prod)
|
|
||||||
if prod:
|
if prod:
|
||||||
|
prod['pices'] = product['quantity']
|
||||||
self.selected_order_products.append(prod)
|
self.selected_order_products.append(prod)
|
||||||
|
print(prod)
|
||||||
|
|
||||||
self.name.value = self.selected_user['name'] if '@default.com' not in self.selected_user['email'] else 'Anonim user'
|
self.name.value = self.selected_user['name'] if '@default.com' not in self.selected_user['email'] else 'Anonim user'
|
||||||
self.name.update()
|
self.name.update()
|
||||||
@@ -259,16 +308,28 @@ class OrdersPage:
|
|||||||
)
|
)
|
||||||
image = ft.Image(
|
image = ft.Image(
|
||||||
src=product['image'],
|
src=product['image'],
|
||||||
width=200,
|
width=120,
|
||||||
height=200,
|
height=120,
|
||||||
fit=ft.ImageFit.CONTAIN
|
fit=ft.ImageFit.CONTAIN
|
||||||
)
|
)
|
||||||
quantity_label = ft.Text("Cantitate")
|
quantity_label = ft.Text("Cantitate")
|
||||||
quantity = ft.Text(product['quantity'])
|
quantity = ft.Text(product['quantity'])
|
||||||
quantity_row = ft.Row(
|
pices_label = ft.Text("Numar bucati")
|
||||||
|
pices = ft.Text(product['pices'])
|
||||||
|
quantity_row = ft.Column(
|
||||||
[
|
[
|
||||||
quantity_label,
|
ft.Row(
|
||||||
quantity
|
[
|
||||||
|
quantity_label,
|
||||||
|
quantity
|
||||||
|
]
|
||||||
|
),
|
||||||
|
ft.Row(
|
||||||
|
[
|
||||||
|
pices_label,
|
||||||
|
pices
|
||||||
|
]
|
||||||
|
)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
product_row = ft.Row(
|
product_row = ft.Row(
|
||||||
|
|||||||
@@ -14,8 +14,10 @@ class ProductsPage:
|
|||||||
self.description = ft.TextField(label="Descriere", multiline=True, min_lines=3, max_lines=5)
|
self.description = ft.TextField(label="Descriere", multiline=True, min_lines=3, max_lines=5)
|
||||||
self.details = ft.TextField(label="Detalii", multiline=True, min_lines=3, max_lines=5)
|
self.details = ft.TextField(label="Detalii", multiline=True, min_lines=3, max_lines=5)
|
||||||
self.price = ft.TextField(label="Pret")
|
self.price = ft.TextField(label="Pret")
|
||||||
self.discount = ft.TextField(label="Reducere (%)")
|
self.discount = ft.TextField(label="Reducere (%)", value='0')
|
||||||
self.quantity = ft.TextField(label="Cantitate")
|
self.quantity = ft.TextField(label="Cantitate")
|
||||||
|
self.search_filed = ft.TextField(label="Cauta Produs", on_submit=self.on_search_btn_click, expand=True)
|
||||||
|
self.search_btn = ft.IconButton(icon=ft.Icons.SEARCH, on_click=self.on_search_btn_click)
|
||||||
self.product_image = ft.Image(
|
self.product_image = ft.Image(
|
||||||
width=150,
|
width=150,
|
||||||
height=150,
|
height=150,
|
||||||
@@ -31,6 +33,7 @@ class ProductsPage:
|
|||||||
],
|
],
|
||||||
expand=True
|
expand=True
|
||||||
)
|
)
|
||||||
|
self.aviability.value = 'in_stock'
|
||||||
|
|
||||||
self.category = ft.Dropdown(
|
self.category = ft.Dropdown(
|
||||||
label="Categorie",
|
label="Categorie",
|
||||||
@@ -110,6 +113,19 @@ class ProductsPage:
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def on_search_btn_click(self, e):
|
||||||
|
search = self.search_filed.value
|
||||||
|
buffer = []
|
||||||
|
for product in self._all_products:
|
||||||
|
if search.lower() in product['name'].lower():
|
||||||
|
buffer.append(product)
|
||||||
|
self.products_list.controls.clear()
|
||||||
|
self.search_filed.value = ''
|
||||||
|
self.search_filed.update()
|
||||||
|
self._all_products = self.product_manager.get_all()
|
||||||
|
self.products_list.controls=self.create_list(buffer, self.edit_product, self.delete_product)
|
||||||
|
self.products_list.update()
|
||||||
|
|
||||||
def on_file_picker_result(self, e: ft.FilePickerResultEvent):
|
def on_file_picker_result(self, e: ft.FilePickerResultEvent):
|
||||||
if e.files:
|
if e.files:
|
||||||
file = e.files[0]
|
file = e.files[0]
|
||||||
@@ -227,10 +243,21 @@ class ProductsPage:
|
|||||||
ft.Container(
|
ft.Container(
|
||||||
content=ft.Row(
|
content=ft.Row(
|
||||||
[
|
[
|
||||||
ft.Column(
|
ft.Row(
|
||||||
[
|
[
|
||||||
ft.Text(value=item['name'], weight=ft.FontWeight.BOLD, size=15),
|
ft.Image(
|
||||||
ft.Text(value=f"Pret: {item['price']}", size=12)
|
src=item['image'],
|
||||||
|
width=50,
|
||||||
|
height=50,
|
||||||
|
fit=ft.ImageFit.COVER,
|
||||||
|
border_radius=5
|
||||||
|
),
|
||||||
|
ft.Column(
|
||||||
|
[
|
||||||
|
ft.Text(value=item['name'], weight=ft.FontWeight.BOLD, size=15),
|
||||||
|
ft.Text(value=f"Pret: {item['price']}", size=12)
|
||||||
|
]
|
||||||
|
),
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
ft.Row(
|
ft.Row(
|
||||||
@@ -299,6 +326,12 @@ class ProductsPage:
|
|||||||
],
|
],
|
||||||
alignment=ft.MainAxisAlignment.SPACE_BETWEEN
|
alignment=ft.MainAxisAlignment.SPACE_BETWEEN
|
||||||
),
|
),
|
||||||
|
ft.Row(
|
||||||
|
[
|
||||||
|
self.search_filed,
|
||||||
|
self.search_btn,
|
||||||
|
]
|
||||||
|
),
|
||||||
self.products_list
|
self.products_list
|
||||||
],
|
],
|
||||||
alignment=ft.MainAxisAlignment.START,
|
alignment=ft.MainAxisAlignment.START,
|
||||||
|
|||||||
62
UI_V2/admin/settings.py
Normal file
62
UI_V2/admin/settings.py
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
import flet as ft
|
||||||
|
from admin.company_data import CompanyData
|
||||||
|
from admin.company_details import CompanyDetails
|
||||||
|
|
||||||
|
class Settings:
|
||||||
|
def __init__(self, page: ft.Page, dashboard):
|
||||||
|
self.page = page
|
||||||
|
self.dashboard = dashboard
|
||||||
|
|
||||||
|
def on_add_policy_btn_click(self, e):
|
||||||
|
policy = CompanyDetails(self.page)
|
||||||
|
self.dashboard.placeholder.content = policy.build()
|
||||||
|
self.dashboard.placeholder.update()
|
||||||
|
|
||||||
|
def on_add_data_btn_click(self, e):
|
||||||
|
data = CompanyData(self.page)
|
||||||
|
self.dashboard.placeholder.content = data.build()
|
||||||
|
self.dashboard.placeholder.update()
|
||||||
|
|
||||||
|
def build(self):
|
||||||
|
return ft.Container(
|
||||||
|
content=ft.Column(
|
||||||
|
[
|
||||||
|
ft.GridView(
|
||||||
|
[
|
||||||
|
ft.Card(
|
||||||
|
content=ft.Container(
|
||||||
|
content=ft.Column(
|
||||||
|
[
|
||||||
|
ft.Icon(name=ft.Icons.DATASET, size=100),
|
||||||
|
ft.Text("Adauga datele companiei", size=16, weight=ft.FontWeight.BOLD),
|
||||||
|
ft.Button("Adauga", icon=ft.Icons.ADD, on_click=self.on_add_data_btn_click)
|
||||||
|
],
|
||||||
|
horizontal_alignment=ft.CrossAxisAlignment.CENTER
|
||||||
|
),
|
||||||
|
padding=10
|
||||||
|
)
|
||||||
|
),
|
||||||
|
ft.Card(
|
||||||
|
content=ft.Container(
|
||||||
|
content=ft.Column(
|
||||||
|
[
|
||||||
|
ft.Icon(name=ft.Icons.POLICY, size=100),
|
||||||
|
ft.Text("Adauga politicile companiei", size=16, weight=ft.FontWeight.BOLD),
|
||||||
|
ft.Button("Adauga", icon=ft.Icons.ADD, on_click=self.on_add_policy_btn_click)
|
||||||
|
],
|
||||||
|
horizontal_alignment=ft.CrossAxisAlignment.CENTER
|
||||||
|
),
|
||||||
|
padding=10
|
||||||
|
)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
spacing=10,
|
||||||
|
runs_count=4,
|
||||||
|
max_extent=250,
|
||||||
|
child_aspect_ratio=1.0,
|
||||||
|
expand=True,
|
||||||
|
width=1000
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
99
UI_V2/dbActions/fidelity_cards.py
Normal file
99
UI_V2/dbActions/fidelity_cards.py
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
import sqlite3
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
class FidelityCards:
|
||||||
|
def __init__(self, db_path="instance/app_database.db"):
|
||||||
|
self.db_path = db_path
|
||||||
|
self._create_fidelity_cards_table()
|
||||||
|
|
||||||
|
def _create_fidelity_cards_table(self):
|
||||||
|
with sqlite3.connect(self.db_path) as conn:
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute("""
|
||||||
|
CREATE TABLE IF NOT EXISTS fidelity_cards (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
card_id TEXT,
|
||||||
|
card_type INTEGER,
|
||||||
|
client_name TEXT,
|
||||||
|
phone_number TEXT,
|
||||||
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
""")
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
def add_fidelity_card(self, card_id, card_type, client_name, phone_number):
|
||||||
|
try:
|
||||||
|
with sqlite3.connect(self.db_path) as conn:
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute("""
|
||||||
|
INSERT INTO fidelity_cards (card_id, card_type, client_name, phone_number)
|
||||||
|
VALUES (?, ?, ?, ?)
|
||||||
|
""", (card_id, card_type, client_name, phone_number,))
|
||||||
|
conn.commit()
|
||||||
|
return True
|
||||||
|
except sqlite3.IntegrityError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_all_fidelity_cards(self):
|
||||||
|
with sqlite3.connect(self.db_path) as conn:
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute("""
|
||||||
|
SELECT * FROM fidelity_cards
|
||||||
|
""",)
|
||||||
|
rows = cursor.fetchall()
|
||||||
|
result = []
|
||||||
|
if rows:
|
||||||
|
for row in rows:
|
||||||
|
buffer = {
|
||||||
|
"id": row[0],
|
||||||
|
"card_id": row[1],
|
||||||
|
"card_type": row[2],
|
||||||
|
"client_name": row[3],
|
||||||
|
"phone_number": row[4],
|
||||||
|
"created_at": row[5]
|
||||||
|
}
|
||||||
|
result.append(buffer)
|
||||||
|
return result
|
||||||
|
return []
|
||||||
|
|
||||||
|
def get_fidelity_card(self, id):
|
||||||
|
with sqlite3.connect(self.db_path) as conn:
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute("""
|
||||||
|
SELECT * FROM fidelity_cards WHERE id = ?
|
||||||
|
""",(id, ))
|
||||||
|
row = cursor.fetchone()
|
||||||
|
result = []
|
||||||
|
if row:
|
||||||
|
result = {
|
||||||
|
"id": row[0],
|
||||||
|
"card_id": row[1],
|
||||||
|
"card_type": row[2],
|
||||||
|
"client_name": row[3],
|
||||||
|
"phone_number": row[4],
|
||||||
|
"created_at": row[5]
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
return None
|
||||||
|
|
||||||
|
def remove_fidelity_card(self, id):
|
||||||
|
with sqlite3.connect(self.db_path) as conn:
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute('''
|
||||||
|
DELETE FROM fidelity_cards WHERE id=?;
|
||||||
|
''', (id,))
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
def update_card(self, id, card_id, card_type, client_name, phone_number):
|
||||||
|
try:
|
||||||
|
with sqlite3.connect(self.db_path) as conn:
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute("""
|
||||||
|
UPDATE fidelity_cards
|
||||||
|
SET card_id = ?, card_type = ?, client_name = ?, phone_number = ?
|
||||||
|
WHERE id = ?
|
||||||
|
""", (card_id, card_type, client_name, phone_number, id))
|
||||||
|
conn.commit()
|
||||||
|
return True
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
33
UI_V2/dbActions/netopia.py
Normal file
33
UI_V2/dbActions/netopia.py
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import sqlite3
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
class Netopia:
|
||||||
|
def __init__(self, db_path="instance/app_database.db"):
|
||||||
|
self.db_path = db_path
|
||||||
|
self._create_netopia_table()
|
||||||
|
|
||||||
|
def _create_netopia_table(self):
|
||||||
|
with sqlite3.connect(self.db_path) as conn:
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute("""
|
||||||
|
CREATE TABLE IF NOT EXISTS netopia (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
order_id TEXT,
|
||||||
|
netopia_id TEXT,
|
||||||
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
""")
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
def add_netopia_card(self, order_id, netopia_id):
|
||||||
|
try:
|
||||||
|
with sqlite3.connect(self.db_path) as conn:
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute("""
|
||||||
|
INSERT INTO netopia (order_id, netopia_id)
|
||||||
|
VALUES (?, ? )
|
||||||
|
""", (order_id, netopia_id))
|
||||||
|
conn.commit()
|
||||||
|
return True
|
||||||
|
except sqlite3.IntegrityError:
|
||||||
|
return False
|
||||||
@@ -86,6 +86,15 @@ class Orders:
|
|||||||
''', (status, id))
|
''', (status, id))
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
|
def update_order_user_id(self, user_id, id):
|
||||||
|
with sqlite3.connect(self.db_path) as conn:
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute('''
|
||||||
|
UPDATE orders SET user_id = ?
|
||||||
|
WHERE id = ?
|
||||||
|
''', (user_id, id))
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
def get_order_products(self, id):
|
def get_order_products(self, id):
|
||||||
with sqlite3.connect(self.db_path) as conn:
|
with sqlite3.connect(self.db_path) as conn:
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
@@ -155,9 +164,23 @@ class Orders:
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
def remove_product_from_order(self, order_id, product_id):
|
def remove_product_from_order(self, order_id, product_id):
|
||||||
with sqlite3.connect(self.db_path) as conn:
|
with sqlite3.connect(self.db_path) as conn:
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
cursor.execute('''
|
cursor.execute('''
|
||||||
DELETE FROM orders_products WHERE orders_id=? and product_id=?;
|
DELETE FROM orders_products WHERE orders_id=? and product_id=?;
|
||||||
''', (order_id, product_id))
|
''', (order_id, product_id))
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
|
def remove_order(self, order_id):
|
||||||
|
with sqlite3.connect(self.db_path) as conn:
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute('''
|
||||||
|
DELETE FROM orders_products WHERE orders_id=?;
|
||||||
|
''', (order_id,))
|
||||||
|
conn.commit()
|
||||||
|
with sqlite3.connect(self.db_path) as conn:
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute('''
|
||||||
|
DELETE FROM orders WHERE id=?;
|
||||||
|
''', (order_id,))
|
||||||
|
conn.commit()
|
||||||
158
UI_V2/dbActions/providers.py
Normal file
158
UI_V2/dbActions/providers.py
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
import sqlite3
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
class Providers:
|
||||||
|
def __init__(self, db_path="instance/app_database.db"):
|
||||||
|
self.db_path = db_path
|
||||||
|
self._create_providers_table()
|
||||||
|
|
||||||
|
def _create_providers_table(self):
|
||||||
|
with sqlite3.connect(self.db_path) as conn:
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute("""
|
||||||
|
CREATE TABLE IF NOT EXISTS providers (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
provider_name TEXT,
|
||||||
|
provider_vat TEXT,
|
||||||
|
provider_register_number TEXT,
|
||||||
|
provider_address TEXT,
|
||||||
|
contact_name TEXT,
|
||||||
|
contact_number TEXT,
|
||||||
|
contact_email TEXT,
|
||||||
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
status TEXT NOT NULL DEFAULT 'Activ'
|
||||||
|
);
|
||||||
|
""")
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
def add_provider(self, provider):
|
||||||
|
try:
|
||||||
|
with sqlite3.connect(self.db_path) as conn:
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute("""
|
||||||
|
INSERT INTO providers (
|
||||||
|
provider_name,
|
||||||
|
provider_vat,
|
||||||
|
provider_register_number,
|
||||||
|
provider_address,
|
||||||
|
contact_name,
|
||||||
|
contact_number,
|
||||||
|
contact_email
|
||||||
|
)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||||
|
""", (
|
||||||
|
provider['provider_name'],
|
||||||
|
provider['provider_vat'],
|
||||||
|
provider['provider_register_number'],
|
||||||
|
provider['provider_address'],
|
||||||
|
provider['contact_name'],
|
||||||
|
provider['contact_number'],
|
||||||
|
provider['contact_email']
|
||||||
|
)
|
||||||
|
)
|
||||||
|
conn.commit()
|
||||||
|
return True
|
||||||
|
except sqlite3.IntegrityError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_all_providers(self):
|
||||||
|
with sqlite3.connect(self.db_path) as conn:
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute("""
|
||||||
|
SELECT * FROM providers
|
||||||
|
""",)
|
||||||
|
rows = cursor.fetchall()
|
||||||
|
result = []
|
||||||
|
if rows:
|
||||||
|
for row in rows:
|
||||||
|
buffer = {
|
||||||
|
"id": row[0],
|
||||||
|
"provider_name": row[1],
|
||||||
|
"provider_vat": row[2],
|
||||||
|
"provider_register_number": row[3],
|
||||||
|
"provider_address": row[4],
|
||||||
|
"contact_name": row[5],
|
||||||
|
"contact_number": row[6],
|
||||||
|
"contact_email": row[7],
|
||||||
|
"created_at": row[8],
|
||||||
|
"status": row[9]
|
||||||
|
}
|
||||||
|
result.append(buffer)
|
||||||
|
return result
|
||||||
|
return []
|
||||||
|
|
||||||
|
def get_provider(self, id):
|
||||||
|
with sqlite3.connect(self.db_path) as conn:
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute("""
|
||||||
|
SELECT * FROM providers WHERE id = ?
|
||||||
|
""",(id, ))
|
||||||
|
row = cursor.fetchone()
|
||||||
|
result = []
|
||||||
|
if row:
|
||||||
|
result = {
|
||||||
|
"id": row[0],
|
||||||
|
"provider_name": row[1],
|
||||||
|
"provider_vat": row[2],
|
||||||
|
"provider_register_number": row[3],
|
||||||
|
"provider_address": row[4],
|
||||||
|
"contact_name": row[5],
|
||||||
|
"contact_number": row[6],
|
||||||
|
"contact_email": row[7],
|
||||||
|
"created_at": row[8],
|
||||||
|
"status": row[9]
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
return None
|
||||||
|
|
||||||
|
def remove_provider(self, id):
|
||||||
|
with sqlite3.connect(self.db_path) as conn:
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute('''
|
||||||
|
DELETE FROM providers WHERE id=?;
|
||||||
|
''', (id,))
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
def update_provider(self, provider):
|
||||||
|
#try:
|
||||||
|
with sqlite3.connect(self.db_path) as conn:
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute("""
|
||||||
|
UPDATE providers
|
||||||
|
SET provider_name = ?,
|
||||||
|
provider_vat = ?,
|
||||||
|
provider_register_number = ?,
|
||||||
|
provider_address = ?,
|
||||||
|
contact_name = ?,
|
||||||
|
contact_number = ?,
|
||||||
|
contact_email = ?,
|
||||||
|
status = ?
|
||||||
|
WHERE id = ?
|
||||||
|
""", (provider['provider_name'],
|
||||||
|
provider['provider_vat'],
|
||||||
|
provider['provider_register_number'],
|
||||||
|
provider['provider_address'],
|
||||||
|
provider['contact_name'],
|
||||||
|
provider['contact_number'],
|
||||||
|
provider['contact_email'],
|
||||||
|
provider['status'],
|
||||||
|
provider['id'])
|
||||||
|
)
|
||||||
|
conn.commit()
|
||||||
|
return True
|
||||||
|
#except Exception:
|
||||||
|
# return False
|
||||||
|
|
||||||
|
def deactivate(self, id):
|
||||||
|
try:
|
||||||
|
with sqlite3.connect(self.db_path) as conn:
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute("""
|
||||||
|
UPDATE providers
|
||||||
|
SET status = ?
|
||||||
|
WHERE id = ?
|
||||||
|
""", ('Inactive', id))
|
||||||
|
conn.commit()
|
||||||
|
return True
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
284
UI_V2/helpers/netopia.py
Normal file
284
UI_V2/helpers/netopia.py
Normal file
@@ -0,0 +1,284 @@
|
|||||||
|
"""
|
||||||
|
NETOPIA Payments helper for Flet/Flask apps
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
This module wraps the official NETOPIA Python SDK (API v2) and exposes:
|
||||||
|
• an easy `start_card_payment(...)` helper you can call from your app
|
||||||
|
• IPN verification and order status helpers
|
||||||
|
• an optional Flask Blueprint with REST endpoints you can plug into your
|
||||||
|
existing backend (or the small Flask service that often accompanies Flet apps)
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
pip install netopia-sdk flask
|
||||||
|
|
||||||
|
Environment variables expected (see README at bottom of file too):
|
||||||
|
NETOPIA_API_KEY – API key from admin.netopia-payments.com
|
||||||
|
NETOPIA_POS_SIGNATURE – POS signature
|
||||||
|
NETOPIA_PUBLIC_KEY – RSA public key (PEM string)
|
||||||
|
NETOPIA_PRIVATE_KEY – RSA private key (PEM string, optional)
|
||||||
|
NETOPIA_REDIRECT_URL – your site URL where the buyer returns after payment
|
||||||
|
NETOPIA_NOTIFY_URL – public URL that receives IPN callbacks
|
||||||
|
NETOPIA_CANCEL_URL – optional cancel URL
|
||||||
|
NETOPIA_POS_SIGNATURE_SET – optional, CSV list of allowed POS signatures
|
||||||
|
NETOPIA_IS_LIVE – 'true' to use production; otherwise sandbox
|
||||||
|
|
||||||
|
Usage from Flet (example):
|
||||||
|
from helpers.netopia import start_card_payment
|
||||||
|
url_payload = start_card_payment(
|
||||||
|
order_id="TG-100045",
|
||||||
|
amount=159.90,
|
||||||
|
currency="RON",
|
||||||
|
description="Comandă #TG-100045",
|
||||||
|
customer={
|
||||||
|
"email": "client@example.com",
|
||||||
|
"phone": "0712345678",
|
||||||
|
"first_name": "Ion",
|
||||||
|
"last_name": "Popescu",
|
||||||
|
"city": "București",
|
||||||
|
"country": "642", # 642 = Romania
|
||||||
|
"address": "Str. Exemplu 10",
|
||||||
|
"zip": "010101",
|
||||||
|
"county": "B-IF",
|
||||||
|
"language": "ro",
|
||||||
|
},
|
||||||
|
products=[
|
||||||
|
{"name": "Mix nuci 500g", "code": "MX500", "category": "fructe-uscate", "price": 79.95, "vat": 0},
|
||||||
|
{"name": "Caju 500g", "code": "CJ500", "category": "fructe-uscate", "price": 79.95, "vat": 0},
|
||||||
|
],
|
||||||
|
installments=1,
|
||||||
|
)
|
||||||
|
# url_payload typically contains the redirect URL – open it in a webview or browser
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
• You must expose your IPN endpoint publicly (HTTPS) and configure it in Netopia admin.
|
||||||
|
• Always trust order status updates coming from IPN, not only the browser redirect.
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
|
from datetime import datetime, timezone
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import List, Optional, Dict, Any
|
||||||
|
|
||||||
|
# NETOPIA SDK imports
|
||||||
|
from netopia_sdk.config import Config
|
||||||
|
from netopia_sdk.client import PaymentClient
|
||||||
|
from netopia_sdk.payment import PaymentService
|
||||||
|
from netopia_sdk.requests.models import (
|
||||||
|
StartPaymentRequest,
|
||||||
|
ConfigData,
|
||||||
|
PaymentData,
|
||||||
|
PaymentOptions,
|
||||||
|
Instrument,
|
||||||
|
OrderData,
|
||||||
|
BillingData,
|
||||||
|
ProductsData,
|
||||||
|
ShippingData,
|
||||||
|
)
|
||||||
|
|
||||||
|
# ---------------------------
|
||||||
|
# Configuration & wiring
|
||||||
|
# ---------------------------
|
||||||
|
@dataclass
|
||||||
|
class NetopiaSettings:
|
||||||
|
api_key: str
|
||||||
|
pos_signature: str
|
||||||
|
public_key_str: str
|
||||||
|
notify_url: str
|
||||||
|
redirect_url: str
|
||||||
|
is_live: bool
|
||||||
|
pos_signature_set: List[str]
|
||||||
|
cancel_url: str | None = None
|
||||||
|
private_key_str: str | None = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_env(cls) -> "NetopiaSettings":
|
||||||
|
print("API_KEY? ", os.getenv("NETOPIA_API_KEY") is not None)
|
||||||
|
is_live_str = os.getenv("NETOPIA_IS_LIVE", "false").strip().lower()
|
||||||
|
is_live = is_live_str in ("1", "true", "yes", "on")
|
||||||
|
|
||||||
|
pos_sig = os.environ.get("NETOPIA_POS_SIGNATURE", "").strip()
|
||||||
|
pos_sig_set_env = os.getenv("NETOPIA_POS_SIGNATURE_SET", pos_sig)
|
||||||
|
pos_sig_set = [s.strip() for s in pos_sig_set_env.split(",") if s.strip()]
|
||||||
|
|
||||||
|
return cls(
|
||||||
|
api_key=os.environ.get("NETOPIA_API_KEY", "").strip(),
|
||||||
|
pos_signature=pos_sig,
|
||||||
|
public_key_str=os.environ.get("NETOPIA_PUBLIC_KEY", "").strip(),
|
||||||
|
private_key_str=os.environ.get("NETOPIA_PRIVATE_KEY", "").strip(),
|
||||||
|
notify_url=os.environ.get("NETOPIA_NOTIFY_URL", "").strip(),
|
||||||
|
redirect_url=os.environ.get("NETOPIA_REDIRECT_URL", "").strip(),
|
||||||
|
is_live=is_live,
|
||||||
|
pos_signature_set=pos_sig_set,
|
||||||
|
cancel_url=os.environ.get("NETOPIA_CANCEL_URL", None),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _build_payment_service(settings: Optional[NetopiaSettings] = None) -> PaymentService:
|
||||||
|
"""Create a PaymentService from settings/env."""
|
||||||
|
settings = settings or NetopiaSettings.from_env()
|
||||||
|
|
||||||
|
if not settings.api_key:
|
||||||
|
raise RuntimeError("NETOPIA_API_KEY is missing")
|
||||||
|
if not settings.pos_signature:
|
||||||
|
raise RuntimeError("NETOPIA_POS_SIGNATURE is missing")
|
||||||
|
if not settings.public_key_str:
|
||||||
|
raise RuntimeError("NETOPIA_PUBLIC_KEY is missing (PEM)")
|
||||||
|
if not settings.notify_url:
|
||||||
|
raise RuntimeError("NETOPIA_NOTIFY_URL is missing")
|
||||||
|
if not settings.redirect_url:
|
||||||
|
raise RuntimeError("NETOPIA_REDIRECT_URL is missing")
|
||||||
|
|
||||||
|
config = Config(
|
||||||
|
api_key=settings.api_key,
|
||||||
|
pos_signature=settings.pos_signature,
|
||||||
|
is_live=settings.is_live,
|
||||||
|
notify_url=settings.notify_url,
|
||||||
|
redirect_url=settings.redirect_url,
|
||||||
|
public_key_str=settings.public_key_str,
|
||||||
|
#private_key_str=settings.private_key_str,
|
||||||
|
pos_signature_set=settings.pos_signature_set,
|
||||||
|
)
|
||||||
|
client = PaymentClient(config)
|
||||||
|
return PaymentService(client)
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------
|
||||||
|
# Helpers: BillingData from minimal fields (SDK-supported)
|
||||||
|
# ---------------------------
|
||||||
|
|
||||||
|
def _derive_billing_from_customer(customer: Dict[str, str]) -> BillingData:
|
||||||
|
"""Construct BillingData using only fields supported by the SDK example.
|
||||||
|
Accepts a single free-form address but does not send it (SDK BillingData
|
||||||
|
in v2 typically supports: email, phone, firstName, lastName, city, country).
|
||||||
|
We try to infer city from the first token before a comma if city is missing.
|
||||||
|
"""
|
||||||
|
city = (customer.get("city") or "").strip()
|
||||||
|
if not city:
|
||||||
|
addr = (customer.get("address") or "").strip()
|
||||||
|
if "," in addr:
|
||||||
|
candidate = addr.split(",", 1)[0].strip()
|
||||||
|
if 1 <= len(candidate) <= 64:
|
||||||
|
city = candidate
|
||||||
|
return BillingData(
|
||||||
|
email=customer.get("email", ""),
|
||||||
|
phone=customer.get("phone", ""),
|
||||||
|
firstName=customer.get("first_name", ""),
|
||||||
|
lastName=customer.get("last_name", ""),
|
||||||
|
city=city,
|
||||||
|
country=int(customer.get("country", "642") or 642),
|
||||||
|
countryName=customer.get("countryName", "Romania"),
|
||||||
|
state=customer.get("state", customer.get("county", "")),
|
||||||
|
postalCode=customer.get("zip", ""),
|
||||||
|
details=(customer.get("address") or "").strip(),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _derive_shipping_from_customer(customer: Dict[str, str]) -> ShippingData:
|
||||||
|
city = (customer.get("ship_city") or customer.get("city") or "").strip()
|
||||||
|
if not city:
|
||||||
|
addr = (customer.get("ship_address") or customer.get("address") or "").strip()
|
||||||
|
if "," in addr:
|
||||||
|
cand = addr.split(",", 1)[0].strip()
|
||||||
|
if 1 <= len(cand) <= 64:
|
||||||
|
city = cand
|
||||||
|
return ShippingData(
|
||||||
|
email=customer.get("ship_email", customer.get("email", "")),
|
||||||
|
phone=customer.get("ship_phone", customer.get("phone", "")),
|
||||||
|
firstName=customer.get("ship_first_name", customer.get("first_name", "")),
|
||||||
|
lastName=customer.get("ship_last_name", customer.get("last_name", "")),
|
||||||
|
city=city,
|
||||||
|
country=int(customer.get("ship_country", customer.get("country", "642")) or 642),
|
||||||
|
countryName=customer.get("ship_countryName", customer.get("countryName", "Romania")),
|
||||||
|
state=customer.get("ship_state", customer.get("state", customer.get("county", ""))),
|
||||||
|
postalCode=customer.get("ship_zip", customer.get("zip", "")),
|
||||||
|
details=(customer.get("ship_address") or customer.get("address") or "").strip(),
|
||||||
|
)
|
||||||
|
|
||||||
|
# ---------------------------
|
||||||
|
# High‑level helpers (call these from your app)
|
||||||
|
# ---------------------------
|
||||||
|
|
||||||
|
def start_card_payment(
|
||||||
|
*,
|
||||||
|
order_id: str,
|
||||||
|
amount: float,
|
||||||
|
currency: str,
|
||||||
|
description: str,
|
||||||
|
customer: Dict[str, str],
|
||||||
|
products: List[Dict[str, Any]],
|
||||||
|
installments: int = 1,
|
||||||
|
settings: Optional[NetopiaSettings] = None,
|
||||||
|
) -> Dict[str, Any]:
|
||||||
|
"""Create a redirect‑based card payment and return the SDK response.
|
||||||
|
|
||||||
|
The response typically includes the URL you must redirect the buyer to.
|
||||||
|
You should persist the order locally before calling this.
|
||||||
|
"""
|
||||||
|
svc = _build_payment_service(settings)
|
||||||
|
|
||||||
|
billing = _derive_billing_from_customer(customer)
|
||||||
|
shipping = _derive_shipping_from_customer(customer)
|
||||||
|
|
||||||
|
prods: List[ProductsData] = []
|
||||||
|
for p in products:
|
||||||
|
prods.append(
|
||||||
|
ProductsData(
|
||||||
|
name=str(p["name"]),
|
||||||
|
code=str(p.get("code", p["name"]))[:32],
|
||||||
|
category=str(p.get("category", "")),
|
||||||
|
price=float(p.get("price", 0.0)),
|
||||||
|
vat=int(p.get("vat", 0)),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
cfg = NetopiaSettings.from_env() if settings is None else settings
|
||||||
|
|
||||||
|
now_iso = datetime.now(timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ')
|
||||||
|
|
||||||
|
req = StartPaymentRequest(
|
||||||
|
config=ConfigData(
|
||||||
|
emailTemplate=customer.get("email_template", "default"),
|
||||||
|
emailSubject=customer.get("email_subject", "Order Confirmation"),
|
||||||
|
cancelUrl=cfg.cancel_url or cfg.redirect_url,
|
||||||
|
notifyUrl=cfg.notify_url,
|
||||||
|
redirectUrl=cfg.redirect_url,
|
||||||
|
language=customer.get("language", "ro"),
|
||||||
|
),
|
||||||
|
payment=PaymentData(
|
||||||
|
options=PaymentOptions(installments=int(installments), bonus=0),
|
||||||
|
instrument=None,
|
||||||
|
data={},
|
||||||
|
),
|
||||||
|
order=OrderData(
|
||||||
|
ntpID=None,
|
||||||
|
posSignature=None,
|
||||||
|
dateTime=now_iso,
|
||||||
|
orderID=str(order_id),
|
||||||
|
amount=float(amount),
|
||||||
|
currency=str(currency),
|
||||||
|
description=str(description),
|
||||||
|
billing=billing,
|
||||||
|
shipping=shipping,
|
||||||
|
products=prods,
|
||||||
|
installments={"selected": int(installments) if installments else 0, "available": []},
|
||||||
|
data={},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
return svc.start_payment(req)
|
||||||
|
|
||||||
|
|
||||||
|
def verify_ipn(raw_body: bytes, settings: Optional[NetopiaSettings] = None) -> Dict[str, Any]:
|
||||||
|
"""Verify an IPN payload coming from NETOPIA. Returns the decoded data.
|
||||||
|
|
||||||
|
Raise an exception if verification fails.
|
||||||
|
"""
|
||||||
|
svc = _build_payment_service(settings)
|
||||||
|
return svc.verify_ipn(raw_body)
|
||||||
|
|
||||||
|
|
||||||
|
def get_status(*, ntp_id: Optional[str] = None, order_id: Optional[str] = None, settings: Optional[NetopiaSettings] = None) -> Dict[str, Any]:
|
||||||
|
"""Query order status by ntpID and/or orderID."""
|
||||||
|
svc = _build_payment_service(settings)
|
||||||
|
return svc.get_status(ntpID=ntp_id, orderID=order_id)
|
||||||
@@ -7,10 +7,20 @@ from pages.products.product import ProductPage
|
|||||||
from pages.profile.profilepage import ProfilePage
|
from pages.profile.profilepage import ProfilePage
|
||||||
from pages.shopping_cart.cart import Cart
|
from pages.shopping_cart.cart import Cart
|
||||||
from pages.shopping_cart.peload_card import PreloadCard
|
from pages.shopping_cart.peload_card import PreloadCard
|
||||||
|
from pages.shopping_cart.payment_redirect import PaymentRedirect
|
||||||
|
from pages.details.about_us import AboutUS
|
||||||
|
from pages.details.terms_and_conditions import TermsAndConditions
|
||||||
|
from pages.details.cancel_policy import CancelPolicy
|
||||||
|
from pages.details.confidentialty_policy import ConfidentialtyPolicy
|
||||||
|
from pages.details.delivery_policy import DeliveryPolicys
|
||||||
|
from pages.details.gdpr_policy import GDPR
|
||||||
|
|
||||||
import os
|
import os
|
||||||
os.environ["FLET_SECRET_KEY"] = os.urandom(12).hex()
|
os.environ["FLET_SECRET_KEY"] = os.urandom(12).hex()
|
||||||
|
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
def main(page: ft.Page):
|
def main(page: ft.Page):
|
||||||
page.title = "Taina Gustului"
|
page.title = "Taina Gustului"
|
||||||
page.theme_mode = ft.ThemeMode.LIGHT
|
page.theme_mode = ft.ThemeMode.LIGHT
|
||||||
@@ -36,8 +46,8 @@ def main(page: ft.Page):
|
|||||||
|
|
||||||
if route == "/admin":
|
if route == "/admin":
|
||||||
if not page.client_storage.get("is_authenticated"):
|
if not page.client_storage.get("is_authenticated"):
|
||||||
page.go("/auth")
|
page.go("/auth")
|
||||||
return
|
return
|
||||||
dashbaord = Dashboard(page)
|
dashbaord = Dashboard(page)
|
||||||
page.add(dashbaord.build())
|
page.add(dashbaord.build())
|
||||||
page.update()
|
page.update()
|
||||||
@@ -73,6 +83,48 @@ def main(page: ft.Page):
|
|||||||
page.update()
|
page.update()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if route == '/payment/redirect':
|
||||||
|
redirect = PaymentRedirect(page)
|
||||||
|
page.add(redirect.build())
|
||||||
|
page.update()
|
||||||
|
return
|
||||||
|
|
||||||
|
if route == '/about_us':
|
||||||
|
about_us = AboutUS(page)
|
||||||
|
page.add(about_us.build())
|
||||||
|
page.update()
|
||||||
|
return
|
||||||
|
|
||||||
|
if route == '/termeni_si_conditii':
|
||||||
|
termeni_si_conditii = TermsAndConditions(page)
|
||||||
|
page.add(termeni_si_conditii.build())
|
||||||
|
page.update()
|
||||||
|
return
|
||||||
|
|
||||||
|
if route == '/politica_de_anulare_comanda':
|
||||||
|
politica_de_anulare_comanda = CancelPolicy(page)
|
||||||
|
page.add(politica_de_anulare_comanda.build())
|
||||||
|
page.update()
|
||||||
|
return
|
||||||
|
|
||||||
|
if route == '/politica_de_confidentialitate':
|
||||||
|
politica_de_confidentialitate = ConfidentialtyPolicy(page)
|
||||||
|
page.add(politica_de_confidentialitate.build())
|
||||||
|
page.update()
|
||||||
|
return
|
||||||
|
|
||||||
|
if route == '/politica_de_livrare_comanda':
|
||||||
|
politica_de_livrare_comanda = DeliveryPolicys(page)
|
||||||
|
page.add(politica_de_livrare_comanda.build())
|
||||||
|
page.update()
|
||||||
|
return
|
||||||
|
|
||||||
|
if route == '/gdpr':
|
||||||
|
gdpr = GDPR(page)
|
||||||
|
page.add(gdpr.build())
|
||||||
|
page.update()
|
||||||
|
return
|
||||||
|
|
||||||
# 5) Fallback 404
|
# 5) Fallback 404
|
||||||
page.add(ft.Text("404: Page not found"))
|
page.add(ft.Text("404: Page not found"))
|
||||||
page.update()
|
page.update()
|
||||||
|
|||||||
@@ -14,25 +14,28 @@ class Login:
|
|||||||
self.register = Register(self.page, self.auth, self)
|
self.register = Register(self.page, self.auth, self)
|
||||||
|
|
||||||
def on_login_btn_click(self, e):
|
def on_login_btn_click(self, e):
|
||||||
email = self.email.value
|
try:
|
||||||
password = self.password.value
|
email = self.email.value
|
||||||
password_hash = self.user_manager.hash_password(password)
|
password = self.password.value
|
||||||
user = self.user_manager.authenticate_user(email, password_hash)
|
password_hash = self.user_manager.hash_password(password)
|
||||||
if user:
|
user = self.user_manager.authenticate_user(email, password_hash)
|
||||||
self.page.client_storage.set("is_authenticated", True)
|
if user:
|
||||||
self.page.session.set("user", user)
|
self.page.client_storage.set("is_authenticated", True)
|
||||||
self.error_message.value = ''
|
self.page.session.set("user", user)
|
||||||
self.error_message.update()
|
self.error_message.value = ''
|
||||||
if user['role'] == 'admin':
|
self.error_message.update()
|
||||||
self.page.go('/admin')
|
if user['role'] == 'admin':
|
||||||
else:
|
self.page.go('/admin')
|
||||||
if user['name'] is None or len(user['name'])<=1:
|
|
||||||
self.page.go("/profil")
|
|
||||||
else:
|
else:
|
||||||
self.page.go('/')
|
if user['name'] is None or len(user['name'])<=1:
|
||||||
else:
|
self.page.go("/profil")
|
||||||
self.error_message.value = 'E-mail sau parola sunt gresite!'
|
else:
|
||||||
self.error_message.update()
|
self.page.go('/')
|
||||||
|
else:
|
||||||
|
self.error_message.value = 'E-mail sau parola sunt gresite!'
|
||||||
|
self.error_message.update()
|
||||||
|
except Exception as e:
|
||||||
|
print("Unable to login, error: ", e)
|
||||||
|
|
||||||
def on_register_btn_click(self, e):
|
def on_register_btn_click(self, e):
|
||||||
self.auth.placeholder.content = self.register.build()
|
self.auth.placeholder.content = self.register.build()
|
||||||
|
|||||||
@@ -92,12 +92,15 @@ class Register:
|
|||||||
if self._check_repeat_password(password, repeat_password):
|
if self._check_repeat_password(password, repeat_password):
|
||||||
print("Password is valid!")
|
print("Password is valid!")
|
||||||
password_hash = self.users_manager.hash_password(password)
|
password_hash = self.users_manager.hash_password(password)
|
||||||
self.users_manager.register_user(email, password_hash)
|
if self.users_manager.register_user(email, password_hash):
|
||||||
self.error_message.value = "Inregistrarea a avut loc cu succes, va puteti autentifica!"
|
self.error_message.value = "Inregistrarea a avut loc cu succes, va puteti autentifica!"
|
||||||
self.error_message.color = ft.Colors.GREEN
|
self.error_message.color = ft.Colors.GREEN
|
||||||
self.error_message.update()
|
self.error_message.update()
|
||||||
time.sleep(3)
|
time.sleep(3)
|
||||||
self.on_login_btn_click('')
|
self.on_login_btn_click('')
|
||||||
|
else:
|
||||||
|
self.error_message.value = 'Exita deja un cont cu acet email. Daca ati fost invitat sau ati uitat prola accesati rubrica "Ai uitat parola?"'
|
||||||
|
self.error_message.update()
|
||||||
|
|
||||||
def build(self):
|
def build(self):
|
||||||
return ft.Column(
|
return ft.Column(
|
||||||
|
|||||||
@@ -94,6 +94,8 @@ class Category:
|
|||||||
self.products_group.controls.clear()
|
self.products_group.controls.clear()
|
||||||
self.add_products(buffer)
|
self.add_products(buffer)
|
||||||
self.products_group.update()
|
self.products_group.update()
|
||||||
|
self.searchbar.value = ''
|
||||||
|
self.searchbar.update()
|
||||||
|
|
||||||
def on_profile_btn_click(self, e):
|
def on_profile_btn_click(self, e):
|
||||||
self.page.go('/profil')
|
self.page.go('/profil')
|
||||||
|
|||||||
BIN
UI_V2/pages/details/__pycache__/about_us.cpython-313.pyc
Normal file
BIN
UI_V2/pages/details/__pycache__/about_us.cpython-313.pyc
Normal file
Binary file not shown.
BIN
UI_V2/pages/details/__pycache__/cancel_policy.cpython-313.pyc
Normal file
BIN
UI_V2/pages/details/__pycache__/cancel_policy.cpython-313.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
UI_V2/pages/details/__pycache__/delivery_policy.cpython-313.pyc
Normal file
BIN
UI_V2/pages/details/__pycache__/delivery_policy.cpython-313.pyc
Normal file
Binary file not shown.
BIN
UI_V2/pages/details/__pycache__/gdpr_policy.cpython-313.pyc
Normal file
BIN
UI_V2/pages/details/__pycache__/gdpr_policy.cpython-313.pyc
Normal file
Binary file not shown.
Binary file not shown.
55
UI_V2/pages/details/about_us.py
Normal file
55
UI_V2/pages/details/about_us.py
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import flet as ft
|
||||||
|
import json
|
||||||
|
|
||||||
|
class AboutUS:
|
||||||
|
def __init__(self, page:ft.Page):
|
||||||
|
self.page = page
|
||||||
|
self.data = self.load_data()
|
||||||
|
self.company_name = ft.Text(value=self.data['company_name'])
|
||||||
|
self.vat = ft.Text(value=self.data['vat'])
|
||||||
|
self.register_number = ft.Text(value=self.data['register_number'])
|
||||||
|
self.address = ft.Text(value=self.data['address'])
|
||||||
|
|
||||||
|
def load_data(self):
|
||||||
|
try:
|
||||||
|
with open('instance/company_data.json', 'r', encoding='utf-8') as f:
|
||||||
|
data = json.load(f)
|
||||||
|
return data
|
||||||
|
except FileNotFoundError:
|
||||||
|
return {
|
||||||
|
'company_name': '',
|
||||||
|
'vat': '',
|
||||||
|
'register_number': '',
|
||||||
|
'address': ''
|
||||||
|
}
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
self.page.snack_bar = ft.SnackBar(ft.Text('Eroare: fișierul company_data.json este corupt.'))
|
||||||
|
self.page.snack_bar.open = True
|
||||||
|
self.page.update()
|
||||||
|
return None
|
||||||
|
except Exception as ex:
|
||||||
|
self.page.snack_bar = ft.SnackBar(ft.Text(f'Eroare la citirea datelor companiei: {ex}'))
|
||||||
|
self.page.snack_bar.open = True
|
||||||
|
self.page.update()
|
||||||
|
return None
|
||||||
|
|
||||||
|
def build(self):
|
||||||
|
return ft.Container(
|
||||||
|
content=ft.Row(
|
||||||
|
[
|
||||||
|
ft.Image(src="images/tainagustului.png", width=100),
|
||||||
|
ft.Column(
|
||||||
|
[
|
||||||
|
ft.Text("Despre noi", size=18, weight=ft.FontWeight.BOLD),
|
||||||
|
self.company_name,
|
||||||
|
self.vat,
|
||||||
|
self.register_number,
|
||||||
|
self.address
|
||||||
|
]
|
||||||
|
)
|
||||||
|
],
|
||||||
|
alignment=ft.MainAxisAlignment.CENTER,
|
||||||
|
vertical_alignment=ft.CrossAxisAlignment.CENTER,
|
||||||
|
scroll=ft.ScrollMode.ADAPTIVE
|
||||||
|
)
|
||||||
|
)
|
||||||
44
UI_V2/pages/details/cancel_policy.py
Normal file
44
UI_V2/pages/details/cancel_policy.py
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import flet as ft
|
||||||
|
import json
|
||||||
|
|
||||||
|
class CancelPolicy:
|
||||||
|
def __init__(self, page: ft.Page):
|
||||||
|
self.page = page
|
||||||
|
|
||||||
|
def load_data(self):
|
||||||
|
try:
|
||||||
|
with open('instance/policies.json', 'r', encoding='utf-8') as f:
|
||||||
|
data = json.load(f)
|
||||||
|
return data
|
||||||
|
except FileNotFoundError:
|
||||||
|
return {
|
||||||
|
'confidentialty_policy': '',
|
||||||
|
'delivery_policy': '',
|
||||||
|
'cancel_policy': '',
|
||||||
|
'gdpr': '',
|
||||||
|
'terms_and_conditions': ''
|
||||||
|
}
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
self.page.snack_bar = ft.SnackBar(ft.Text('Eroare: fișierul policies.json este corupt.'))
|
||||||
|
self.page.snack_bar.open = True
|
||||||
|
self.page.update()
|
||||||
|
return None
|
||||||
|
except Exception as ex:
|
||||||
|
self.page.snack_bar = ft.SnackBar(ft.Text(f'Eroare la citirea politicilor: {ex}'))
|
||||||
|
self.page.snack_bar.open = True
|
||||||
|
self.page.update()
|
||||||
|
return None
|
||||||
|
|
||||||
|
def build(self):
|
||||||
|
return ft.Container(
|
||||||
|
content=ft.Column(
|
||||||
|
[
|
||||||
|
ft.Text("Politica de anulare comandă",size = 18, weight=ft.FontWeight.BOLD, text_align=ft.TextAlign.CENTER),
|
||||||
|
ft.Text(value=self.load_data()['cancel_policy'])
|
||||||
|
],
|
||||||
|
alignment=ft.MainAxisAlignment.START,
|
||||||
|
scroll=ft.ScrollMode.ADAPTIVE
|
||||||
|
),
|
||||||
|
padding=10,
|
||||||
|
expand=True
|
||||||
|
)
|
||||||
44
UI_V2/pages/details/confidentialty_policy.py
Normal file
44
UI_V2/pages/details/confidentialty_policy.py
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import flet as ft
|
||||||
|
import json
|
||||||
|
|
||||||
|
class ConfidentialtyPolicy:
|
||||||
|
def __init__(self, page: ft.Page):
|
||||||
|
self.page = page
|
||||||
|
|
||||||
|
def load_data(self):
|
||||||
|
try:
|
||||||
|
with open('instance/policies.json', 'r', encoding='utf-8') as f:
|
||||||
|
data = json.load(f)
|
||||||
|
return data
|
||||||
|
except FileNotFoundError:
|
||||||
|
return {
|
||||||
|
'confidentialty_policy': '',
|
||||||
|
'delivery_policy': '',
|
||||||
|
'cancel_policy': '',
|
||||||
|
'gdpr': '',
|
||||||
|
'terms_and_conditions': ''
|
||||||
|
}
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
self.page.snack_bar = ft.SnackBar(ft.Text('Eroare: fișierul policies.json este corupt.'))
|
||||||
|
self.page.snack_bar.open = True
|
||||||
|
self.page.update()
|
||||||
|
return None
|
||||||
|
except Exception as ex:
|
||||||
|
self.page.snack_bar = ft.SnackBar(ft.Text(f'Eroare la citirea politicilor: {ex}'))
|
||||||
|
self.page.snack_bar.open = True
|
||||||
|
self.page.update()
|
||||||
|
return None
|
||||||
|
|
||||||
|
def build(self):
|
||||||
|
return ft.Container(
|
||||||
|
content=ft.Column(
|
||||||
|
[
|
||||||
|
ft.Text("Politica de confidențialitate",size = 18, weight=ft.FontWeight.BOLD, text_align=ft.TextAlign.CENTER),
|
||||||
|
ft.Text(value=self.load_data()['confidentialty_policy'])
|
||||||
|
],
|
||||||
|
alignment=ft.MainAxisAlignment.START,
|
||||||
|
scroll=ft.ScrollMode.ADAPTIVE
|
||||||
|
),
|
||||||
|
padding=10,
|
||||||
|
expand=True
|
||||||
|
)
|
||||||
44
UI_V2/pages/details/delivery_policy.py
Normal file
44
UI_V2/pages/details/delivery_policy.py
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import flet as ft
|
||||||
|
import json
|
||||||
|
|
||||||
|
class DeliveryPolicys:
|
||||||
|
def __init__(self, page: ft.Page):
|
||||||
|
self.page = page
|
||||||
|
|
||||||
|
def load_data(self):
|
||||||
|
try:
|
||||||
|
with open('instance/policies.json', 'r', encoding='utf-8') as f:
|
||||||
|
data = json.load(f)
|
||||||
|
return data
|
||||||
|
except FileNotFoundError:
|
||||||
|
return {
|
||||||
|
'confidentialty_policy': '',
|
||||||
|
'delivery_policy': '',
|
||||||
|
'cancel_policy': '',
|
||||||
|
'gdpr': '',
|
||||||
|
'terms_and_conditions': ''
|
||||||
|
}
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
self.page.snack_bar = ft.SnackBar(ft.Text('Eroare: fișierul policies.json este corupt.'))
|
||||||
|
self.page.snack_bar.open = True
|
||||||
|
self.page.update()
|
||||||
|
return None
|
||||||
|
except Exception as ex:
|
||||||
|
self.page.snack_bar = ft.SnackBar(ft.Text(f'Eroare la citirea politicilor: {ex}'))
|
||||||
|
self.page.snack_bar.open = True
|
||||||
|
self.page.update()
|
||||||
|
return None
|
||||||
|
|
||||||
|
def build(self):
|
||||||
|
return ft.Container(
|
||||||
|
content=ft.Column(
|
||||||
|
[
|
||||||
|
ft.Text("Politica de livrare comandă",size = 18, weight=ft.FontWeight.BOLD, text_align=ft.TextAlign.CENTER),
|
||||||
|
ft.Text(value=self.load_data()['delivery_policy'])
|
||||||
|
],
|
||||||
|
alignment=ft.MainAxisAlignment.START,
|
||||||
|
scroll=ft.ScrollMode.ADAPTIVE
|
||||||
|
),
|
||||||
|
padding=10,
|
||||||
|
expand=True
|
||||||
|
)
|
||||||
44
UI_V2/pages/details/gdpr_policy.py
Normal file
44
UI_V2/pages/details/gdpr_policy.py
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import flet as ft
|
||||||
|
import json
|
||||||
|
|
||||||
|
class GDPR:
|
||||||
|
def __init__(self, page: ft.Page):
|
||||||
|
self.page = page
|
||||||
|
|
||||||
|
def load_data(self):
|
||||||
|
try:
|
||||||
|
with open('instance/policies.json', 'r', encoding='utf-8') as f:
|
||||||
|
data = json.load(f)
|
||||||
|
return data
|
||||||
|
except FileNotFoundError:
|
||||||
|
return {
|
||||||
|
'confidentialty_policy': '',
|
||||||
|
'delivery_policy': '',
|
||||||
|
'cancel_policy': '',
|
||||||
|
'gdpr': '',
|
||||||
|
'terms_and_conditions': ''
|
||||||
|
}
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
self.page.snack_bar = ft.SnackBar(ft.Text('Eroare: fișierul policies.json este corupt.'))
|
||||||
|
self.page.snack_bar.open = True
|
||||||
|
self.page.update()
|
||||||
|
return None
|
||||||
|
except Exception as ex:
|
||||||
|
self.page.snack_bar = ft.SnackBar(ft.Text(f'Eroare la citirea politicilor: {ex}'))
|
||||||
|
self.page.snack_bar.open = True
|
||||||
|
self.page.update()
|
||||||
|
return None
|
||||||
|
|
||||||
|
def build(self):
|
||||||
|
return ft.Container(
|
||||||
|
content=ft.Column(
|
||||||
|
[
|
||||||
|
ft.Text("Politica GDPR (siguranța datelor cu caracter personal)",size = 18, weight=ft.FontWeight.BOLD, text_align=ft.TextAlign.CENTER),
|
||||||
|
ft.Text(value=self.load_data()['gdpr'])
|
||||||
|
],
|
||||||
|
alignment=ft.MainAxisAlignment.START,
|
||||||
|
scroll=ft.ScrollMode.ADAPTIVE
|
||||||
|
),
|
||||||
|
padding=10,
|
||||||
|
expand=True
|
||||||
|
)
|
||||||
44
UI_V2/pages/details/terms_and_conditions.py
Normal file
44
UI_V2/pages/details/terms_and_conditions.py
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import flet as ft
|
||||||
|
import json
|
||||||
|
|
||||||
|
class TermsAndConditions:
|
||||||
|
def __init__(self, page: ft.Page):
|
||||||
|
self.page = page
|
||||||
|
|
||||||
|
def load_data(self):
|
||||||
|
try:
|
||||||
|
with open('instance/policies.json', 'r', encoding='utf-8') as f:
|
||||||
|
data = json.load(f)
|
||||||
|
return data
|
||||||
|
except FileNotFoundError:
|
||||||
|
return {
|
||||||
|
'confidentialty_policy': '',
|
||||||
|
'delivery_policy': '',
|
||||||
|
'cancel_policy': '',
|
||||||
|
'gdpr': '',
|
||||||
|
'terms_and_conditions': ''
|
||||||
|
}
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
self.page.snack_bar = ft.SnackBar(ft.Text('Eroare: fișierul policies.json este corupt.'))
|
||||||
|
self.page.snack_bar.open = True
|
||||||
|
self.page.update()
|
||||||
|
return None
|
||||||
|
except Exception as ex:
|
||||||
|
self.page.snack_bar = ft.SnackBar(ft.Text(f'Eroare la citirea politicilor: {ex}'))
|
||||||
|
self.page.snack_bar.open = True
|
||||||
|
self.page.update()
|
||||||
|
return None
|
||||||
|
|
||||||
|
def build(self):
|
||||||
|
return ft.Container(
|
||||||
|
content=ft.Column(
|
||||||
|
[
|
||||||
|
ft.Text("Termeni si conditii",size = 18, weight=ft.FontWeight.BOLD, text_align=ft.TextAlign.CENTER),
|
||||||
|
ft.Text(value=self.load_data()['terms_and_conditions'])
|
||||||
|
],
|
||||||
|
alignment=ft.MainAxisAlignment.START,
|
||||||
|
scroll=ft.ScrollMode.ADAPTIVE
|
||||||
|
),
|
||||||
|
padding=10,
|
||||||
|
expand=True
|
||||||
|
)
|
||||||
@@ -26,7 +26,7 @@ class Home:
|
|||||||
expand=True,
|
expand=True,
|
||||||
width=1000
|
width=1000
|
||||||
)
|
)
|
||||||
self.products = self.products_manager.get_all()
|
self.products = self.products_manager.get_all()[:20]
|
||||||
self.add_products(self.products)
|
self.add_products(self.products)
|
||||||
|
|
||||||
self.searchbar = ft.TextField(
|
self.searchbar = ft.TextField(
|
||||||
@@ -64,6 +64,7 @@ class Home:
|
|||||||
self.products_group.controls.clear()
|
self.products_group.controls.clear()
|
||||||
self.add_products(buffer)
|
self.add_products(buffer)
|
||||||
self.page.session.set("search_for", None)
|
self.page.session.set("search_for", None)
|
||||||
|
self.searchbar.value = ''
|
||||||
|
|
||||||
def on_acasa_btn_click(self, e):
|
def on_acasa_btn_click(self, e):
|
||||||
self.page.go('/')
|
self.page.go('/')
|
||||||
@@ -158,12 +159,32 @@ class Home:
|
|||||||
def on_search_btn_click(self, e):
|
def on_search_btn_click(self, e):
|
||||||
search = self.searchbar.value
|
search = self.searchbar.value
|
||||||
buffer = []
|
buffer = []
|
||||||
for product in self.products:
|
for product in self.products_manager.get_all():
|
||||||
if search.lower() in product['name'].lower():
|
if search.lower() in product['name'].lower():
|
||||||
buffer.append(product)
|
buffer.append(product)
|
||||||
self.products_group.controls.clear()
|
self.products_group.controls.clear()
|
||||||
self.add_products(buffer)
|
self.add_products(buffer)
|
||||||
self.products_group.update()
|
self.products_group.update()
|
||||||
|
self.searchbar.value = ''
|
||||||
|
self.searchbar.update()
|
||||||
|
|
||||||
|
def on_about_us_btn_click(self, e):
|
||||||
|
self.page.go('/about_us')
|
||||||
|
|
||||||
|
def on_terms_and_cond_btn_click(self, e):
|
||||||
|
self.page.go("/termeni_si_conditii")
|
||||||
|
|
||||||
|
def on_cancel_policy_btn_click(self, e):
|
||||||
|
self.page.go("/politica_de_anulare_comanda")
|
||||||
|
|
||||||
|
def on_confidentiality_policy_btn_click(self, e):
|
||||||
|
self.page.go('/politica_de_confidentialitate')
|
||||||
|
|
||||||
|
def on_delivery_policy_btn_click(self, e):
|
||||||
|
self.page.go("/politica_de_livrare_comanda")
|
||||||
|
|
||||||
|
def on_gdpr_btn_click(self, e):
|
||||||
|
self.page.go("/gdpr")
|
||||||
|
|
||||||
def build(self):
|
def build(self):
|
||||||
return ft.Container(
|
return ft.Container(
|
||||||
@@ -201,10 +222,33 @@ class Home:
|
|||||||
alignment=ft.MainAxisAlignment.CENTER,
|
alignment=ft.MainAxisAlignment.CENTER,
|
||||||
width=1000
|
width=1000
|
||||||
),
|
),
|
||||||
self.products_group
|
self.products_group,
|
||||||
|
ft.Divider(height=1),
|
||||||
|
ft.Row(
|
||||||
|
[
|
||||||
|
ft.Column(
|
||||||
|
[
|
||||||
|
ft.TextButton("Despre noi", on_click=self.on_about_us_btn_click, icon=ft.Icons.INFO),
|
||||||
|
ft.TextButton("Termeni si conditii", on_click=self.on_terms_and_cond_btn_click, icon=ft.Icons.INFO),
|
||||||
|
ft.TextButton("Politica de anulare comanda",on_click=self.on_cancel_policy_btn_click, icon=ft.Icons.INFO),
|
||||||
|
ft.TextButton("Politica de confidentialitate",on_click=self.on_confidentiality_policy_btn_click, icon=ft.Icons.INFO),
|
||||||
|
ft.TextButton("Politica de livrare comanda",on_click=self.on_delivery_policy_btn_click, icon=ft.Icons.INFO),
|
||||||
|
ft.TextButton("Politica GDPR (siguranța datelor cu caracter personal)",on_click=self.on_gdpr_btn_click, icon=ft.Icons.INFO)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
ft.Column(
|
||||||
|
[
|
||||||
|
ft.TextButton("TainaGustului", icon=ft.Icons.FACEBOOK)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
],
|
||||||
|
alignment=ft.MainAxisAlignment.SPACE_AROUND,
|
||||||
|
vertical_alignment=ft.CrossAxisAlignment.START
|
||||||
|
)
|
||||||
],
|
],
|
||||||
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
|
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
|
||||||
expand=True
|
expand=True,
|
||||||
|
width=1000
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
scroll=ft.ScrollMode.ADAPTIVE,
|
scroll=ft.ScrollMode.ADAPTIVE,
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ class ProductPage:
|
|||||||
ft.Stack(
|
ft.Stack(
|
||||||
[
|
[
|
||||||
ft.Image(
|
ft.Image(
|
||||||
src=f"images/{sp['image']}",
|
src=f"{sp['image']}",
|
||||||
fit=ft.ImageFit.COVER,
|
fit=ft.ImageFit.COVER,
|
||||||
repeat=ft.ImageRepeat.NO_REPEAT,
|
repeat=ft.ImageRepeat.NO_REPEAT,
|
||||||
border_radius=ft.border_radius.all(5),
|
border_radius=ft.border_radius.all(5),
|
||||||
@@ -104,7 +104,7 @@ class ProductPage:
|
|||||||
],
|
],
|
||||||
alignment=ft.MainAxisAlignment.CENTER
|
alignment=ft.MainAxisAlignment.CENTER
|
||||||
),
|
),
|
||||||
ft.IconButton(ft.Icons.ADD_SHOPPING_CART, on_click=lambda e, i=sp: self.on_sp_add_to_cart_click(i))
|
#ft.IconButton(ft.Icons.ADD_SHOPPING_CART, on_click=lambda e, i=sp: self.on_sp_add_to_cart_click(i))
|
||||||
],
|
],
|
||||||
width=200,
|
width=200,
|
||||||
alignment=ft.MainAxisAlignment.SPACE_BETWEEN
|
alignment=ft.MainAxisAlignment.SPACE_BETWEEN
|
||||||
@@ -358,7 +358,9 @@ class ProductPage:
|
|||||||
self.page.go('/')
|
self.page.go('/')
|
||||||
|
|
||||||
def on_sp_product_click(self, product):
|
def on_sp_product_click(self, product):
|
||||||
self.page.session.set('product', product)
|
self.page.session.set("product", product)
|
||||||
|
name = product['name'].replace(" ", "-").lower()
|
||||||
|
self.page.go(f'/produs/{name}')
|
||||||
|
|
||||||
def ask_for_create_user(self):
|
def ask_for_create_user(self):
|
||||||
self.page.open(self.ask_for_login_dialog)
|
self.page.open(self.ask_for_login_dialog)
|
||||||
|
|||||||
@@ -9,15 +9,46 @@ class ProfilePage:
|
|||||||
self.company_manager = Company()
|
self.company_manager = Company()
|
||||||
self.user = self.page.session.get("user")
|
self.user = self.page.session.get("user")
|
||||||
self.company = self.company_manager.get_company(self.user['id'])
|
self.company = self.company_manager.get_company(self.user['id'])
|
||||||
self.user_name = ft.TextField(label="Nume si Prenume", value=self.user['name'])
|
prenume = ''
|
||||||
|
if "@default.com" not in self.user['email']:
|
||||||
|
if '~' in self.user['name']:
|
||||||
|
prenume = self.user['name'].split('~')[0]
|
||||||
|
self.first_name = ft.TextField(
|
||||||
|
label="Prenume",
|
||||||
|
value=prenume
|
||||||
|
)
|
||||||
|
nume = ''
|
||||||
|
if "@default.com" not in self.user['email']:
|
||||||
|
if '~' in self.user['name']:
|
||||||
|
nume = self.user['name'].split('~')[1]
|
||||||
|
self.last_name = ft.TextField(
|
||||||
|
label="Nume",
|
||||||
|
value=nume
|
||||||
|
)
|
||||||
self.email = ft.TextField(label="E-mail", value=self.user['email'], read_only=True)
|
self.email = ft.TextField(label="E-mail", value=self.user['email'], read_only=True)
|
||||||
self.phone = ft.TextField(label="Telefon", value=self.user['phone'])
|
self.phone = ft.TextField(label="Telefon", value=self.user['phone'])
|
||||||
|
address = ''
|
||||||
|
if self.user['address']:
|
||||||
|
if "~" in self.user['address']:
|
||||||
|
address = self.user['address'].split("~")[0].split("%")[1]
|
||||||
|
else:
|
||||||
|
address = self.user['address'].split("%")[1]
|
||||||
self.address = ft.TextField(
|
self.address = ft.TextField(
|
||||||
label="Adresa",
|
label="Strada si numar",
|
||||||
multiline=True,
|
multiline=True,
|
||||||
min_lines=3,
|
min_lines=3,
|
||||||
max_lines=5,
|
max_lines=5,
|
||||||
value = self.user['address'].split("~")[0] if self.user['address'] else ''
|
value = address
|
||||||
|
)
|
||||||
|
city = ''
|
||||||
|
if self.user['address']:
|
||||||
|
if "~" in self.user['address']:
|
||||||
|
city = self.user['address'].split("~")[0].split("%")[0]
|
||||||
|
else:
|
||||||
|
city = self.user['address'].split("%")[0]
|
||||||
|
self.city = ft.TextField(
|
||||||
|
label="Oras",
|
||||||
|
value = city
|
||||||
)
|
)
|
||||||
self.company_name = ft.TextField(
|
self.company_name = ft.TextField(
|
||||||
label="Denumire firma",
|
label="Denumire firma",
|
||||||
@@ -39,11 +70,11 @@ class ProfilePage:
|
|||||||
value=self.company['address'] if self.company else '')
|
value=self.company['address'] if self.company else '')
|
||||||
self.second_address_placeholder = ft.Column()
|
self.second_address_placeholder = ft.Column()
|
||||||
self.second_address = ft.TextField(
|
self.second_address = ft.TextField(
|
||||||
label="Adresa de livrare",
|
label="Adresa de livrare (str, nr, oras, judet)",
|
||||||
multiline=True,
|
multiline=True,
|
||||||
min_lines=3,
|
min_lines=3,
|
||||||
max_lines=5,
|
max_lines=5,
|
||||||
value=self.user['address'].split("~")[1] if self.user['address'] and len(self.user['address'].split("~"))>1 else ''
|
value=self.user['address'].split("~")[1] if self.user['address'] and "~" in self.user['address'] and len(self.user['address'].split("~"))>1 else ''
|
||||||
)
|
)
|
||||||
self.second_address_placeholder =ft.Column()
|
self.second_address_placeholder =ft.Column()
|
||||||
self.order_placeholder =ft.Column()
|
self.order_placeholder =ft.Column()
|
||||||
@@ -75,7 +106,7 @@ class ProfilePage:
|
|||||||
self.order_placeholder.controls.append(self.company_address)
|
self.order_placeholder.controls.append(self.company_address)
|
||||||
self.order_placeholder.update()
|
self.order_placeholder.update()
|
||||||
|
|
||||||
def check_inserted_user_data(self, username, phone, address):
|
def check_inserted_user_data(self, username, phone, address, city):
|
||||||
found = False
|
found = False
|
||||||
if username is None or len(username)< 1:
|
if username is None or len(username)< 1:
|
||||||
found = True
|
found = True
|
||||||
@@ -83,6 +114,8 @@ class ProfilePage:
|
|||||||
found = True
|
found = True
|
||||||
if address is None or len(address)< 1:
|
if address is None or len(address)< 1:
|
||||||
found = True
|
found = True
|
||||||
|
if city is None or len(city)< 1:
|
||||||
|
found = True
|
||||||
if found:
|
if found:
|
||||||
self.error_message.value = "Toate campurile sunt obligatori!"
|
self.error_message.value = "Toate campurile sunt obligatori!"
|
||||||
self.error_message.color = ft.Colors.RED
|
self.error_message.color = ft.Colors.RED
|
||||||
@@ -115,14 +148,14 @@ class ProfilePage:
|
|||||||
return found
|
return found
|
||||||
|
|
||||||
def on_save_btn_click(self, e):
|
def on_save_btn_click(self, e):
|
||||||
username = self.user_name.value
|
username = self.first_name.value + "~" + self.last_name.value
|
||||||
phone = self.phone.value
|
phone = self.phone.value
|
||||||
address = self.address.value
|
address = self.city.value+"%"+self.address.value
|
||||||
if self.is_second_address:
|
if self.is_second_address:
|
||||||
if self.check_second_address_inserted(self.second_address.value):
|
if self.check_second_address_inserted(self.second_address.value):
|
||||||
return
|
return
|
||||||
address = self.address.value + '~' + self.second_address.value
|
address = self.city.value+"%"+self.address.value + '~' + self.second_address.value
|
||||||
if self.check_inserted_user_data(username, phone, address):
|
if self.check_inserted_user_data(username, phone, self.address.value, self.city.value):
|
||||||
return
|
return
|
||||||
self.user_manager.update_user_data(username, phone, address, self.user['id'])
|
self.user_manager.update_user_data(username, phone, address, self.user['id'])
|
||||||
|
|
||||||
@@ -148,6 +181,35 @@ class ProfilePage:
|
|||||||
self.error_message.value = "Profilul a fost salvat!"
|
self.error_message.value = "Profilul a fost salvat!"
|
||||||
self.error_message.color = ft.Colors.GREEN
|
self.error_message.color = ft.Colors.GREEN
|
||||||
self.error_message.update()
|
self.error_message.update()
|
||||||
|
self.user = self.user_manager.get(self.user['id'])
|
||||||
|
self.page.session.set('user',self.user)
|
||||||
|
self.first_name.value=self.user['name'].split('~')[0]
|
||||||
|
self.first_name.update()
|
||||||
|
self.last_name.value=self.user['name'].split('~')[1]
|
||||||
|
self.last_name.update()
|
||||||
|
self.phone.value = self.user['phone']
|
||||||
|
self.phone.update()
|
||||||
|
self.address.value = self.user['address'].split("~")[0].split("%")[1] if self.user['address'] else ''
|
||||||
|
self.address.update()
|
||||||
|
self.city.value = self.user['address'].split("~")[0].split("%")[0] if self.user['address'] else ''
|
||||||
|
self.city.update()
|
||||||
|
try:
|
||||||
|
self.company = self.company_manager.get_company(self.user['id'])
|
||||||
|
self.company_name.value=self.company['name'] if self.company else ''
|
||||||
|
self.company_name.update()
|
||||||
|
self.vat.value = self.company['vat'] if self.company else ''
|
||||||
|
self.vat.update()
|
||||||
|
self.register_number.value=self.company['register_number'] if self.company else ''
|
||||||
|
self.register_number.update()
|
||||||
|
self.company_address.value=self.company['address'] if self.company else ''
|
||||||
|
self.company_address.update()
|
||||||
|
except Exception as e:
|
||||||
|
print ("Unable to save company data", e)
|
||||||
|
try:
|
||||||
|
self.second_address.value=self.user['address'].split("~")[1] if self.user['address'] and len(self.user['address'].split("~"))>1 else ''
|
||||||
|
self.second_address.update()
|
||||||
|
except Exception as e:
|
||||||
|
print("Unable to save delivery address.", e)
|
||||||
|
|
||||||
def on_back_btn_click(self, e):
|
def on_back_btn_click(self, e):
|
||||||
self.page.go('/')
|
self.page.go('/')
|
||||||
@@ -171,10 +233,12 @@ class ProfilePage:
|
|||||||
alignment=ft.MainAxisAlignment.END
|
alignment=ft.MainAxisAlignment.END
|
||||||
),
|
),
|
||||||
ft.Icon(name=ft.Icons.ACCOUNT_CIRCLE, size=100),
|
ft.Icon(name=ft.Icons.ACCOUNT_CIRCLE, size=100),
|
||||||
self.user_name,
|
self.first_name,
|
||||||
|
self.last_name,
|
||||||
self.email,
|
self.email,
|
||||||
self.phone,
|
self.phone,
|
||||||
self.address,
|
self.address,
|
||||||
|
self.city,
|
||||||
ft.Divider(),
|
ft.Divider(),
|
||||||
ft.Text("Adresa de livrare difera de adresa de domiciliu?", text_align=ft.TextAlign.CENTER),
|
ft.Text("Adresa de livrare difera de adresa de domiciliu?", text_align=ft.TextAlign.CENTER),
|
||||||
ft.Button("Adauga adresa livrare", width=400, on_click=self.on_second_address_btn_click),
|
ft.Button("Adauga adresa livrare", width=400, on_click=self.on_second_address_btn_click),
|
||||||
|
|||||||
@@ -3,19 +3,26 @@ from dbActions.orders import Orders
|
|||||||
from dbActions.products import Products
|
from dbActions.products import Products
|
||||||
from dbActions.company import Company
|
from dbActions.company import Company
|
||||||
from dbActions.users import Users
|
from dbActions.users import Users
|
||||||
|
from dbActions.fidelity_cards import FidelityCards
|
||||||
|
from dbActions.netopia import Netopia
|
||||||
|
from helpers.emails import send_gmail
|
||||||
|
from helpers.netopia import start_card_payment
|
||||||
|
import re
|
||||||
|
|
||||||
class Cart:
|
class Cart:
|
||||||
def __init__(self, page: ft.Page):
|
def __init__(self, page: ft.Page):
|
||||||
self.page = page
|
self.page = page
|
||||||
self.user = self.page.session.get('user')
|
self.user = self.page.session.get('user')
|
||||||
self.orders = Orders()
|
self.orders_manager = Orders()
|
||||||
self.productsDB = Products()
|
self.productsDB = Products()
|
||||||
self.company_manager = Company()
|
self.company_manager = Company()
|
||||||
self.user_manager = Users()
|
self.user_manager = Users()
|
||||||
|
self.card_manager = FidelityCards()
|
||||||
|
self.netopia_manager = Netopia()
|
||||||
self.products = []
|
self.products = []
|
||||||
self.is_second_address = None
|
self.is_second_address = None
|
||||||
self.is_company = None
|
self.is_company = None
|
||||||
|
self.pret_total = ft.Text("Pret total: 0", weight=ft.FontWeight.BOLD)
|
||||||
self.delete_dialog = ft.AlertDialog(
|
self.delete_dialog = ft.AlertDialog(
|
||||||
title=ft.Text("Stergeti?"),
|
title=ft.Text("Stergeti?"),
|
||||||
actions=[
|
actions=[
|
||||||
@@ -24,9 +31,9 @@ class Cart:
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
self.on_hold_orders = self.orders.get_on_hold_order(self.user['id'])
|
self.on_hold_orders = self.orders_manager.get_on_hold_order(self.user['id'])
|
||||||
if self.on_hold_orders:
|
if self.on_hold_orders:
|
||||||
self.order_products = self.orders.get_order_products(self.on_hold_orders['id'])
|
self.order_products = self.orders_manager.get_order_products(self.on_hold_orders['id'])
|
||||||
|
|
||||||
for product in self.order_products:
|
for product in self.order_products:
|
||||||
self.products.append(
|
self.products.append(
|
||||||
@@ -70,36 +77,65 @@ class Cart:
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
if '@default.com' not in self.user['email']:
|
self.all_orders = self.orders_manager.get_orders_for_user(self.page.session.get('user')['id'])
|
||||||
self.all_orders = self.orders.get_orders_for_user(self.page.session.get('user')['id'])
|
self.all_orders = self.all_orders[::-1]
|
||||||
self.all_orders = self.all_orders[::-1]
|
self.orders_manager_list = ft.ListView(
|
||||||
self.orders_list = ft.ListView(
|
controls=self.create_history_list(self.all_orders),
|
||||||
controls=self.create_history_list(self.all_orders),
|
spacing=10,
|
||||||
spacing=10,
|
expand=True
|
||||||
expand=True
|
)
|
||||||
)
|
|
||||||
self.user = self.page.session.get("user")
|
self.user = self.page.session.get("user")
|
||||||
self.company = self.company_manager.get_company(self.user['id'])
|
self.company = self.company_manager.get_company(self.user['id'])
|
||||||
self.user_name = ft.TextField(
|
prenume = ''
|
||||||
label="Nume si Prenume",
|
if "@default.com" not in self.user['email']:
|
||||||
value=self.user['name'] if "@default.com" not in self.user['email'] else None
|
if '~' in self.user['name']:
|
||||||
|
prenume = self.user['name'].split('~')[0]
|
||||||
|
self.first_name = ft.TextField(
|
||||||
|
label="Prenume",
|
||||||
|
value=prenume
|
||||||
)
|
)
|
||||||
|
nume = ''
|
||||||
|
if "@default.com" not in self.user['email']:
|
||||||
|
if '~' in self.user['name']:
|
||||||
|
nume = self.user['name'].split('~')[1]
|
||||||
|
self.last_name = ft.TextField(
|
||||||
|
label="Nume",
|
||||||
|
value=nume
|
||||||
|
)
|
||||||
|
|
||||||
self.email = ft.TextField(
|
self.email = ft.TextField(
|
||||||
label="E-mail",
|
label="E-mail",
|
||||||
value=self.user['email'] if "@default.com" not in self.user['email'] else None,
|
value=self.user['email'] if "@default.com" not in self.user['email'] else None,
|
||||||
read_only=True
|
read_only=True if "@default.com" not in self.user['email'] else False
|
||||||
)
|
)
|
||||||
self.phone = ft.TextField(
|
self.phone = ft.TextField(
|
||||||
label="Telefon",
|
label="Telefon",
|
||||||
value=self.user['phone'] if "@default.com" not in self.user['email'] else None
|
value=self.user['phone'] if "@default.com" not in self.user['email'] else None
|
||||||
)
|
)
|
||||||
|
address = ''
|
||||||
|
if self.user['address']:
|
||||||
|
if "~" in self.user['address']:
|
||||||
|
address = self.user['address'].split("~")[0].split("%")[1]
|
||||||
|
else:
|
||||||
|
address = self.user['address'].split("%")[1]
|
||||||
self.address = ft.TextField(
|
self.address = ft.TextField(
|
||||||
label="Adresa",
|
label="Strada si numar",
|
||||||
multiline=True,
|
multiline=True,
|
||||||
min_lines=3,
|
min_lines=3,
|
||||||
max_lines=5,
|
max_lines=5,
|
||||||
value = self.user['address'].split("~")[0] if self.user['address'] else ''
|
value = address
|
||||||
)
|
)
|
||||||
|
city = ''
|
||||||
|
if self.user['address']:
|
||||||
|
if "~" in self.user['address']:
|
||||||
|
city = self.user['address'].split("~")[0].split("%")[0]
|
||||||
|
else:
|
||||||
|
city = self.user['address'].split("%")[0]
|
||||||
|
self.city = ft.TextField(
|
||||||
|
label="Oras",
|
||||||
|
value = city
|
||||||
|
)
|
||||||
|
|
||||||
self.company_name = ft.TextField(
|
self.company_name = ft.TextField(
|
||||||
label="Denumire firma",
|
label="Denumire firma",
|
||||||
value=self.company['name'] if self.company else ''
|
value=self.company['name'] if self.company else ''
|
||||||
@@ -120,11 +156,11 @@ class Cart:
|
|||||||
value=self.company['address'] if self.company else '')
|
value=self.company['address'] if self.company else '')
|
||||||
self.second_address_placeholder = ft.Column()
|
self.second_address_placeholder = ft.Column()
|
||||||
self.second_address = ft.TextField(
|
self.second_address = ft.TextField(
|
||||||
label="Adresa de livrare",
|
label="Adresa de livrare (str, nr, oras, judet)",
|
||||||
multiline=True,
|
multiline=True,
|
||||||
min_lines=3,
|
min_lines=3,
|
||||||
max_lines=5,
|
max_lines=5,
|
||||||
value=self.user['address'].split("~")[1] if self.user['address'] and len(self.user['address'].split("~"))>1 else ''
|
value=self.user['address'].split("~")[1] if self.user['address'] and "~" in self.user['address'] and len(self.user['address'].split("~"))>1 else ''
|
||||||
)
|
)
|
||||||
self.second_address_placeholder =ft.Column()
|
self.second_address_placeholder =ft.Column()
|
||||||
self.order_placeholder =ft.Column()
|
self.order_placeholder =ft.Column()
|
||||||
@@ -145,10 +181,12 @@ class Cart:
|
|||||||
"Detaili de livrare",
|
"Detaili de livrare",
|
||||||
weight=ft.FontWeight.BOLD
|
weight=ft.FontWeight.BOLD
|
||||||
),
|
),
|
||||||
self.user_name,
|
self.first_name,
|
||||||
|
self.last_name,
|
||||||
self.email,
|
self.email,
|
||||||
self.phone,
|
self.phone,
|
||||||
self.address,
|
self.address,
|
||||||
|
self.city,
|
||||||
ft.Divider(),
|
ft.Divider(),
|
||||||
ft.Text("Adresa de livrare difera de adresa de domiciliu?", text_align=ft.TextAlign.CENTER),
|
ft.Text("Adresa de livrare difera de adresa de domiciliu?", text_align=ft.TextAlign.CENTER),
|
||||||
ft.Button("Adauga adresa livrare", width=500, on_click=self.on_second_address_btn_click),
|
ft.Button("Adauga adresa livrare", width=500, on_click=self.on_second_address_btn_click),
|
||||||
@@ -195,20 +233,22 @@ class Cart:
|
|||||||
vertical_alignment=ft.CrossAxisAlignment.START
|
vertical_alignment=ft.CrossAxisAlignment.START
|
||||||
)
|
)
|
||||||
self.order_list_placeholder = ft.Column()
|
self.order_list_placeholder = ft.Column()
|
||||||
if '@default.com' not in self.user['email']:
|
self.order_list_placeholder.controls.append(self.orders_manager_list)
|
||||||
self.order_list_placeholder.controls.append(
|
|
||||||
ft.Text(
|
|
||||||
"Istoric comenzi",
|
|
||||||
weight=ft.FontWeight.BOLD
|
|
||||||
)
|
|
||||||
)
|
|
||||||
self.order_list_placeholder.controls.append(self.orders_list)
|
|
||||||
|
|
||||||
self.item_to_be_deleted = None
|
self.item_to_be_deleted = None
|
||||||
|
|
||||||
self.page.add(self.delete_dialog)
|
self.page.add(self.delete_dialog)
|
||||||
self.page.add(self.confirm_dialog)
|
self.page.add(self.confirm_dialog)
|
||||||
|
|
||||||
|
discount_cards= self.card_manager.get_all_fidelity_cards()
|
||||||
|
_card_id = None
|
||||||
|
for card in discount_cards:
|
||||||
|
if card['phone_number'] == self.user['phone']:
|
||||||
|
_card_id = card['card_id']
|
||||||
|
break
|
||||||
|
|
||||||
|
self.card_id = ft.Text(f"Card de reducere nr. {_card_id}" if _card_id else '', weight=ft.FontWeight.BOLD)
|
||||||
|
|
||||||
def on_second_address_btn_click(self, e):
|
def on_second_address_btn_click(self, e):
|
||||||
self.is_second_address = True
|
self.is_second_address = True
|
||||||
self.second_address_placeholder.controls.append(self.second_address)
|
self.second_address_placeholder.controls.append(self.second_address)
|
||||||
@@ -229,17 +269,27 @@ class Cart:
|
|||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def order_products(self, id):
|
def get_order_products(self, id):
|
||||||
products = self.orders.get_order_products(id)
|
products = self.orders_manager.get_order_products(id)
|
||||||
|
total = 0
|
||||||
|
|
||||||
all_products = []
|
all_products = []
|
||||||
for product in products:
|
for product in products:
|
||||||
name = self.productsDB.get(product['prdouct_id'])['name']
|
item = self.productsDB.get(product['prdouct_id'])
|
||||||
|
total += item['price']
|
||||||
|
name = item['name']
|
||||||
if name not in all_products:
|
if name not in all_products:
|
||||||
all_products.append(name)
|
all_products.append(name)
|
||||||
|
try:
|
||||||
|
self.pret_total.value = f'Pret total: {total}'
|
||||||
|
self.pret_total.update()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
return ft.Text(
|
return ft.Text(
|
||||||
value=' '.join(all_products)
|
value=' '.join(all_products)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def on_go_back_button_click(self, e):
|
def on_go_back_button_click(self, e):
|
||||||
self.page.go("/")
|
self.page.go("/")
|
||||||
|
|
||||||
@@ -296,6 +346,12 @@ class Cart:
|
|||||||
]
|
]
|
||||||
|
|
||||||
def create_history_list(self, items):
|
def create_history_list(self, items):
|
||||||
|
status_value = {
|
||||||
|
'new':'Noua',
|
||||||
|
'on_hold':'In asteptare',
|
||||||
|
'in_progress': 'In lucru',
|
||||||
|
'completed':'Complete'
|
||||||
|
}
|
||||||
return [
|
return [
|
||||||
ft.Container(
|
ft.Container(
|
||||||
content=ft.Column(
|
content=ft.Column(
|
||||||
@@ -303,7 +359,7 @@ class Cart:
|
|||||||
|
|
||||||
ft.Row(
|
ft.Row(
|
||||||
[
|
[
|
||||||
ft.Icon(ft.icons.ARROW_RIGHT, size=20),
|
ft.Icon(ft.Icons.ARROW_RIGHT, size=20),
|
||||||
ft.Text(value="Numar comanda: "),
|
ft.Text(value="Numar comanda: "),
|
||||||
ft.Text(value=item['id'])
|
ft.Text(value=item['id'])
|
||||||
]
|
]
|
||||||
@@ -314,7 +370,7 @@ class Cart:
|
|||||||
value='Status: '
|
value='Status: '
|
||||||
),
|
),
|
||||||
ft.Text(
|
ft.Text(
|
||||||
value=item['status']
|
value=status_value[item['status']]
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
@@ -323,7 +379,7 @@ class Cart:
|
|||||||
ft.Text(
|
ft.Text(
|
||||||
value='Produse: '
|
value='Produse: '
|
||||||
),
|
),
|
||||||
#self.order_products(item['id'])
|
self.get_order_products(item['id'])
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
@@ -338,7 +394,6 @@ class Cart:
|
|||||||
for item in items
|
for item in items
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def on_delete_product_click(self, item):
|
def on_delete_product_click(self, item):
|
||||||
print('Delte item', item)
|
print('Delte item', item)
|
||||||
|
|
||||||
@@ -349,9 +404,9 @@ class Cart:
|
|||||||
def on_confirm_delete_btn_click(self, e):
|
def on_confirm_delete_btn_click(self, e):
|
||||||
print("confirm delete item", self.item_to_be_deleted)
|
print("confirm delete item", self.item_to_be_deleted)
|
||||||
#remove item
|
#remove item
|
||||||
self.orders.remove_product_from_order(self.on_hold_orders['id'], self.item_to_be_deleted)
|
self.orders_manager.remove_product_from_order(self.on_hold_orders['id'], self.item_to_be_deleted)
|
||||||
#update list
|
#update list
|
||||||
self.order_products = self.orders.get_order_products(self.on_hold_orders['id'])
|
self.order_products = self.orders_manager.get_order_products(self.on_hold_orders['id'])
|
||||||
self.products = []
|
self.products = []
|
||||||
for product in self.order_products:
|
for product in self.order_products:
|
||||||
self.products.append(
|
self.products.append(
|
||||||
@@ -372,7 +427,6 @@ class Cart:
|
|||||||
self.item_to_be_deleted = None
|
self.item_to_be_deleted = None
|
||||||
self.page.close(self.delete_dialog)
|
self.page.close(self.delete_dialog)
|
||||||
|
|
||||||
|
|
||||||
def open_confirm_dialog(self, e):
|
def open_confirm_dialog(self, e):
|
||||||
print('open dialog')
|
print('open dialog')
|
||||||
print(self.on_hold_orders)
|
print(self.on_hold_orders)
|
||||||
@@ -392,18 +446,24 @@ class Cart:
|
|||||||
self.error_message.value = "Va rugam inserati adresa de livrare!"
|
self.error_message.value = "Va rugam inserati adresa de livrare!"
|
||||||
self.error_message.color = ft.Colors.RED
|
self.error_message.color = ft.Colors.RED
|
||||||
self.error_message.update()
|
self.error_message.update()
|
||||||
|
print('Second address found')
|
||||||
return True
|
return True
|
||||||
|
print('Second address not found')
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def check_company_data_inserted(self, company_name, vat, register_number, company_address):
|
def check_company_data_inserted(self, company_name, vat, register_number, company_address):
|
||||||
found = False
|
found = False
|
||||||
if company_name is None or len(company_name)< 1:
|
if company_name is None or len(company_name)< 1:
|
||||||
|
print("Comapny name not found")
|
||||||
found = True
|
found = True
|
||||||
if vat is None or len(vat)< 1:
|
if vat is None or len(vat)< 1:
|
||||||
|
print("Vat not found")
|
||||||
found = True
|
found = True
|
||||||
if register_number is None or len(register_number)< 1:
|
if register_number is None or len(register_number)< 1:
|
||||||
|
print("Register number not found")
|
||||||
found = True
|
found = True
|
||||||
if company_address is None or len(company_address)< 1:
|
if company_address is None or len(company_address)< 1:
|
||||||
|
print("Company address not found")
|
||||||
found = True
|
found = True
|
||||||
if found:
|
if found:
|
||||||
self.error_message.value = "Toate campurile sunt obligatori!"
|
self.error_message.value = "Toate campurile sunt obligatori!"
|
||||||
@@ -411,13 +471,22 @@ class Cart:
|
|||||||
self.error_message.update()
|
self.error_message.update()
|
||||||
return found
|
return found
|
||||||
|
|
||||||
def check_inserted_user_data(self, username, phone, address):
|
def check_inserted_user_data(self, username, phone, address, email, city):
|
||||||
found = False
|
found = False
|
||||||
if username is None or len(username)< 1:
|
if username is None or len(username)< 1:
|
||||||
|
print('Username not found')
|
||||||
found = True
|
found = True
|
||||||
if phone is None or len(phone)< 1:
|
if phone is None or len(phone)< 1:
|
||||||
|
print("Phone not found")
|
||||||
found = True
|
found = True
|
||||||
if address is None or len(address)< 1:
|
if address is None or len(address)< 1:
|
||||||
|
print("Adress not found")
|
||||||
|
found = True
|
||||||
|
if city is None or len(city)< 1:
|
||||||
|
print("City not found")
|
||||||
|
found = True
|
||||||
|
if email is None or len(email)<1:
|
||||||
|
print("email not found")
|
||||||
found = True
|
found = True
|
||||||
if found:
|
if found:
|
||||||
self.error_message.value = "Toate campurile sunt obligatori!"
|
self.error_message.value = "Toate campurile sunt obligatori!"
|
||||||
@@ -426,25 +495,53 @@ class Cart:
|
|||||||
|
|
||||||
return found
|
return found
|
||||||
|
|
||||||
|
def check_email_is_valid(self, email):
|
||||||
|
email_regex = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
|
||||||
|
if re.fullmatch(email_regex, email) is not None:
|
||||||
|
self.error_message.value = ""
|
||||||
|
self.error_message.update()
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
self.error_message.value = "Va rugam inserati un e-mail valid!"
|
||||||
|
self.error_message.update()
|
||||||
|
return False
|
||||||
|
|
||||||
def create_update_user_details(self):
|
def create_update_user_details(self):
|
||||||
username = self.user_name.value
|
username = self.first_name.value + "~" + self.last_name.value
|
||||||
phone = self.phone.value
|
phone = self.phone.value
|
||||||
address = self.address.value
|
address = self.city.value+"%"+self.address.value
|
||||||
|
email = self.email.value
|
||||||
|
|
||||||
if self.is_second_address:
|
if self.is_second_address:
|
||||||
|
print("Second address has been selected (button click)")
|
||||||
if self.check_second_address_inserted(self.second_address.value):
|
if self.check_second_address_inserted(self.second_address.value):
|
||||||
return
|
return False
|
||||||
address = self.address.value + '~' + self.second_address.value
|
address = self.city.value+"%"+self.address.value + '~' + self.second_address.value
|
||||||
if self.check_inserted_user_data(username, phone, address):
|
if self.check_inserted_user_data(username, phone, self.address.value, email, self.city.value):
|
||||||
return
|
return False
|
||||||
|
|
||||||
|
if not self.check_email_is_valid(email):
|
||||||
|
return False
|
||||||
|
|
||||||
if '@default.com' in self.user['email']:
|
if '@default.com' in self.user['email']:
|
||||||
self.user = self.user_manager.invite_user()
|
print("User is default @default.com in name")
|
||||||
self.page.session.set("user", self.user)
|
try:
|
||||||
|
user_id = self.user_manager.invite_user(
|
||||||
|
email, username, phone, address
|
||||||
|
)
|
||||||
|
self.user = self.user_manager.get(user_id)
|
||||||
|
print("User invited")
|
||||||
|
self.page.session.set("user", self.user)
|
||||||
|
self.orders_manager.update_order_user_id(user_id, self.on_hold_orders['id'])
|
||||||
|
except:
|
||||||
|
print("Unable to create user, user already exists")
|
||||||
|
self.error_message.value = "Exita deja un utilizator cu aceasta adresa de email!"
|
||||||
|
return False
|
||||||
else:
|
else:
|
||||||
self.user_manager.update_user_data(username, phone, address, self.user['id'])
|
self.user_manager.update_user_data(username, phone, address, self.user['id'])
|
||||||
|
|
||||||
if self.is_company:
|
if self.is_company:
|
||||||
|
print("Compani selected (company button has been pressed)")
|
||||||
if self.check_company_data_inserted(self.company_name.value, self.vat.value, self.register_number.value, self.company_address.value):
|
if self.check_company_data_inserted(self.company_name.value, self.vat.value, self.register_number.value, self.company_address.value):
|
||||||
return
|
return
|
||||||
if self.company:
|
if self.company:
|
||||||
@@ -462,36 +559,150 @@ class Cart:
|
|||||||
'address': self.company_address.value
|
'address': self.company_address.value
|
||||||
}
|
}
|
||||||
self.company_manager.add_company(company)
|
self.company_manager.add_company(company)
|
||||||
|
if self.payment.value == None:
|
||||||
|
self.error_message.value = "Va rugam selectati metoda de plata!"
|
||||||
|
self.error_message.color = ft.Colors.RED
|
||||||
|
self.error_message.update()
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
def on_confim_btn_click(self, e):
|
def create_history(self):
|
||||||
#create / update user details:
|
if '@default.com' not in self.user['email']:
|
||||||
self.create_update_user_details()
|
self.all_orders = self.orders_manager.get_orders_for_user(self.page.session.get('user')['id'])
|
||||||
|
self.all_orders = self.all_orders[::-1]
|
||||||
|
buffer = []
|
||||||
|
for order in self.all_orders:
|
||||||
|
if order['status'] != 'on_hold':
|
||||||
|
buffer.append(order)
|
||||||
|
self.orders_manager_list.controls.clear()
|
||||||
|
self.orders_manager_list.controls = self.create_history_list(buffer)
|
||||||
|
self.orders_manager_list.update()
|
||||||
|
|
||||||
print('confirm')
|
def notify_admin_and_client(self):
|
||||||
self.page.close(self.confirm_dialog)
|
users = self.user_manager.get_all()
|
||||||
self.orders.update_order_status("new", self.on_hold_orders['id'])
|
admins = []
|
||||||
|
for user in users:
|
||||||
|
if user['role'] == 'admin':
|
||||||
|
admins.append(user)
|
||||||
|
for admin in admins:
|
||||||
|
send_gmail(
|
||||||
|
to_email=admin['email'],
|
||||||
|
subject="Comanda noua pe tainagustului.ro",
|
||||||
|
body=f'''
|
||||||
|
Ati primit o noua comanda de la {self.user['email']}.
|
||||||
|
Va rugam accesati wwww.tainagusutului.ro pentru detalii.
|
||||||
|
'''
|
||||||
|
)
|
||||||
|
|
||||||
self.products = []
|
send_gmail(
|
||||||
self.on_hold_orders = self.orders.get_on_hold_order(self.user['id'])
|
to_email=self.user['email'],
|
||||||
if self.on_hold_orders:
|
subject="Multumim pentru comanda!",
|
||||||
self.order_products = self.orders.get_order_products(self.on_hold_orders['id'])
|
body=f'''
|
||||||
|
Buna ziua,
|
||||||
|
|
||||||
for product in self.order_products:
|
Comanda a fost primita si va fi livrata in cel mai scurt timp.
|
||||||
self.products.append(
|
|
||||||
|
Va multumim,
|
||||||
|
Echipa tainagustului.ro
|
||||||
|
'''
|
||||||
|
)
|
||||||
|
|
||||||
|
def save_order_ntp_id(self, order_id, netopia_id):
|
||||||
|
self.netopia_manager.add_netopia_card(order_id, netopia_id)
|
||||||
|
|
||||||
|
def online_pay(self, order_id):
|
||||||
|
if self.payment.value == "plata_online_cu_cardul":
|
||||||
|
print("The user seelected card payment")
|
||||||
|
order_products = []
|
||||||
|
products_ids = self.orders_manager.get_order_products(order_id)
|
||||||
|
for prod in products_ids:
|
||||||
|
p = self.productsDB.get(prod['prdouct_id'])
|
||||||
|
order_products.append(
|
||||||
{
|
{
|
||||||
'product':self.productsDB.get(product['prdouct_id']),
|
'name':p['name'],
|
||||||
'quantity':product['quantity']
|
'code':p['id'],
|
||||||
|
'category':p['category_id'],
|
||||||
|
'price':p['price'],
|
||||||
|
'vat':0,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
self.product_list.controls.clear()
|
print(order_products)
|
||||||
self.product_list.controls = self.create_list(self.products, self.on_delete_product_click)
|
response = start_card_payment(
|
||||||
self.product_list.update()
|
order_id=order_id,
|
||||||
if '@default.com' not in self.user['email']:
|
amount=self.pret_total.value.split(": ")[1],
|
||||||
self.all_orders = self.orders.get_orders_for_user(self.page.session.get('user')['id'])
|
currency='RON',
|
||||||
self.all_orders = self.all_orders[::-1]
|
description="Comanda noua",
|
||||||
self.orders_list.controls.clear()
|
customer={
|
||||||
self.orders_list.controls = self.create_history_list(self.all_orders)
|
'email':self.email.value,
|
||||||
self.orders_list.update()
|
'phone':self.phone.value,
|
||||||
|
'firstName':self.first_name.value,
|
||||||
|
'lastName':self.last_name.value,
|
||||||
|
'city':self.city.value,
|
||||||
|
'country': 642,
|
||||||
|
'address':self.address.value,
|
||||||
|
'county':'',
|
||||||
|
'zipCode':''
|
||||||
|
},
|
||||||
|
products=order_products
|
||||||
|
)
|
||||||
|
print(type(response))
|
||||||
|
|
||||||
|
# Extract URL & ntpID from SDK response
|
||||||
|
payment_url = response.payment['paymentURL']
|
||||||
|
ntp_id = response.payment['ntpID']
|
||||||
|
|
||||||
|
# 1) Persist mapping (VERY IMPORTANT for IPN/status reconciliation)
|
||||||
|
if ntp_id:
|
||||||
|
self.save_order_ntp_id(order_id, ntp_id) # implement in your DB layer
|
||||||
|
|
||||||
|
# 2) Open hosted payment page
|
||||||
|
if payment_url:
|
||||||
|
self.page.launch_url(payment_url, web_window_name="_blank")
|
||||||
|
self.page.go("/payment/redirect") # your UX page
|
||||||
|
else:
|
||||||
|
self.page.snack_bar = ft.SnackBar(ft.Text("Nu am primit URL-ul de plată."))
|
||||||
|
self.page.snack_bar.open = True
|
||||||
|
self.page.update()
|
||||||
|
|
||||||
|
def on_confim_btn_click(self, e):
|
||||||
|
self.error_message.color = ft.Colors.RED
|
||||||
|
self.error_message.update()
|
||||||
|
#create / update user details:
|
||||||
|
print("Confirm button Selected ")
|
||||||
|
self.page.close(self.confirm_dialog)
|
||||||
|
if self.create_update_user_details():
|
||||||
|
print('User details updated')
|
||||||
|
order_id = self.on_hold_orders['id']
|
||||||
|
self.orders_manager.update_order_status("new", self.on_hold_orders['id'])
|
||||||
|
print('Order status is set to new')
|
||||||
|
self.products = []
|
||||||
|
self.on_hold_orders = self.orders_manager.get_on_hold_order(self.user['id'])
|
||||||
|
if self.on_hold_orders:
|
||||||
|
self.order_products = self.orders_manager.get_order_products(self.on_hold_orders['id'])
|
||||||
|
|
||||||
|
for product in self.order_products:
|
||||||
|
self.products.append(
|
||||||
|
{
|
||||||
|
'product':self.productsDB.get(product['prdouct_id']),
|
||||||
|
'quantity':product['quantity']
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.product_list.controls.clear()
|
||||||
|
self.product_list.controls = self.create_list(self.products, self.on_delete_product_click)
|
||||||
|
self.product_list.update()
|
||||||
|
|
||||||
|
#hiostory
|
||||||
|
self.create_history()
|
||||||
|
|
||||||
|
self.error_message.value = "Comanda a fost trimisa cu success!"
|
||||||
|
self.error_message.color = ft.Colors.GREEN
|
||||||
|
self.error_message.update()
|
||||||
|
|
||||||
|
#online pay
|
||||||
|
self.online_pay(order_id)
|
||||||
|
|
||||||
|
#notify admin
|
||||||
|
self.notify_admin_and_client()
|
||||||
|
|
||||||
def build(self):
|
def build(self):
|
||||||
return ft.Container(
|
return ft.Container(
|
||||||
@@ -505,10 +716,16 @@ class Cart:
|
|||||||
ft.Icons.SHOPPING_CART_CHECKOUT,
|
ft.Icons.SHOPPING_CART_CHECKOUT,
|
||||||
size=40,
|
size=40,
|
||||||
),
|
),
|
||||||
ft.Text(
|
ft.Column(
|
||||||
"Produse adugate:",
|
[
|
||||||
weight=ft.FontWeight.BOLD,
|
self.pret_total,
|
||||||
size=15
|
self.card_id,
|
||||||
|
# ft.Text(
|
||||||
|
# "Produse adugate:",
|
||||||
|
# weight=ft.FontWeight.BOLD,
|
||||||
|
# size=15
|
||||||
|
# ),
|
||||||
|
]
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
|
|||||||
9
UI_V2/pages/shopping_cart/confirm_data.py
Normal file
9
UI_V2/pages/shopping_cart/confirm_data.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import flet as ft
|
||||||
|
|
||||||
|
class ConfirmData:
|
||||||
|
def __init__(self):
|
||||||
|
self.first_name = ft.TextField(label="Prenume")
|
||||||
|
self.last_name = ft.TextField(label="Nume")
|
||||||
|
self.city = ft.TextField(label="Oras")
|
||||||
|
self.address = ft.TextField(label="Strada si numar")
|
||||||
|
|
||||||
35
UI_V2/pages/shopping_cart/payment_redirect.py
Normal file
35
UI_V2/pages/shopping_cart/payment_redirect.py
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import flet as ft
|
||||||
|
|
||||||
|
class PaymentRedirect:
|
||||||
|
def __init__(self, page: ft.Page):
|
||||||
|
self.page = page
|
||||||
|
|
||||||
|
def build(self):
|
||||||
|
return ft.Container(
|
||||||
|
content=ft.Column(
|
||||||
|
[
|
||||||
|
ft.Row(
|
||||||
|
[
|
||||||
|
ft.Image(src='images/tainagustului.png', width=200)
|
||||||
|
],
|
||||||
|
alignment=ft.MainAxisAlignment.CENTER
|
||||||
|
),
|
||||||
|
ft.Text(
|
||||||
|
"Sunteți redirecționat către pagina de plată NETOPIA...",
|
||||||
|
size=20,
|
||||||
|
weight=ft.FontWeight.BOLD,
|
||||||
|
text_align=ft.TextAlign.CENTER,
|
||||||
|
),
|
||||||
|
ft.ProgressRing(width=40, height=40, color=ft.Colors.GREEN),
|
||||||
|
ft.Text(
|
||||||
|
"Vă rugăm să nu închideți această fereastră până la finalizarea plății.",
|
||||||
|
size=16,
|
||||||
|
color=ft.Colors.GREY_700,
|
||||||
|
text_align=ft.TextAlign.CENTER,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
alignment=ft.MainAxisAlignment.CENTER,
|
||||||
|
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
|
||||||
|
spacing=20
|
||||||
|
)
|
||||||
|
)
|
||||||
@@ -1 +1,5 @@
|
|||||||
flet==0.28.3
|
flet==0.28.3
|
||||||
|
netopia-sdk==2.1.1
|
||||||
|
python-dotenv==1.2.0
|
||||||
|
Flask==3.1.2
|
||||||
|
flask-cors==6.0.1
|
||||||
Reference in New Issue
Block a user