Files
opensourcepos/app/Language/az/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
14 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" => "Mövcud ballar",
"rewards_package" => "Mükafatlar",
"rewards_remaining_balance" => "Mükafatın yerdə qalan bal dəyəri ",
"account_number" => "Hesab #",
"add_payment" => "Ödəniş Əlavə Etmək",
"amount_due" => "Qalıq",
"amount_tendered" => "Ödənilən məbləğ",
"authorized_signature" => "Səlahiyyətli İmza",
"cancel_sale" => "İmtina",
"cash" => "Nəğd pullar",
"cash_1" => "",
"cash_2" => "",
"cash_3" => "",
"cash_4" => "",
"cash_adjustment" => "Nağd pulun tənzimlənməsi",
"cash_deposit" => "Nağd depozit",
"cash_filter" => "Nəğd Pul",
"change_due" => "Qalıq",
"change_price" => "Satış qiymətini dəyiş",
"check" => "Çek",
"check_balance" => "Çek Xatırladan",
"check_filter" => "Çek",
"close" => "",
"comment" => "Şərh",
"comments" => "Şərhlər",
"company_name" => "",
"complete" => "",
"complete_sale" => "Tamamlayın",
"confirm_cancel_sale" => "Siz əminsiniz ki,satışı ləğv etmək istəyirsiniz? Bütün detallar silinəcək.",
"confirm_delete" => "Siz əminsiniz ki seçilmiş satışı (lar) silmək istəyirsiz?",
"confirm_restore" => "Seçilmiş Satışları bərpa etmək istədiyinizə əminsinizmi?",
"credit" => "Kredit kartı",
"credit_deposit" => "Kredit Depoziti",
"credit_filter" => "Kredit kartı",
"current_table" => "",
"customer" => "Ad",
"customer_address" => "Ünvan",
"customer_discount" => "Endirim",
"customer_email" => "E-poçt",
"customer_location" => "Yer",
"customer_mailchimp_status" => "Mailchimp Statusu",
"customer_optional" => "(Ödənişlərdə tələb olunur)",
"customer_required" => "(Vacib)",
"customer_total" => "Cəmi",
"customer_total_spent" => "",
"daily_sales" => "",
"date" => "Satış Tarixi",
"date_range" => "Tarix Aralığı",
"date_required" => "Düzgün tarix daxil edilməlidir.",
"date_type" => "Boşluğa tarix əlavə edilməlidir.",
"debit" => "Debit kart",
"debit_filter" => "",
"delete" => "Silməyə izin ver",
"delete_confirmation" => "Siz bu satışı silmək istəyinizə əminsiniz? Bu əməlliyat bərpa edilməyəcək.",
"delete_entire_sale" => "Bütün Satışı Silmək",
"delete_successful" => "Siz uğurla satışı sildiniz.",
"delete_unsuccessful" => "Satışın silinməsi uğursuz oldu.",
"description_abbrv" => "Təsvir.",
"discard" => "İmtina",
"discard_quote" => "",
"discount" => "Disk",
"discount_included" => "% Endirim",
"discount_short" => "%",
"due" => "Görə",
"due_filter" => "Görə",
"edit" => "Redaktə",
"edit_item" => "Malın Redaktəsi",
"edit_sale" => "Satışın Redaktəsi",
"email_receipt" => "E-poçt Qəbz",
"employee" => "Əməkdaş",
"entry" => "Daxil",
"error_editing_item" => "XƏTA Malın redaktəsində",
"negative_price_invalid" => "",
"negative_quantity_invalid" => "",
"negative_discount_invalid" => "",
"discount_percent_exceeds_100" => "",
"discount_exceeds_item_total" => "",
"negative_total_invalid" => "",
"find_or_scan_item" => "Malın axtarışı",
"find_or_scan_item_or_receipt" => "Tapmaq skan etmək və ya kvitansiya",
"giftcard" => "Hədiyyə Kartı",
"giftcard_balance" => "Hədiyyə Kartı Balansı",
"giftcard_filter" => "",
"giftcard_number" => "Hədiyyə kartının nömrəsi",
"group_by_category" => "Bölməyə görə grup",
"group_by_type" => "Növə görə qrup",
"hsn" => "HSN",
"id" => "Satış İD",
"include_prices" => "Qiymətlər daxildir?",
"invoice" => "Qaimə",
"invoice_confirm" => "Bu qaimə göndəriləcək",
"invoice_enable" => "Qaimə Yarat",
"invoice_filter" => "Qaimələr",
"invoice_no_email" => "Bu müştərinin elektron ünvanı düzgün deyil.",
"invoice_number" => "Qaimə #",
"invoice_number_duplicate" => "Qaimə nömrəsi unikal olmalıdır.",
"invoice_sent" => "Qaimə göndərildi",
"invoice_total" => "Qaimə Çəmi",
"invoice_type_custom_invoice" => "Fərqli Qaimə (custom_invoice.php)",
"invoice_type_custom_tax_invoice" => "Fərqli Vergi Qaiməsi (custom_tax_invoice.php)",
"invoice_type_invoice" => "Qaimə (invoice.php)",
"invoice_type_tax_invoice" => "Vergi Qaiməsi (tax_invoice.php)",
"invoice_unsent" => "Qaimə göndərilə bilmədi",
"invoice_update" => "Yeniden say",
"item_insufficient_of_stock" => "Anbarda kifayət qədər mal yoxdur.",
"item_name" => "Malın adı",
"item_number" => "Mal #",
"item_out_of_stock" => "Mal satılıb.",
"key_browser" => "Faydalı Qısayollar",
"key_cancel" => "Cari Kotirovka/Fatura/Satışı ləğv edir",
"key_customer_search" => "Müştəri Axtarışı",
"key_finish_quote" => "Ödəniş etmədən Kotirovka/Faturanı tamamlayın",
"key_finish_sale" => "Ödəniş əlavə edib, faktura/satışı tamamlayın",
"key_full" => "Tam Ekran rejimində açın",
"key_function" => "Function",
"key_help" => "Qısa yollar",
"key_help_modal" => "Qısa yollar pəncərəsini açın",
"key_in" => "Yaxınlaşdır",
"key_item_search" => "Element Axtarışı",
"key_out" => "Uzaqlaşdır",
"key_payment" => "Ödəniş əlavə et",
"key_print" => "Cari səhifəni çap et",
"key_restore" => "Orjinal ekran ölçüsünə qayıt",
"key_search" => "Axtarışın hesabat cədvəlləri",
"key_suspend" => "Cari satışı dayandırın",
"key_suspended" => "Dayandırılmış Satışları göstər",
"key_system" => "Sistem Qısayolları",
"key_tendered" => "Təklif olunan məbləği dəyişdirin",
"key_title" => "Satış üçün klaviatura qısa yolları",
"mc" => "",
"mode" => "Qeydiyyat Rejimi",
"must_enter_numeric" => "Ödəniş məbləği rəqəm ilə olmalıdır.",
"must_enter_numeric_giftcard" => "Hədiyyə Kartın nömrəsi rəqəmlə olmalıdır.",
"new_customer" => "Yeni Müştəri",
"new_item" => "Yeni Mal",
"no_description" => "Heç Biri",
"no_filter" => "Hamısı",
"no_items_in_cart" => "Səbətdə heç bir mal yoxdur.",
"no_sales_to_display" => "Satış yoxdur.",
"none_selected" => "Silmək üçün hər hansı bir Satış (lar) seçmədiniz.",
"nontaxed_ind" => " . ",
"not_authorized" => "Bu hərəkət səlahiyyətli deyil.",
"one_or_multiple" => "Satış (lar)",
"payment" => "Ödəniş Növü",
"payment_amount" => "Məbləğ",
"payment_not_cover_total" => "Ödəmə məbləği Toplamdan çox və ya bərabər olmalıdır.",
"payment_type" => "Növ",
"payments" => "",
"payments_total" => "Cəmi Ödənilənlər",
"price" => "Qiymət",
"print_after_sale" => "Satışdan sonra Çap edin",
"quantity" => "Miqdarı",
"quantity_less_than_reorder_level" => "Diqqət: İstədiyinizin Miqdarı bu Öhdəlik üçün Yenidən Səviyyə səviyyəsindən aşağıdadır.",
"quantity_less_than_zero" => "Xəbərdarlıq: İstədiyiniz miqdar kifayət deyil. Siz hələ də satışı edə bilərsiniz, lakin malın sayını yoxlayın.",
"quantity_of_items" => "{0} Məhsulların miqdarı",
"quote" => "Qiymət ver",
"quote_number" => "Sitat Nömrəsi",
"quote_number_duplicate" => "Sitatın nömrəsi unikal olmalıdır.",
"quote_sent" => "Sitat göndərildi",
"quote_unsent" => "Sitat göndırilə bilmədi",
"receipt" => "malın çeki",
"receipt_no_email" => "Bu müştərinin etibarlı bir e-poçt ünvanı yoxdur.",
"receipt_number" => "Satış №",
"receipt_sent" => "Çek Göndərildi",
"receipt_unsent" => "Çek göndərilə Bilmədi",
"refund" => "Qaytarılma növü",
"register" => "jurnal satışı",
"remove_customer" => "müştəriləri silmək",
"remove_discount" => "",
"return" => "qaytarmaq",
"rewards" => "Mükafat Balları",
"rewards_balance" => "Mükafat Balları Balansı",
"sale" => "satış",
"sale_by_invoice" => "Faktura ilə Satış",
"sale_for_customer" => "Müştəri:",
"sale_time" => "Vaxt",
"sales_tax" => "Satış Vergisi",
"sales_total" => "",
"select_customer" => "Müştəri seçmək",
"send_invoice" => "Faktura Göndər",
"send_quote" => "Sitat Göndər",
"send_receipt" => "Çek Göndər",
"send_work_order" => "İş Sifarişini Göndərin",
"serial" => "seriya nömrəsi",
"service_charge" => "",
"show_due" => "",
"show_invoice" => "Fakturanı Göstər",
"show_receipt" => "Çek Göstər",
"start_typing_customer_name" => "müştəri adını çap etməyə başlayın...",
"start_typing_item_name" => "Malın adın başlayın çap etməyə yada skan edin şifrəni...",
"stock" => "Anbar",
"stock_location" => "Ehtiyyatın Yeri",
"sub_total" => "yekun",
"successfully_deleted" => "satış",
"successfully_restored" => "Siz uğurla bərpa etdimiz",
"successfully_suspended_sale" => "Sizin satışınız uğurla dayandırıldı.",
"successfully_updated" => "Satış uğurla yeniləndi.",
"suspend_sale" => "Dayandırmaq",
"suspended_doc_id" => "Sənəd",
"suspended_sale_id" => "Satış dayandırıldı İD",
"suspended_sales" => "satış dayandırıldı",
"table" => "Masa",
"takings" => "Gündəlik Satışlar",
"tax" => "vergi",
"tax_id" => "Vergi İD",
"tax_invoice" => "Vergi Qaimə",
"tax_percent" => "vergi %",
"taxed_ind" => "T",
"total" => "cəm",
"total_tax_exclusive" => "Vergi Xaric",
"transaction_failed" => "Satış əməliyyatı uğursuz oldu.",
"unable_to_add_item" => "Satışa əlavə edilən məhsul uğursuz oldu",
"unsuccessfully_deleted" => "Satış (lar) silmək uğursuz oldu.",
"unsuccessfully_restored" => "Satış (lar) bərpa olunmadı.",
"unsuccessfully_suspended_sale" => "Satış dayandırıla bilmədi.",
"unsuccessfully_updated" => "Satış yeniləməsi uğursuz oldu.",
"unsuspend" => "blok etmək",
"unsuspend_and_delete" => "blok etmək və silmək",
"update" => "Yenilə",
"upi" => "UPI",
"visa" => "",
"wholesale" => "",
"work_order" => "İş Sifarişi",
"work_order_number" => "Sifariş nömrəsi",
"work_order_number_duplicate" => "İş sifarişinin nömrəsi unikal olmalıdır.",
"work_order_sent" => "İş sifarişi göndərildi",
"work_order_unsent" => "İş Sifarişi göndərilməmişdi",
];