Αρχείο αλλαγών¶
Καταγραφή σημαντικών αλλαγών για την ομάδα ανάπτυξης. Οι νεότερες καταχωρήσεις είναι πάνω.
Μορφή:
Μετά την ημερομηνία [ΕΕΕΕ-ΜΜ-ΗΗ] αφήνουμε κενή γραμμή πριν τα στοιχεία - (αλλιώς το MkDocs τα εμφανίζει ως ένα κομμάτι κειμένου, όχι ως λίστα).
[ΕΕΕΕ-ΜΜ-ΗΗ ΩΩ:ΛΛ] (προαιρετική ζώνη ώρας)
- Σύντομη, συγκεκριμένη αλλαγή (αρχείο ή περιοχή αν βοηθάει)
- …
[2026-04-21]
-
Ραντεβού / πολλαπλά παραστατικά: Το modal ραντεβού υποστηρίζει πλέον σύνδεση με πολλά παραστατικά του ίδιου συναλλασσόμενου. Τα συνδεδεμένα δελτία αποθηκεύονται στο
appointments.dochead_idsως TEXT JSON array αντικειμένων (μεid, αριθμό, σειρά, κατάσταση), ενώ τοid_docheadπαραμένει ως πρώτο/κύριο παραστατικό για συμβατότητα. Στο UI εμφανίζονται πολλαπλοί σύνδεσμοι προς τα δελτία και η επικύρωση ελέγχει ότι όλα τα επιλεγμένα παραστατικά ανήκουν στον ίδιο συναλλασσόμενο (db/migrations/20260421130000_add_dochead_ids_to_appointments.php,AppointmentModel,AppointmentController,add-appointment-modal.html.twig,calendar.js). -
Αποθήκη / barcode lookup: Στη σελίδα
/warehouse/barcodes, όταν αναζητείται είδος με barcode, εμφανίζεται πλέον και ενότητα «Σχετικά παραστατικά» με όλο το ιστορικό παραστατικών του storage, ώστε να φαίνονται και τα κλειστά δελτία μαζί με σειρά, κατάσταση, ημερομηνία παράδοσης και καταχώρησης (ItemStorageModel,barcodes.html.twig,warehouse-barcodes.js). -
Παραστατικά / εκτύπωση barcode: Στην προβολή δελτίου προστέθηκε ενέργεια «Όλα τα barcode» με επιλογές θερμικής εκτύπωσης
57mmκαι80mm, η οποία εκτυπώνει μαζικά όλα τα μοναδικά barcode του δελτίου αντί για ένα-ένα (Documents/edit.html.twig,documents-edit.js).
[2026-04-20]
- Πελάτης / SCRUM-1724: Σε νέα καταχώρηση (modal «Νέος πελάτης» και ροή «Δημιουργία πελάτη» στο modal ραντεβού) το «Είναι ιδιώτης» είναι προεπιλεγμένο (ΑΦΜ
000000000). Οι υπάρχουσες καρτέλες δεν τροποποιούνται. (add-customer-modal.html.twig,add-appointment-modal.html.twig,skeleton.js,calendar.js, οδηγοί03-pelatologio.md,05-rantevou.md).
[2026-04-17]
- Ραντεβού / προεπιλεγμένος πελάτης: Το
CalendarAppointments.openCreateModal(ημερομηνία, { idtrader, lockTrader, hideCreateTrader })επιτρέπει κλείδωμα του πεδίου συναλλασσόμενου (Select2 disabled) και απόκρυψη του «Δημιουργία πελάτη». Μεidtraderμόνο, ενεργοποιούνται από προεπιλογή τοlockTraderκαι τοhideCreateTrader. Στην επεξεργασία συναλλασσόμενου, καρτέλα «Ραντεβού», προστέθηκε κουμπί «Νέο ραντεβού» με αυτή τη συμπεριφορά (calendar.js,traders.js,add-appointment-modal.html.twig,Traders/edit.html.twig,docs/odigos-hristi/05-rantevou.md). Το ίδιο κλείδωμα εφαρμόζεται στο modal πριν το κλείσιμο δελτίου παράδοσης (openBeforeCloseDeliveryAppointment).
[2026-04-16]
-
Είδη / επεξεργασία — εμφάνιση τύπου χρέωσης για τεμ.: Στο
/items/edit/{id}, όταν η μονάδα μέτρησης είναι τεμ., στη στήλη «Τύπος χρέωσης» και στο dropdown σύνδεσης υπηρεσίας εμφανίζεται πάντα «Σταθερή» για όλες τις υπηρεσίες (ανεξάρτητα από τοrate_typeστην βάση μέχρι να αποθηκευτεί το είδος)· με αλλαγή μονάδας ανανεώνεται η εμφάνιση (items.js). -
Είδη / μονάδα τεμ. και τύπος χρέωσης υπηρεσιών: Στο
PUT /api/items/{id}, όταν το είδος έχει μονάδα τεμ. (idmunit = 1), όλες οι υπηρεσίες που είναι συνδεδεμένες με το είδος (item_services) ενημερώνονται σεrate_type = flatστον πίνακαservices(όσες ήτανby_size). Στο UI η ετικέτα τύπου χρέωσης «Σταθερή» δεν περιλαμβάνει πλέον το(τεμ.)(ItemController,items.js,items.html.twig,traders.js,item.controller.md). -
Αποθήκη / barcodes — αποθήκευση μόνο κατηγορίας (UI): Στο
/warehouse/barcodesτο είδος εμφανίζεται σταθερό· η αλλαγή κατηγορίας και η επαναχαρτογράφηση γραμμών γίνονται με κουμπί «Αποθήκευση» κάτω από την κατηγορία. Το APIPOST /api/warehouse/storage/{id}/change-item-contextπαραμένει πλήρες (iditem,iditemcategory)· το UI στέλνει το τρέχον είδος (warehouse-barcodes.js,barcodes.html.twig, οδηγός08-syskeuasia-barcodes.md). -
Αποθήκη / αλλαγή είδους & επαναχαρτογράφηση υπηρεσιών (backend): Το
POST /api/warehouse/storage/{id}/change-item-context(μεdry_runκαιconfirm_drop_unmapped) ενημερώνει τοitem_storage.iditemκαι τις γραμμέςdocitemsτου ίδιου δελτίου (per_item): αντιστοίχιση ανάidservice, τιμές από κατάλογο, συγχώνευση διπλών, διαγραφή μη αντιστοιχίσιμων μετά επιβεβαίωση (WarehouseController,ItemServiceModel::findActiveLinkId,DocumentModel::updateDocitemItemServiceId,warehouse.controller.md). -
Πελάτης / αναζήτηση (δελτίο & ραντεβού): Στη δημιουργία παραστατικού (
documents.js) και στο modal ραντεβού (calendar.js,add-appointment-modal.html.twig) το κείμενο επιλογής πελάτη περιλαμβάνει κινητό, σταθερό και στοιχεία διεύθυνσης, ώστε το Select2 να εντοπίζει τον πελάτη και με αυτά. Ενημερώθηκαν οι οδηγοίdocs/odigos-hristi/07-parastatika-kai-delitia.md,05-rantevou.md. -
Ραντεβού / φόρτωση λιστών από API: Όταν οι επιλογές συναλλασσόμενου/δρομολογίου/οχήματος φορτώνονται με
fetch(χωρίς προ-γεμισμένο HTML), τοcalendar.jsδιαβάζει πλέον σωστά τοdata.traders/data.route_schedules/data.vehiclesαπό την τυπική απάντησηapiSuccess— αποφεύγεται κλήση.mapπάνω στο αντικείμενοdata. -
Αποθήκη / barcodes & κατηγορία είδους: Στη σελίδα
/warehouse/barcodes, όταν το είδος έχει ενεργές κατηγορίες, εμφανίζεται επιλογή κατηγορίας (όπως στο δελτίο): ο πίνακας υπηρεσιών φιλτράρεται ανά κατηγορία (και εμφανίζονται υπηρεσίες χωρίς υποκατηγορία), η προσθήκη καλείGET /api/item-servicesμεiditemcategory. Το lookup επιστρέφειitem_categoriesκαιiditemcategoryανά γραμμήdocitems(ItemStorageModel,warehouse-barcodes.js,barcodes.html.twig, οδηγός08-syskeuasia-barcodes.md). -
Δελτίο / κατηγορία είδους: Στη δημιουργία παραστατικού, αν το είδος έχει ενεργές κατηγορίες (
item_categories), εμφανίζεται επιλογή κατηγορίας είδους· μετά την επιλογή φορτώνονται μόνο οι σχετικές υπηρεσίες (και οι συνδέσεις χωρίς υποκατηγορία, π.χ. Φύλαξη).GET /api/itemsπεριλαμβάνειitem_categoriesανά είδος·GET /api/item-services?iditem=…δέχεται προαιρετικάiditemcategory(ItemCategoryModel,ItemServiceModel,ItemController,ItemServiceController,public/assets/js/documents.js,ItemApiTest,ItemServiceLinkApiTest). -
Fylaksi (catalog & documents): Storage is linked per item (
per_item): separateitem_services/id_item_serviceper catalog item, not per document. UpdatedExpressServiceProvisioner,DocumentModel,DocumentController,CompanyDefaultsService,ItemController,public/assets/js/documents.js; added migrationdb/migrations/20260416193000_fylaksi_per_item.php; docsexpress-service-provisioner,company-defaults.service,document.controller. - Fylaksi / seed & SQL: New companies get Φύλαξη on every item via
ExpressServiceProvisioner::ensureFylaksiOnAllItemsafter catalog seed (CompanyDefaultsService). Manual DB backfill script:db/sql/fylaksi_per_item_backfill.sql.RegistrationDefaultsTestexpectations updated;documents.jscallssyncAutoFylaksiLinesafter auto Πλύσιμο on row load. -
Documents / With Fylaksi checkbox:
public/assets/js/documents.jsrefetches per-rowitem_serviceswhen enabled (refreshItemServicesCache,patchSvcPickerOptions) so Φύλαξη appears on all rows with a selected item, without clearing other service lines. -
Τεκμηρίωση / παραστατικά: Στο
docs/03-reference/document.controller.mdπροστέθηκε πλήρες παράδειγμα JSON γιαPOST /api/documents(υποχρεωτικά/προαιρετικά πεδία,iddocseries = 239,with_fylakis/is_express, κανόνεςbarcode_range,grossval/by_size). -
API / είδη: Το
GET /api/itemsεπιστρέφει για κάθε είδοςitem_services(ίδια δομή με τοGET /api/item-services?iditem=…) καιitem_categories(ενεργές κατηγορίες). ΤοGET /api/items/{id}και οι απαντήσειςPOST/PUTείδους περιλαμβάνουν τα ίδια πεδία (ItemController,ItemCategoryModel,ItemServiceModel::getGroupedByItemIdForCompany,ItemApiTest). -
API / πρόσβαση με κλειδί εταιρείας: Τα προστατευμένα endpoints κάτω από
/apiμπορούν πλέον να κληθούν με την κεφαλίδαX-CARPET-TOKEN, η οποία ταιριάζει με το πεδίοapi_tokenτου πίνακαcompanies. Σε κάθε νέα εταιρεία (εγγραφή) δημιουργείται αυτόματα τυχαίο token 64 hex χαρακτήρων· οι υπάρχουσες εταιρείες παίρνουν token με το migrationdb/migrations/20260416130000_companies_api_token.php. Η ταυτοποίηση με token εγκαθιστά συνεδρία ως κύριο μέλος της εταιρείας (ιδιοκτήτης πρώτα, αλλιώς πρώτο ενεργό μέλος), με τους ρόλους/δικαιώματά του (Auth::tryBootstrapFromCarpetToken,Middleware,CompanyModel,CompanyUserModel). - API / κλειδί ανά χρήστη: Η ίδια κεφαλίδα
X-CARPET-TOKENμπορεί να είναι και τοapi_tokenτου πίνακαuseraccounts(έλεγχος μετά το κλειδί εταιρείας). Η συνεδρία γεμίζει με τον συγκεκριμένο χρήστη και την πρώτη ενεργή εταιρεία του (getFirstCompany), όπως στη σύνδεση με κωδικό. Κάθε νέος λογαριασμός παίρνει token στη δημιουργία· υπάρχοντες χρήστες ενημερώνονται μεdb/migrations/20260416140000_useraccounts_api_token.php(AccountModel,Auth). - Ραντεβού / ανάθεση οδηγού: Προστέθηκε προαιρετική ανάθεση οδηγού (
assigned_driver_user_idστον πίνακαappointments, migrationdb/migrations/20260416150000_appointments_assigned_driver.php). Κενή τιμή σημαίνει ραντεβού ανοιχτό σε όλους τους οδηγούς· με τιμή, επιτρέπονται μόνο μέλη εταιρείας με ρόλοdriver. Οι συνδεδεμένοι οδηγοί βλέπουν στη λίστα/API μόνο ραντεβού χωρίς ανάθεση ή ανατεθειμένα στον ίδιο (AppointmentModel,AppointmentController,TraderController,CompanyUserModel::listDriversForCompany, modal,calendar.js,dashboard-calendar.js). - Ραντεβού / φίλτρο λίστας οδηγού (API): Στο
GET /api/appointmentsκαιGET /api/traders/{id}/appointmentsο περιορισμός «ανοιχτά ή δικά μου» εφαρμόζεται όταν ο χρήστης έχει ρόλοdriverκαι δεν έχειmanage_appointments· όσοι διαχειρίζονται ραντεβού (π.χ. γραμματεία, διαχειριστής) βλέπουν πάντα όλα, ακόμη κι αν έχουν και ρόλο οδηγού (Auth::appointmentsDriverScopeUserId,AppointmentController,TraderController). - API / έκδοση κλειδιού με κωδικό: Προστέθηκαν
POST /api/auth/token(emailήusername+password) για απόκτηση τουapi_tokenκαι χρήση ωςX-CARPET-TOKEN(ίδιοι κανόνες / 2FA με τη σύνδεση). Αν χρειάζεται 2FA,require_2faκαιPOST /api/auth/token/verify-2faμεotp(ίδιο cookie). Λογαριασμοί χωρίς token:AccountModel::ensureApiToken,AuthController,ApiRoutes).
[2026-04-15]
- Αποθήκη / barcodes: Στην αναζήτηση φυσικού είδους (
/warehouse/barcodes, APIlookup) οι γραμμές υπηρεσιών φορτώνονται πλέον μόνο για το κύριο παραστατικό του storage (παλαιότερη γραμμήdocitems), ώστε να μην επαναλαμβάνονται οι ίδιες υπηρεσίες όταν το ίδιοitem_storageσυνδέεται με πολλά δελτία (ItemStorageModel). - Χρήστες / υποχρεωτική εταιρεία: Δεν επιτρέπεται πλέον ενεργή συνεδρία χωρίς
company_id: τοAuth::loginαπαιτεί αριθμό εταιρείας, η σύνδεση και το 2FA απορρίπτονται με μήνυμα αν ο λογαριασμός δεν συνδέεται με εταιρεία, τα view routes (και το admin) περνούν από middlewarecompany, και η αρχική σύνδεση (checkAuthPage) καθαρίζει «σπασμένη» συνεδρία χωρίς εταιρεία (Auth,AuthController,Router,ViewRoutes,AdminRoutes). - Εγγραφή / εταιρεία: Μετά την εγγραφή δημιουργείται πάντα εταιρεία και σύνδεση ιδιοκτήτη (seed defaults)· αν λείπει το όνομα εταιρείας, χρησιμοποιείται όνομα/επώνυμο, αλλιώς το τοπικό μέρος του email, αλλιώς η ετικέτα «Εταιρεία». Στο dashboard, αν για κάποιο λόγο λείπει
comidστη συνεδρία, γίνεται ανακατεύθυνση στην αρχική σύνδεση (AuthController,HomeController). - Πελατολόγιο & ραντεβού / σταθερό τηλέφωνο: Το σταθερό δεν είναι πλέον υποχρεωτικό ούτε στην καρτέλα πελάτη/συνεργάτη ούτε στο ραντεβού· κενό πεδίο αποθηκεύεται ως
NULL. Όταν συμπληρώνεται, ελέγχονται 10 ψηφία. Στο UI αφαιρέθηκε τοrequiredαπό το πεδίο επεξεργασίας πελάτη, διορθώθηκε η αποστολήphoneστοPOST /api/traders(ώστε να μην στέλνεται το κείμενοnullμέσω φόρμας), και το ραντεβού στέλνει πάνταtmp_phoneως κείμενο, ώστε στο επεξεργασία να μπορεί να καθαριστεί το σταθερό (TraderController,AppointmentController,edit.html.twig,traders.js,skeleton.js,calendar.js, οδηγός χρήστη). - Πελατολόγιο / τιμοκατάλογος πελάτη: Στην επεξεργασία πελάτη (
/traders/customers/edit/{id}) προστέθηκε καρτέλα Τιμοκατάλογος με όλα τα είδη και τις συνδεδεμένες υπηρεσίες (ανά είδος)· εμφανίζεται η γενική τιμή καταλόγου και επεξεργάσιμη τιμή πελάτη (item_pricesμόνο για τον συγκεκριμένο πελάτη). API:GET /api/traders/{id}/price-catalog,PUT /api/item-prices/{id}(ItemPriceModel,TraderController,ItemPriceController,edit.html.twig,traders.js,TraderApiTest). - Προϊόντα / επεξεργασία είδους: Στη σελίδα
/items/edit/{id}η γενική τιμή κάθε σύνδεσης υπηρεσίας είναι πλέον επεξεργάσιμη στον πίνακα (πεδίο τιμής + επιβεβαίωση ή Enter)· χρησιμοποιείται το υπάρχονPUT /api/item-services/{id}(public/assets/js/items.js,edit.html.twig). - Παραστατικά / φάση παράδοσης (ροή): Το φίλτρο και η στήλη παράδοσης στη λίστα δελτίων χρησιμοποιούν πλέον
workflow_delivery_phase(preparation/towards_delivery/delivered) από την αλυσίδα συσχέτισης. Το ίδιο πεδίο εμφανίζεται στην προβολή δελτίου, στο side panel και στα φυσικά είδη του συναλλασσόμενου (DocumentModel,DocumentController,ItemStorageModel,documents-list.js,documents-edit.js,document-panel.js,traders.js, views,DocumentApiTest). -
Παραστατικά / UI φάσης παράδοσης: Στη λίστα δελτίων και στα φυσικά είδη συναλλασσόμενου η φάση εμφανίζεται ως ετικέτα (Ετοιμασία / Προς παράδοση / Παραδόθηκε) με tooltip «Βήμα 1–3», αντί για μόνο αριθμούς (
documents-list.js,traders.js,list.html.twig). -
Παραστατικά / λίστα δελτίων: Στη σελίδα
/documentsκάθε αλυσίδα συσχετισμένων δελτίων εμφανίζεται ως μία γραμμή με βάση το δελτίο παραλαβής (σειρά 239)· τα υπόλοιπα (π.χ. προς παράδοση, χρεωστικό) εμφανίζονται στη στήλη Συσχέτιση με συνδέσμους, ταξινομημένα κατά σειρά ροής. Η αναζήτηση και οι εξαγωγές Excel/PDF λαμβάνουν υπόψη και τους αριθμούς/σειρές των συσχετιζόμενων δελτίων (public/assets/js/documents-list.js). - Παραστατικά / τιμή υπηρεσίας ανά τ.μ.: Προστέθηκε στήλη
docitems.unit_gross(ακαθάριστη τιμή μονάδας €/τ.μ. τη στιγμή του δελτίου). Αν στο νέο δελτίο η ποσότητα τ.μ. είναι 0, το σύνολο γραμμής παραμένει 0 αλλά αποθηκεύεται η μοναδιαία τιμή που βάλατε· όταν καταχωρείτε τ.μ. στην αποθήκη, το σύνολο υπολογίζεται από αυτή (και όχι μόνο από τον κατάλογο). Στη φόρμα νέου δελτίου οι προτεινόμενες τιμές από τον κατάλογο εμφανίζονται πλέον με ΦΠΑ (καθαρή × 1,24), συνεπώς με το backend (DocumentModel,DocumentController,WarehouseController,ItemStorageModel,public/assets/js/documents.js, migrationdb/migrations/20260415120000_add_unit_gross_to_docitems.php). -
Tests / DocumentApiTest: Οι κλήσεις δημιουργίας δελτίου και
GET /api/documents/next-numberχρησιμοποιούν πλέονiddocseries = 239(δελτίο παραλαβής), ώστε να συμφωνούν με την επικύρωσηDocSeries::DELIVERY_SLIP. -
Παραστατικά / ροή 3 βημάτων (παραλαβή → προς παράδοση → χρεωστικό): Το κλείσιμο εφαρμόζεται πλέον μόνο στο δελτίο παραλαβής (σειρά 239) και δημιουργεί παραστατικό προς παράδοση (σειρά 3) σε κατάσταση ανοιχτό, ώστε να εμφανίζεται το κουμπί «Κλείσιμο → χρεωστικό» (κλείνει το δελτίο παράδοσης και δημιουργεί 3ο παραστατικό με
iddocseries = 1/ χρεωστικό). Νέα API διαδρομήPOST /api/documents/{id}/charge, ενημερωμένα μηνύματα/επιβεβαιώσεις σε πλήρη σελίδα και side panel (DocSeries,DocumentModel::closeDocument,DocumentController,ApiRoutes,documents-edit.js,document-panel.js,Documents/edit.html.twig,Documents/document_panel.html.twig). - Παραστατικά / UX «Προς διακίνηση»: Το πρώτο βήμα εμφανίζεται ως Προς διακίνηση (και στα modals επιβεβαίωσης). Μετά επιτυχές «Προς διακίνηση» ή «Κλείσιμο → χρεωστικό» γίνεται μετάβαση στο νέο παραστατικό (
new_idαπό API) ώστε να μην μένετε σε κλειστό δελτίο χωρίς ενέργειες· στο side panel ανοίγει το νέο id (documents-edit.js,document-panel.js). - UI / Modals νέου πελάτη & ραντεβού: Με το κλείσιμο του modal (
hidden.bs.modal) καθαρίζονται πλέον όλα τα πεδία, ώστε στο επόμενο άνοιγμα να μην μένουν δεδομένα από προηγούμενη συμπλήρωση ή ακύρωση (public/assets/js/skeleton.js,public/assets/js/calendar.js). - UI / Προϊόντα-Υπηρεσίες: Διορθώθηκε η ευθυγράμμιση του
form-check form-switchστα modals «Νέο Είδος» και «Νέα Υπηρεσία» στη σελίδα/items, ώστε ο διακόπτης να μην εμφανίζεται εκτός αριστερής πλευράς (public/assets/css/items.css). - Ρόλοι χρηστών / μενού & πρόσβαση (views): Εφαρμόστηκε διαχωρισμός ορατότητας στο sidebar για τον ρόλο Γραμματέας (εμφανίζονται: Πελατολόγιο, Προϊόντα/Υπηρεσίες, Ραντεβού, Δρομολόγια, Παραστατικά· αποκρύπτονται: Αναφορές, Εικόνα επιχείρησης, Στοιχεία επιχείρησης, Διαχείριση χρηστών) στο
app/Views/Components/sidebar.html.twig. - Ρόλοι χρηστών / οδηγός: Ο ρόλος Οδηγός περιορίστηκε ώστε να βλέπει μόνο Πελατολόγιο, Ραντεβού και Παραστατικά. Αποκρύπτονται όλες οι υπόλοιπες ενότητες μενού (συμπεριλαμβανομένης της Αρχικής) και προστέθηκαν route guards για
403σε dashboard/warehouse όταν δεν επιτρέπεται (app/Views/Components/sidebar.html.twig,app/Routes/ViewRoutes.php). - Ρόλοι χρηστών / αποθηκάριος: Ο ρόλος Αποθηκάριος περιορίστηκε ώστε να βλέπει μόνο τη σελίδα barcode (ενότητα «Συσκευασία»). Παράλληλα, τα view route guards για Πελατολόγιο/Ραντεβού/Παραστατικά έγιναν role-based (
admin|secretary|driver) ώστε ο αποθηκάριος να λαμβάνει403σε κάθε άλλη σελίδα (app/Views/Components/sidebar.html.twig,app/Routes/ViewRoutes.php). - Landing redirect ανά ρόλο από
/dashboard: Υλοποιήθηκε ενιαίο σημείο εισόδου στοHomeController@index: ο Οδηγός ανακατευθύνεται σε/appointments, ο Αποθηκάριος σε/warehouse/barcodes, ενώ η Γραμματεία παραμένει στο dashboard. Το route/dashboardείναι πλέον προσβάσιμο από όλους τους authenticated ρόλους για μελλοντική role-based αρχική (app/Controllers/View/HomeController.php,app/Routes/ViewRoutes.php,app/Views/Components/sidebar.html.twig). - 403 σε μη επιτρεπόμενες σελίδες: Προστέθηκαν route-level έλεγχοι στα view routes ώστε όταν ο χρήστης δεν έχει το απαιτούμενο role/permission να μπλοκάρεται με
403(χωρίς αλλαγές σε API authorization) στοapp/Routes/ViewRoutes.php. - Backend modular middleware: Επεκτάθηκε το middleware resolver με
role_any:καιpermission_any:για επαναχρησιμοποιήσιμους κανόνες πρόσβασης σε ομάδες routes (app/Core/Middleware.php). - Τεκμηρίωση χρήστη: Ενημερώθηκε ο οδηγός με ενότητα «Μενού ανά ρόλο χρήστη» και σημείωση για
403σε απευθείας πρόσβαση URL (docs/odigos-hristi/02-i-othoni-kai-to-menou.md).
[2026-04-14]
- Email / SMTP & TLS: Προστέθηκε
Helpers::applyPhpMailerSmtpTlsOptionsκαι μεταβλητή περιβάλλοντοςMAIL_SMTP_VERIFY_PEER(προεπιλογή ενεργή επαλήθευση). Με τιμή0/falseαπενεργοποιείται ο έλεγχος peer όταν ο πάροχος δίνει πιστοποιητικό με CN διαφορετικό από τοMAIL_HOST(χρήση μόνο αν δεν διορθώνεται το hostname). Εφαρμόζεται σε πρόσκληση χρήστη, reset κωδικού (Helpers,AuthController). Ενημερώθηκαν.env.exampleκαιdocs/01-getting-started/local-setup.md. - Πρόσκληση χρήστη / SMTP: Όταν αποτυγχάνει το email πρόσκλησης, το API επιστρέφει πλέον το σφάλμα μεταφοράς (
mail_error+ κείμενο στοmessage) για διάγνωση (Helpers::sendUserInvitationEmail,CompanyUserController,settings-users.js). - Σύνδεση / ρόλοι & δικαιώματα στη συνεδρία: Στο
AuthController::loginUserαφαιρέθηκε το λανθασμένοarray_columnπάνω στις τιμές που επιστρέφουν ήδηRoleModel::getUserRolesκαιPermissionModel::getUserPermissions(λίστες string). Προηγουμένως άδειαζαν$_SESSION['roles']και$_SESSION['permissions'], οπότε δεν λειτουργούσαν έλεγχοι/μενού ανά δικαίωμα (π.χ. «Διαχείριση χρηστών» /manage_users). - Πελάτες / κινητό μοναδικό & εύρεση τηλεφώνου: Κινητό μοναδικό και API
lookup-contact. Στο modal νέου πελάτη και στην επεξεργασία: μήνυμα κάτω από τα τηλέφωνα, απενεργοποιημένο κουμπί αποθήκευσης όταν ο αριθμός υπάρχει ήδη (χωρίς αυτόματη μετάβαση). Ραντεβού: προεπιλογή συναλλασσόμενου, κείμενο βοήθειας, απόκρυψη «Δημιουργία πελάτη» όταν βρίσκεται υπάρχων (add-customer-modal.html.twig,add-appointment-modal.html.twig,edit.html.twig,skeleton.js,traders.js,calendar.js).
[2026-04-09]
- Ρυθμίσεις / διαχείριση χρηστών: Νέα σελίδα
/settings/users(μενού «Διαχείριση χρηστών» για λογαριασμούς με δικαίωμαmanage_users). Προσθήκη μελών με ρόλο Διαχειριστής, Γραμματέας, Αποθηκάριος ή Οδηγός· αποστολή email με προσωρινό κωδικό και σύνδεσμο. API:GET/POST /api/company/users(CompanyUserModel::listMembersWithRoles,CompanyUserController,Helpers::sendUserInvitationEmail,settings-users.js,sidebar.html.twig). - Παραστατικά / τιμολόγηση (
dochead.invoice): Στη δημιουργία δελτίου παραλαβής επιλέγετε αν το παραστατικό τιμολογείται (προεπιλογή ναι)· αποθηκεύεταιinvoice0/1. Η λίστα δελτίων έχει στήλη εικονιδίου· στην προβολή δελτίου, στο πλευρικό panel και στον πίνακα φυσικών ειδών πελάτη εμφανίζεται αν τιμολογείται (create.html.twig,edit.html.twig,list.html.twig,documents.js,documents-list.js,documents-edit.js,document-panel.js,traders.js,DocumentController,DocumentModel::getAll,ItemStorageModel::findStoragesForTrader). - Κατάλογος / «Πλύσιμο»: Σε κάθε νέα εταιρεία εξασφαλίζεται η υπηρεσία Πλύσιμο (και μετά το seed τιμών καταλόγου). Κάθε νέο είδος και κάθε νέα υποκατηγορία είδους συνδέονται αυτόματα με Πλύσιμο και γενική τιμή καταλόγου (
PlisisimoProvisioner,ItemController,ItemCategoryController,CompanyDefaultsService). Στη δημιουργία δελτίου, μόλις επιλέγετε είδος σε γραμμή, προστίθεται αυτόματα η υπηρεσία Πλύσιμο (αν υπάρχει στον κατάλογο — προτιμάται σύνδεση χωρίς υποκατηγορία) (public/assets/js/documents.js). - Αποθήκη / barcodes: Στο αποτέλεσμα αναζήτησης (
/warehouse/barcodes) το ονοματεπώνυμο συναλλασσόμενου είναι πλέον σύνδεσμος που ανοίγει την καρτέλα πελάτη ή συνεργάτη σε νέο παράθυρο (target="_blank")· τοlookupεπιστρέφειtrader_type(ItemStorageModel::findFullContextByStorageId,warehouse-barcodes.js). - Αποθήκη / ράφι & ποσότητα: Η αποθήκευση «ραφιού & ποσότητας» (
PATCH /api/warehouse/storage/{id}μεshelf+quantity) απαιτεί πλέον μη κενό ράφι και ποσότητα > 0 (≥ 0,01 για τ.μ.)· ίδιοι έλεγχοι στο UI barcodes και στο modal φυσικού είδους πελατολογίου (WarehouseController::patchStorageShelfAndQuantity,warehouse-barcodes.js,traders.js). - Δελτίο / δημιουργία: Η προεπιλογή ποσότητας τ.μ. (είδη ανά τετραγωνικό) στη φόρμα νέου παραστατικού είναι 0 και όχι 1· το API αποδέχεται αποθήκευση 0 στο
item_storage(χωρίς εξαναγκασμό σε 1) — ενδεικτικά για υπολογισμούς και κλείσιμο ισχύουν οι υπάρχοντες έλεγχοι τ.μ. (documents.js,DocumentController,DocumentModel). - Πελάτης / modal φυσικό είδος (barcode): Όταν λείπει barcode στο είδος αλλά το δελτίο έχει εύρος με διαθέσιμους αριθμούς, το
GET /api/warehouse/lookup?storage_id=επιστρέφειpick_choices[]μεslot_barcode(ίδια αντιστοίχιση με την αποθήκη)· στο modal εμφανίζεται dropdown για επιλογή γραμμής και «Αποθήκευση barcode» συνδέει τον αριθμό στην επιλεγμένη γραμμή (ItemStorageModel::findStoragesMissingBarcodeOnDocForPick,WarehouseController::lookup,Traders/edit.html.twig,traders.js). - Αποθήκη / αναζήτηση barcode: Η επίλυση «μόνο στο εύρος δελτίου» (
findStorageIdByDocheadBarcodeRange) χρησιμοποιεί πλέον την ίδια αντιστοίχιση με το εικονικό barcode (mapVirtualBarcodesFromDocheadRange) και όχιparts[idx]— ώστε η σάρωση π.χ. 11 να ανοίγει το σωστό είδος, όχι αυτό που αντιστοιχούσε στο 10 λόγω λάθους θέσης (ItemStorageModel). - Αποθήκη / εύρος δελτίου (εικονικό barcode): Η αντιστοίχιση «κενό barcode στο είδος → αριθμός από
barcode_range» δεν χρησιμοποιεί πλέον απλάparts[idx]ανά σειρά· αφαιρούνται πρώτα οι αριθμοί που είναι ήδη καταχωρημένοι σε άλλη γραμμή, ώστε να μην εμφανίζονται δύο φορές το ίδιο (π.χ. 11 και 11 αντί για 10 και 11). Νέα μέθοδοςItemStorageModel::mapVirtualBarcodesFromDocheadRange· χρησιμοποιείται και στην προβολή γραμμών δελτίου (DocumentModel::getItemsDetailed). - Αποθήκη / εύρος barcode (διόρθωση): Αποφεύγεται αναφορά
foreach ($rows as &$row)και κοινόpick_choicesarray ανά γραμμή — ώστε να μην «αλλοιώνονται» τυχαία τα πεδία barcode/γραμμών σε άλλες εγγραφές JSON. Ίδια λογική στοItemStorageModelγια το virtual barcode (WarehouseController,ItemStorageModel). - Αποθήκη / εύρος barcode: Ο πίνακας αποτελεσμάτων Από–Έως παραμένει όπως πριν (στήλες barcode, είδος, ράφι, ποσότητα, παραστατικό, κατάσταση, συναλλασσόμενος)· όταν το barcode προέρχεται από το εύρος δελτίου χωρίς να είναι ακόμα στο είδος, στη στήλη Είδος εμφανίζεται dropdown (
pick_choices) με τις γραμμές του δελτίου χωρίς barcode + Σύνδεση. ΤοGET /by-barcode-rangeεμπλουτίζει τις εγγραφές μεpick_choicesότανneeds_barcode_link(WarehouseController::byBarcodeRange,warehouse-barcodes.js,barcodes.html.twig). - Αποθήκη / barcodes: Όταν σκανάρετε barcode που ανήκει στο εύρος δελτίου αλλά δεν έχει ακόμα συνδεθεί σε
item_storage, εμφανίζεται λίστα επιλογής με τα φυσικά είδη του ίδιου δελτίου που δεν έχουν barcode είδους (είδος + υπηρεσίες)· μετά τη σύνδεση ανοίγει το γνωστό panel. Αν το barcode είναι ήδη στο είδος, η συμπεριφορά παραμένει η ίδια (WarehouseController::lookup,ItemStorageModel,barcodes.html.twig,warehouse-barcodes.js). - Αποθήκη / API
PATCH /storage/{id}: Ράφι και ποσότητα υποχρεωτικά μαζί στο ίδιο αίτημα· το barcode μόνο σε ξεχωριστό αίτημα (αυστηρό κενό μεταξύ των δύο). Στο modal πελάτη: κουμπί «Αποθήκευση barcode» χωριστά από «Αποθήκευση ραφιού & ποσότητας» (WarehouseController,Traders/edit.html.twig,traders.js). - Πελάτης / φυσικά είδη: Στον πίνακα «Υπηρεσίες» (καρτέλα πελάτη) εμφανίζεται το ίδιο barcode μόνο αν έχει καταχωρηθεί στο είδος· αλλιώς εμφανίζεται το εύρος δελτίου (
barcode_range) — όχι πλέον «ψευδές» barcode από τη θέση στο εύρος. Στο modal επεξεργασίας φυσικού είδους: πεδίο Barcode είδους (επεξεργάσιμο όταν το δελτίο είναι ανοιχτό), Εύρος δελτίου μόνο ανάγνωση· τοPATCH /api/warehouse/storage/{id}δέχεται προαιρετικόbarcode(ItemStorageModel::findStoragesForTrader,updateBarcodeForStorage,WarehouseController,traders.js,Traders/edit.html.twig). - Δελτίο / barcode (φόρμα δημιουργίας): Δίπλα στο «Πρώτο barcode» εμφανίζεται read-only το πλήρες εύρος που θα αποθηκευτεί στο δελτίο· αφαιρέθηκε το κείμενο βοήθειας κάτω από το πεδίο (
create.html.twig,documents.js). - Δελτίο / barcode: Στη δημιουργία δελτίου δηλώνεται μόνο το πρώτο barcode· για κάθε είδος εκχωρούνται διαδοχικοί αριθμοί και το πλήρες εύρος αποθηκεύεται μόνο στο dochead (
barcode_range) — ταitem_storageδημιουργούνται χωρίς barcode (η σάρωση/αποθήκη συνεχίζουν να λειτουργούν μέσω του εύρους του δελτίου). ΕνημερώθηκανDocumentModel::createDocument,getItemsDetailed,ItemStorageModel(εύρος αποθήκης & πελάτης),create.html.twig,documents.js,warehouse-barcodes.js. - Υπηρεσίες / «Ανά Παραστατικό»: Η αλλαγή τιμής καταλόγου για υπηρεσία εμβέλειας «ανά παραστατικό» γίνεται πλέον με ενημέρωση της υπάρχουσας σύνδεσης (
PUT /api/item-services/{id}) αντί για διαγραφή+δημιουργία — ώστε να μην εμφανίζεται σφάλμα «συσχετισμένες εγγραφές» όταν το δελτίο έχει ήδη γραμμές που δείχνουν σε αυτή τη σύνδεση (ItemServiceController,ItemServiceModel,items.js,ApiRoutes.php). - Ραντεβού / εξαγωγή: Excel/PDF από το ημερολόγιο (
/appointments, dashboard): καθετη χρονολογική λίστα· φίλτρο ανά προβολή (ημέρα / εβδομάδα / 42ήμερο πλέγμα μήνα μέσω__calendarExportGetRange)· χωρίς στήλη Κατάσταση (appointments-export.js,dashboard-calendar.js,calendar.html.twig,Helpers.php). - Παραστατικά / λίστα: Στη λίστα
/documentsπροστέθηκε σύνολο ποσού (€) στοtfootγια τα τρέχοντα φίλτρα, καθώς και εξαγωγή Excel και PDF (ίδια δεδομένα με το φιλτραρισμένο σύνολο)· φόρτωσηxlsx/html2pdfαπόHelpers.php(list.html.twig,documents-list.js). - Παραστατικά / λίστα: Στη σελίδα
/documentsπροστέθηκαν φίλτρα Φύλαξη (όλα / με φύλαξη / χωρίς φύλαξη) και Express (όλα / Express / όχι Express), μαζί με τον καθαρισμό φίλτρων (list.html.twig,documents-list.js). - Παραστατικά / λίστα: Στη στήλη Συσχέτιση (
/documents) εμφανίζεται πλέον η περιγραφή σειράς του συσχετισμένου δελτίου (π.χ. ΔΕΛΤΙΟ ΠΑΡΑΛΑΒΗΣ / ΠΑΡΑΔΟΣΗΣ) μαζί με τον αριθμό δελτίου, όχι μόνο#…· τοGET /api/documentsεπιστρέφειcorrelated_series_descr,correlated_series_code(DocumentModel::getAll,documents-list.js). - Παραστατικά / καρτέλα πελάτη: Όταν ανοίγει η φόρμα ραντεβού πριν το κλείσιμο δελτίου από το πλευρικό panel (π.χ.
/traders/customers/edit/…), το offcanvas κλείνει πρόσκαιρα ώστε το modal ραντεβού να εμφανίζεται μπροστά· σε ακύρωση το panel ξανανοίγει. Κλήσηinit()στηνopenBeforeCloseDeliveryAppointmentώστε να είναι σίγουρα δεμένα handlers φόρμας (calendar.js). - Παραστατικά / ραντεβού πριν κλείσιμο: Όταν ανοίγει η φόρμα ραντεβού από το βήμα «πρώτα ραντεβού παράδοσης», το τρέχον δελτίο παραλαβής παραμένει προεπιλεγμένο στη σύνδεση παραστατικού (δεν ακυρώνεται πλέον από την αλλαγή πελάτη στο modal ούτε από επανάληψη ανανέωσης της λίστας)·
calendar.js(__docCloseAfterApptSave,onTraderOrCreateModeChanged,openBeforeCloseDeliveryAppointment). - Παραστατικά / UI: Οι επιβεβαιώσεις κλεισίματος δελτίου και του προαιρετικού βήματος «ραντεβού πριν το κλείσιμο» χρησιμοποιούν πλέον
Toast.confirm(@tsirosgeorge/toastnotification, κεντρική επιβεβαίωση με overlay) αντί γιαwindow.confirm(documents-edit.js,document-panel.js). - Παραστατικά / κλείσιμο & ραντεβού: Αν δεν υπάρχει ήδη ραντεβού με
id_dochead= το δελτίο παραλαβής που κλείνετε, μπορεί να ερωτηθείτε αν θέλετε πρώτα ραντεβού παράδοσης· αποθηκεύετε το ραντεβού με σύνδεση στο τρέχον δελτίο παραλαβής, και μετά εκτελείται το κλείσιμο (POST …/close) ώστε τοrepointDeliveryAppointmentsToNewDeliveryDocνα μεταφέρει τη σύνδεση στο νέο δελτίο αποστολής (CalendarAppointments.openBeforeCloseDeliveryAppointment,handleFormSubmitστοcalendar.js,documents-edit.js,document-panel.js). ΤοGET /api/documents/{id}επιστρέφειlinked_appointment_count· τοPOST …/closeεπιστρέφειnew_iddocseries,new_series_descr. - Πελάτης / UI: Στην καρτέλα πελάτη, στήλη «Παραστατικό» (φυσικά είδη) και στήλη «Δελτίο» (ραντεβού) εμφανίζεται πλέον η περιγραφή σειράς (
docseries.descr, π.χ. ΔΕΛΤΙΟ ΠΑΡΑΛΑΒΗΣ) αντί του κωδικού σειράς (CODE)· fallback στον κωδικό αν λείπει περιγραφή (ItemStorageModel::findStoragesForTraderπεδίοseries_descr,traders.js— τα ραντεβού είχαν ήδηdoc_series_descrστο API). - Παραστατικά / λίστα: Στη λίστα δελτίων (
/documents) το όνομα συναλλασσόμενου είναι σύνδεσμος προς την καρτέλα επεξεργασίας (/traders/customers/edit/…ή…/partners/…ανάλογα με τον τύπο)· το API λίστας επιστρέφει πλέονtrader_type(DocumentModel::getAll,documents-list.js). - Παραστατικά / slider (offcanvas): Στο πλευρικό panel προβολής παραστατικού (π.χ. από σελίδα πελάτη) προστέθηκε κουμπί Κλείσιμο παραστατικού για ανοιχτά δελτία — ίδια επιβεβαίωση και κλήση
POST /api/documents/{id}/closeμε την πλήρη σελίδα (document_panel.html.twig,document-panel.js). - Παραστατικά / ροή: Μετά την επιτυχή δημιουργία δελτίου από τη φόρμα (
/documents/create), η εφαρμογή μεταφέρει πλέον στη λίστα παραστατικών (/documents) αντί να ανοίγει ξανά τη φόρμα νέου δελτίου (public/assets/js/documents.js). - UI / εικονίδια: Προστέθηκαν εικονίδια Font Awesome σε κουμπιά και ενέργειες (ημερολόγιο: προβολή Μήνα/Εβδομάδα/Ημέρα, Νέος Πελάτης, Νέο Ραντεβού· modals νέου πελάτη/ραντεβού· dropdown «Νέο» στο navbar· Άκυρο σε φόρμες επεξεργασίας συναλλασσόμενου/δρομολογίου/οχήματος/προγράμματος· σελίδες σφαλμάτων 403/404/405). Αρχεία:
calendar.html.twig,add-appointment-modal.html.twig,add-customer-modal.html.twig,navbar.html.twig,Traders/edit.html.twig,Routes/edit.html.twig,Vehicles/edit.html.twig,Schedules/edit.html.twig,Errors/403|404|405.html.twig. - Παραστατικά / UI: Αφαιρέθηκε η εμφάνιση τύπου χρέωσης υπηρεσίας (σταθερό / ανά τ.μ.) από την προβολή δελτίου (
documents-edit.js) και από τη φόρμα νέου δελτίου (documents.js) — παραμένει η λογική τιμολόγησης στοdata-rate/calculateTotals. - UI / ειδοποιήσεις: Το
toast-helper.jsκαλούσε baretoast· σε ορισμένα περιβάλλοντα τοtoastδεν είναι στο global scope και προκαλούσεReferenceError: toast is not defined(π.χ. μετά από ενέργεια στην αποθήκη barcodes). Χρησιμοποιείται πλέον ρητάwindow.toast· ενημερώθηκανdocuments-edit.js,traders.js,skeleton.js(__appToast). - Παραστατικά / αποθήκη: Όταν το δελτίο είναι κλειστό (
doc_status = closed), αποκλείονται επεξεργασία μέσω API αποθήκης (ράφι, τ.μ., γραμμές υπηρεσιών, προσθήκη υπηρεσίας) και διαγραφή δελτίου·DocumentModel::mutationBlockReason,WarehouseController,DocumentController::destroy· ειδοποίηση και απενεργοποίηση πεδίων στοwarehouse-barcodes.js, modal αποθήκης στοtraders.js, μπάνερ προβολής στοdocuments-edit.js/edit.html.twig,barcodes.html.twig. - Ραντεβού / δελτία: Όταν κλείνει δελτίο παραλαβής (σειρά 239) και δημιουργείται το δελτίο παράδοσης, τα ραντεβού τύπου παράδοση που ήταν συνδεδεμένα με το κλειστό δελτίο ενημερώνονται αυτόματα ώστε το
id_docheadνα δείχνει στο νέο παραστατικό παράδοσης (DocumentModel::closeDocument,AppointmentModel::repointDeliveryAppointmentsToNewDeliveryDoc). - Ραντεβού / δελτία: Στο modal ραντεβού, όταν ο τύπος είναι παράδοση αλλά το συνδεδεμένο ανοιχτό δελτίο είναι ακόμα παραλαβής (σειρά 239), ο σύνδεσμος δεν εμφανίζει πλέον «Παραστατικό παράδοσης» — εμφανίζεται «Δεν έχει κοπεί ακόμα παραστατικό παράδοσης»· όταν το δελτίο είναι η σειρά παράδοσης (ζεύξη, codeid 3), παραμένει «Παραστατικό παράδοσης». Προστέθηκε
iddocseriesστα ανοιχτά παραστατικά (DocumentModel::findOpenDocumentsForTrader) καιdoc_iddocseriesστα ραντεβού (AppointmentModel), ενημερώθηκεpublic/assets/js/calendar.js. - Ραντεβού / δελτία: Στο
calendar.jsπροστέθηκε σταθεράDOCUMENT_VIEW_BASE(/documents) για τον σύνδεσμο «συνδεδεμένο παραστατικό» στο modal ραντεβού (ξεκάθαρο ότι δεν χρησιμοποιείται/docs/της τεκμηρίωσης). - Δρομολόγηση / δελτία: Οι σελίδες δελτίων (views) μεταφέρθηκαν από
/docs/...σε/documents/...ώστε να μην συγκρούεται με το στατικό MkDocs στο/docs/· ενημερώθηκανapp/Routes/ViewRoutes.php, μενού (sidebar,navbar), Twig δελτίων/συναλλασσομένων, και JS (documents.js,documents-list.js,documents-edit.js,document-panel.js,calendar.js,warehouse-barcodes.js)·docs/01-getting-started/architecture-overview.md. - Τεκμηρίωση / MkDocs: Στο
mkdocs.ymlορίστηκεuse_directory_urls: falseώστε να παράγεταιpublic/docs/changelog.html(και γενικά.htmlανά σελίδα) αντί για μόνοchangelog/index.html· ενημερώθηκανdocs/README.mdκαιdocs/01-getting-started/local-setup.md. - Cursor / ρυθμίσεις: Ενημερώθηκε το
.cursorrulesώστε τοmkdocs buildνα ζητείται και όταν αλλάζει τοchangelog.mdστη ρίζα ή τοmkdocs.yml(όχι μόνο τα Markdown κάτω απόdocs/). - Τεκμηρίωση / MkDocs: Το
docs/changelog.mdενσωματώνει πλέον τοchangelog.mdτης ρίζας μέσωpymdownx.snippets(αντί για symlink)· προστέθηκε ρητή αναφορά στην αρχική σελίδα τεκμηρίωσης (docs/README.md)· ενημερώθηκανmkdocs.ymlκαιdocs/01-getting-started/local-setup.md. - Τεκμηρίωση / MkDocs: Το
public/docs/δεν αγνοείται στο.gitignore(για commit)· διαγράφηκε ο παλιός φάκελοςsite/και προστέθηκεsite/στο.gitignore(προεπιλογή MkDocs./site/)· ενημερώθηκε τοdocs/01-getting-started/local-setup.md. - Τεκμηρίωση / MkDocs: Προστέθηκαν
mkdocs.yml,requirements-docs.txt, και οδηγίες στοdocs/01-getting-started/local-setup.md· τοmkdocs buildπαράγει HTML στοpublic/docs/(URL/docs/). Σελίδα ιστορικού:docs/changelog.md(περιεχόμενο απόchangelog.mdστη ρίζα)· ενημερώθηκε τοdocs/README.md.
[2026-04-06]
- Τεκμηρίωση χρήστη: Προστέθηκε
docs/odigos-hristi/— αναλυτικός οδηγός για τελικούς χρήστες (μενού, ροές εργασίας, συμπεριφορά πελατολογίου, δελτίων, ραντεβού, αποθήκης, χωρίς προγραμματιστική ορολογία). Αναδιοργάνωσηdocs/README.md· τα παλιά02-features/*.mdαντικαταστάθηκαν από ανακατεύθυνση στον οδηγό χρήσης. - Τεκμηρίωση: Προστέθηκε φάκελος
docs/με οδηγό εγκατάστασης, επισκόπηση αρχιτεκτονικής, και σκελετοί αναφοράς ανά module (03-reference/)· όλα στα ελληνικά. - Συναλλασσόμενοι / modal νέου πελάτη: Διόρθωση ώστε το κενό πεδίο κωδικού να μην στέλνεται ως συμβολοσειρά
"null"μέσωURLSearchParams· έτσι εφαρμόζεται η αυτόματη ανάθεση κωδικώνPEL-####όταν το πεδίο αφήνεται κενό (public/assets/js/skeleton.js). - Συναλλασσόμενοι / modal νέου πελάτη: Η επιλογή «Είναι ιδιώτης» εμφανίζεται πάντα (όχι μόνο από το ημερολόγιο)· η συμπεριφορά ΑΦΜ
000000000παραμένει ίδια (add-customer-modal.html.twig,skeleton.js). - Παραστατικά / δημιουργία: Προεπιλογή χωρίς τικ σε «Με Φύλαξη» και «Express»· στο JS χρήση ρητού
checked === true· ευθυγράμμιση προεπιλογών API γιαwith_fylakis/is_express(create.html.twig,documents.js,DocumentController.php). - Παραστατικά / δημιουργία: Προκαταβολή επιτρέπεται να υπερβαίνει το σύνολο του παραστατικού· αφαιρέθηκαν όρια στον client και στον server· παραμένει μόνο ο έλεγχος μη αρνητικής τιμής (
documents.js,DocumentController.php).