Files
opensourcepos/app/Language/el/Sales.php
Nozomu Sasaki (Paul) 85c7ce2da4 Fix negative price/quantity/discount validation (GHSA-wv3j-pp8r-7q43) (#4450)
* Fix business logic vulnerability allowing negative sale totals (GHSA-wv3j-pp8r-7q43)

Add server-side validation in postEditItem() to reject negative prices,
quantities, and discounts, as well as percentage discounts exceeding 100%
and fixed discounts exceeding the item total. Also block sale completion
with negative totals in non-return mode to prevent fraud/theft.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix: exempt return mode from negative quantity validation

Return mode legitimately stores items with negative quantities.
The quantity validation now skips the non-negative check in return mode,
consistent with the existing return mode exemption in postComplete().
Also use abs() for fixed discount comparison to handle return quantities.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Refactor: use $rules + validate() pattern per review feedback

Address review comments from jekkos on PR #4450:

1. Use CI4 $rules variable with custom non_negative_decimal validation
   rule instead of manual if-checks for price/discount validation.

2. Add validation error strings to all 44 non-English language files
   (English fallback values used until translations are contributed).

3. Use validate() method with $messages array for localized error
   display, maintaining the existing controller pattern.

Additional improvements:
- Add non_negative_decimal rule to OSPOSRules.php (leverages
  parse_decimals() for locale-aware decimal parsing)
- Preserve manual checks for business logic (return mode quantity
  exemption, discount bounds via bccomp)
- Fix PHP 8.1+ compatibility: avoid passing method return to reset()
- Explicit empty discount handling for bc-math safety

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix: rename to nonNegativeDecimal (PSR), clear non-English translation strings

- Rename validation rule method non_negative_decimal → nonNegativeDecimal in
  OSPOSRules.php and all $rules/$messages references in Sales.php (PSR naming
  per @objecttothis review)
- Replace English fallback text with "" in 43 non-English language files so
  CI4 falls back to the base language string; weblate will handle translations
  (per @jekkos and @objecttothis agreement)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Paul <morimori-dev@github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-04-03 14:49:42 +04:00

232 lines
17 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
return [
"customers_available_points" => "Διαθέσιμοι Πόντοι",
"rewards_package" => "Ανταμοιβές",
"rewards_remaining_balance" => "Η αξία των υπολειπόμενων πόντων ανταμοιβής είναι ",
"account_number" => "Λογαριασμός #",
"add_payment" => "Προσθήκη Πληρωμής",
"amount_due" => "Ποσό επιστροφής",
"amount_tendered" => "Ποσό Είσπραξης",
"authorized_signature" => "Εγκεκριμένη Υπογραφή",
"cancel_sale" => "Ακύρωση",
"cash" => "Μετρητά",
"cash_1" => "",
"cash_2" => "",
"cash_3" => "",
"cash_4" => "",
"cash_adjustment" => "",
"cash_deposit" => "Προκαταβολή Μετρητών",
"cash_filter" => "Μετρητά",
"change_due" => "Ποσό Επιστροφής",
"change_price" => "",
"check" => "Επιταγή",
"check_balance" => "Υπόλοιπο Επιταγής",
"check_filter" => "Επιταγή",
"close" => "",
"comment" => "Σχόλιο",
"comments" => "Σχόλια",
"company_name" => "",
"complete" => "",
"complete_sale" => "Ολοκλήρωση",
"confirm_cancel_sale" => "Είστε σίγουροι πως θέλετε να ακυρώσετε την συναλλαγή? Όλα τα είδη θα χαθούν.",
"confirm_delete" => "Είστε σίγουροι πως θέλετε να διαγράψετε την/τις επιλεγμένες Πωλήσεις?",
"confirm_restore" => "Είστε σίγουροι πως θέλετε να επαναφέρετε την/τις επιλεγμένες Πωλήσεις?",
"credit" => "Πιστωτική Κάρτα",
"credit_deposit" => "Ποσό Πίστωσης",
"credit_filter" => "",
"current_table" => "",
"customer" => "Όνομα",
"customer_address" => "Διεύθυνση",
"customer_discount" => "Έκπτωση",
"customer_email" => "Διεύθυνση ηλεκτρονικού ταχυδρομείου",
"customer_location" => "Τοποθεσία",
"customer_mailchimp_status" => "Κατάσταση Mailchimp",
"customer_optional" => "(Απαραίτητο για πληρωμές επί Πιστώσει)",
"customer_required" => "(Απαραίτητο)",
"customer_total" => "Σύνολο",
"customer_total_spent" => "",
"daily_sales" => "",
"date" => "Ημερομηνία Πώλησης",
"date_range" => "Εύρος Ημερομηνιών",
"date_required" => "Πρέπει να εισάγετε μια σωστή ημερομηνία.",
"date_type" => "Ημερομηνία είναι απαραίτητο πεδίο.",
"debit" => "Χρεωστική Κάρτα",
"debit_filter" => "",
"delete" => "Επιτρέπεται Διαγραφή",
"delete_confirmation" => "Είστε σίγουροι πως θέλετε να διαγράψετε την πώληση? Η διαγραφή δε αναιρείται.",
"delete_entire_sale" => "Διαγραφή Ολόκληρης Πώλησης",
"delete_successful" => "Διαγραφή Πώλησης επιτυχής.",
"delete_unsuccessful" => "Αποτυχία διαγραφής Πώλησης.",
"description_abbrv" => "Περιγρ.",
"discard" => "Απόρριψη",
"discard_quote" => "",
"discount" => "Έκπτ.",
"discount_included" => "% Έκπτωσης",
"discount_short" => "%",
"due" => "Πρέπει να πληρωθεί",
"due_filter" => "Πρέπει να πληρωθεί",
"edit" => "Επεξεργασία",
"edit_item" => "Επεξεργασία είδους",
"edit_sale" => "Επεξεργασία Πώλησης",
"email_receipt" => "Απόδειξη Ηλεκτρονικού Ταχυδρομείου",
"employee" => "Υπάλληλος",
"entry" => "Εγγραφή",
"error_editing_item" => "Σφάλμα επεξεργασίας είδους",
"negative_price_invalid" => "",
"negative_quantity_invalid" => "",
"negative_discount_invalid" => "",
"discount_percent_exceeds_100" => "",
"discount_exceeds_item_total" => "",
"negative_total_invalid" => "",
"find_or_scan_item" => "Εύρεση ή Σκανάρισμα Είδους",
"find_or_scan_item_or_receipt" => "Εύρεση ή Σκανάρισμα είδους ή Απόδειξης",
"giftcard" => "Δωροκάρτα",
"giftcard_balance" => "Υπόλοιπο Δωροκάρτας",
"giftcard_filter" => "",
"giftcard_number" => "Αριθμός Δωροκάρτας",
"group_by_category" => "Ομαδοποίηση ανά Κατηγορία",
"group_by_type" => "Ομαδοποίηση ανά Είδος",
"hsn" => "HSN",
"id" => "ID Πώλησης",
"include_prices" => "Συμπερίληψη Τιμών?",
"invoice" => "Τιμολόγιο",
"invoice_confirm" => "Το τιμολόγιο θα αποσταλεί σε",
"invoice_enable" => "Δημιουργία Τιμολογίου",
"invoice_filter" => "Τιμολόγια",
"invoice_no_email" => "Ο Πελάτης δεν έχει έγκυρο λογαριασμό ταχυδρομείου.",
"invoice_number" => "Τιμολόγιο #",
"invoice_number_duplicate" => "Ο Αριθμός Τιμολογίου πρέπει να είναι μοναδικός.",
"invoice_sent" => "Το Τιμολόγιο απεστάλη σε",
"invoice_total" => "Σύνολο Τιμολογίου",
"invoice_type_custom_invoice" => "Προσαρμοσμένο Τιμολόγιο (custom_invoice.php)",
"invoice_type_custom_tax_invoice" => "Προσαρμοσμένο Φορολογικό Τιμολόγιο (custom_tax_invoice.php)",
"invoice_type_invoice" => "Τιμολόγιο (invoice.php)",
"invoice_type_tax_invoice" => "Φορολογικό Τιμολόγιο (tax_invoice.php)",
"invoice_unsent" => "Ανεπιτυχής αποστολή Τιμολογίου σε",
"invoice_update" => "Επαναμέτρηση",
"item_insufficient_of_stock" => "Το είδος έχει ανεπαρκή απόθεμα.",
"item_name" => "Όνομα Είδους",
"item_number" => "# Είδους",
"item_out_of_stock" => "Το είδος δεν υπάρχει σε απόθεμα.",
"key_browser" => "",
"key_cancel" => "Cancels Current Quote/Invoice/Sale",
"key_customer_search" => "Customer Search",
"key_finish_quote" => "Finish Quote/Invoice witdout payment",
"key_finish_sale" => "Add Payment and Complete Invoice/Sale",
"key_full" => "",
"key_function" => "Function",
"key_help" => "Shortcuts",
"key_help_modal" => "Open Shortcuts Window",
"key_in" => "",
"key_item_search" => "Item Search",
"key_out" => "",
"key_payment" => "Add Payment",
"key_print" => "",
"key_restore" => "",
"key_search" => "",
"key_suspend" => "Suspend Current Sale",
"key_suspended" => "Show Suspended Sales",
"key_system" => "",
"key_tendered" => "Edit Amount Tendered",
"key_title" => "Sales Keyboard Shortcuts",
"mc" => "",
"mode" => "Λειτουργία Ταμείου",
"must_enter_numeric" => "Το Ποσό Είσπραξης πρέπει να είναι Αριθμός.",
"must_enter_numeric_giftcard" => "Ο Αριθμός της Δωροκάρτας πρέπει να είναι αριθμός.",
"new_customer" => "Νέος Πελάτης",
"new_item" => "Νέο Είδος",
"no_description" => "Δεν έχει περιγραφή",
"no_filter" => "Όλα",
"no_items_in_cart" => "Δεν υπάρχουν είδη στο καλάθι.",
"no_sales_to_display" => "Δεν υπάρχουν Πωλήσεις προς προβολή.",
"none_selected" => "Δεν έχετε επιλέξει Πώληση/σεις για διαγραφή.",
"nontaxed_ind" => "",
"not_authorized" => "Αυτή η ενέργεια δεν είναι εξουσιοδοτημένη.",
"one_or_multiple" => "Πώληση/εις",
"payment" => "Τύπος Πληρωμής",
"payment_amount" => "Ποσό",
"payment_not_cover_total" => "Το Ποσό πρέπει να είναι μεγαλύτερο ή ίσο του Συνόλου.",
"payment_type" => "Τύπος",
"payments" => "",
"payments_total" => "Συνολικό Ποσό",
"price" => "Τιμή",
"print_after_sale" => "Εκτύπωση μετά την Πώληση",
"quantity" => "Ποσότητα",
"quantity_less_than_reorder_level" => "Προσοχή: Επιθυμητή Ποσότητα είναι λιγότερη από την τιμή Επαναπαραγγελίας για το είδος.",
"quantity_less_than_zero" => "Προσοχή: Επιθυμητή Ποσότητα είναι ανεπαρκής. Μπορείτε να επεξεργαστείτε την πώληση, αλλά ελέγξτε το απόθεμα.",
"quantity_of_items" => "Ποσότητα των {0} Ειδών",
"quote" => "Παράθεση",
"quote_number" => "Αριθμός Παράθεσης",
"quote_number_duplicate" => "Ο Αριθμός Παράθεσης πρέπει να είναι μοναδικός.",
"quote_sent" => "Η Παράθεση απεστάλη σε",
"quote_unsent" => "Αποτυχία αποστολής Παράθεσης σε",
"receipt" => "Απόδειξη Πώλησης",
"receipt_no_email" => "Ο πελάτης δεν έχει έγκυρη διεύθυνση ηλεκτρονικού ταχυδρομείου.",
"receipt_number" => "Πώληση #",
"receipt_sent" => "Η Απόδειξη εστάλη σε",
"receipt_unsent" => "Αποτυχία αποστολής Απόδειξης σε",
"refund" => "",
"register" => "Μητρώο Πωλήσεων",
"remove_customer" => "Αφαίρεση Πελάτη",
"remove_discount" => "",
"return" => "Επιστροφή",
"rewards" => "Πόντοι Ανταμοιβής",
"rewards_balance" => "Υπόλοιπο Πόντων Ανταμοιβής",
"sale" => "Πώληση",
"sale_by_invoice" => "Πώληση ανά Τιμολόγιο",
"sale_for_customer" => "Πελάτης:",
"sale_time" => "Ώρα",
"sales_tax" => "Φόρος Πώλησης",
"sales_total" => "",
"select_customer" => "Επιλογή Πελάτη",
"send_invoice" => "Αποστολή Τιμολογίου",
"send_quote" => "Αποστολή Παράθεσης",
"send_receipt" => "Αποστολή Απόδειξης",
"send_work_order" => "Αποστολή Εντολής Εργασίας",
"serial" => "Σειριακός",
"service_charge" => "",
"show_due" => "",
"show_invoice" => "Εμφάνιση Τιμολογίου",
"show_receipt" => "Εμφάνιση Απόδειξης",
"start_typing_customer_name" => "Πληκτρολογήστε τις λεπτομέρειες πελάτη...",
"start_typing_item_name" => "Πληκτρολογήστε το είδος ή σκανάρετε το Barcode...",
"stock" => "Απόθεμα",
"stock_location" => "Τοποθεσία Αποθέματος",
"sub_total" => "Υποσύνολο",
"successfully_deleted" => "Έχετε διαγράψει επιτυχώς",
"successfully_restored" => "Έχετε επαναφέρει επιτυχώς",
"successfully_suspended_sale" => "Αναμονή Πώλησης επιτυχής.",
"successfully_updated" => "Ενημέρωση Πώλησης επιτυχής.",
"suspend_sale" => "Αναμονή",
"suspended_doc_id" => "Έγγραφο",
"suspended_sale_id" => "ID",
"suspended_sales" => "Ανεστάλη",
"table" => "Πίνακας",
"takings" => "Ημερήσιες Πωλήσεις",
"tax" => "Φόρος",
"tax_id" => "Id Φόρου",
"tax_invoice" => "Φόρος τιμολογίου",
"tax_percent" => "% Φόρου",
"taxed_ind" => "",
"total" => "Σύνολο",
"total_tax_exclusive" => "Εξαιρουμένου Φόρου",
"transaction_failed" => "Συναλλαγή Πώλησης απέτυχε.",
"unable_to_add_item" => "Προσθήκη είδους στην Πώληση απέτυχε",
"unsuccessfully_deleted" => "Διαγραφή Πώλησης/εων απέτυχε.",
"unsuccessfully_restored" => "Επαναφορά Πώλησης/εων απέτυχε.",
"unsuccessfully_suspended_sale" => "Αναμονή Πώλησης απέτυχε.",
"unsuccessfully_updated" => "Ενημέρωση πώλησης απέτυχε.",
"unsuspend" => "Επαναφορά από Αναμονή",
"unsuspend_and_delete" => "Ενέργεια",
"update" => "Ενημέρωση",
"upi" => "UPI",
"visa" => "",
"wholesale" => "",
"work_order" => "Παραγγελία Εργασίας",
"work_order_number" => "Αριθμός Παραγγελίας Εργασίας",
"work_order_number_duplicate" => "Ο Αριθμός της Παραγγελίας Εργασίας πρέπει να είναι μοναδικός.",
"work_order_sent" => "Εντολή Εργασίας απεστάλη σε",
"work_order_unsent" => "Ανεπιτυχής αποστολή Εντολής Εργασίας",
];