mirror of
https://github.com/opensourcepos/opensourcepos.git
synced 2026-10-26 18:18:53 -04:00
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>
This commit is contained in:
47 files changed
+323
-5
No files matched your search
@@ -135,4 +135,19 @@ class OSPOSRules
|
||||
{
|
||||
return parse_decimals($candidate) !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that a locale-aware decimal value is non-negative (>= 0).
|
||||
*
|
||||
* @param string $candidate
|
||||
* @param string|null $error
|
||||
* @return bool
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
public function nonNegativeDecimal(string $candidate, ?string &$error = null): bool
|
||||
{
|
||||
$value = parse_decimals($candidate);
|
||||
|
||||
return $value !== false && $value >= 0;
|
||||
}
|
||||
}
|
||||
@@ -582,12 +582,21 @@ class Sales extends Secure_Controller
|
||||
$data = [];
|
||||
|
||||
$rules = [
|
||||
'price' => 'trim|required|decimal_locale',
|
||||
'price' => 'trim|required|decimal_locale|nonNegativeDecimal',
|
||||
'quantity' => 'trim|required|decimal_locale',
|
||||
'discount' => 'trim|permit_empty|decimal_locale',
|
||||
'discount' => 'trim|permit_empty|decimal_locale|nonNegativeDecimal',
|
||||
];
|
||||
|
||||
if ($this->validate($rules)) {
|
||||
$messages = [
|
||||
'price' => [
|
||||
'nonNegativeDecimal' => lang('Sales.negative_price_invalid'),
|
||||
],
|
||||
'discount' => [
|
||||
'nonNegativeDecimal' => lang('Sales.negative_discount_invalid'),
|
||||
],
|
||||
];
|
||||
|
||||
if ($this->validate($rules, $messages)) {
|
||||
$description = $this->request->getPost('description', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
|
||||
$serialnumber = $this->request->getPost('serialnumber', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
|
||||
$price = parse_decimals($this->request->getPost('price'));
|
||||
@@ -596,20 +605,38 @@ class Sales extends Secure_Controller
|
||||
$discount = $discount_type
|
||||
? parse_quantity($this->request->getPost('discount'))
|
||||
: parse_decimals($this->request->getPost('discount'));
|
||||
$discount = $discount ?: 0;
|
||||
|
||||
// Return mode legitimately uses negative quantities for refunds
|
||||
if ($this->sale_lib->get_mode() != 'return' && $quantity < 0) {
|
||||
$data['error'] = lang('Sales.negative_quantity_invalid');
|
||||
return $this->_reload($data);
|
||||
}
|
||||
|
||||
// Business logic: discount bounds depend on discount_type and item values
|
||||
if ($discount_type == PERCENT && $discount > 100) {
|
||||
$data['error'] = lang('Sales.discount_percent_exceeds_100');
|
||||
return $this->_reload($data);
|
||||
}
|
||||
|
||||
if ($discount_type == FIXED && bccomp((string)$discount, bcmul((string)abs($quantity), (string)$price, 2), 2) > 0) {
|
||||
$data['error'] = lang('Sales.discount_exceeds_item_total');
|
||||
return $this->_reload($data);
|
||||
}
|
||||
|
||||
$item_location = $this->request->getPost('location', FILTER_SANITIZE_NUMBER_INT);
|
||||
$discounted_total = $this->request->getPost('discounted_total') != ''
|
||||
? parse_decimals($this->request->getPost('discounted_total') ?? '')
|
||||
: null;
|
||||
|
||||
|
||||
$this->sale_lib->edit_item($line, $description, $serialnumber, $quantity, $discount, $discount_type, $price, $discounted_total);
|
||||
|
||||
$this->sale_lib->empty_payments();
|
||||
|
||||
$data['warning'] = $this->sale_lib->out_of_stock($this->sale_lib->get_item_id($line), $item_location);
|
||||
} else {
|
||||
$data['error'] = lang('Sales.error_editing_item');
|
||||
$errors = $this->validator->getErrors();
|
||||
$data['error'] = $errors ? reset($errors) : lang('Sales.error_editing_item');
|
||||
}
|
||||
|
||||
return $this->_reload($data);
|
||||
@@ -723,6 +750,12 @@ class Sales extends Secure_Controller
|
||||
$data['cash_amount_due'] = $totals['cash_amount_due'];
|
||||
$data['non_cash_amount_due'] = $totals['amount_due'];
|
||||
|
||||
// Prevent negative total sales (fraud/theft vector) - returns can have negative totals for legitimate refunds
|
||||
if ($this->sale_lib->get_mode() != 'return' && bccomp($totals['total'], '0') < 0) {
|
||||
$data['error'] = lang('Sales.negative_total_invalid');
|
||||
return $this->_reload($data);
|
||||
}
|
||||
|
||||
if ($data['cash_mode']) { // TODO: Convert this to ternary notation
|
||||
$data['amount_due'] = $totals['cash_amount_due'];
|
||||
} else {
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"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" => "بطاقة هدية",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"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" => "بطاقة هدية",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"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ı",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"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" => "Gift Карта",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"employee" => "Zaposlenik",
|
||||
"entry" => "Ulaz",
|
||||
"error_editing_item" => "Greška pri uređivanju artikla",
|
||||
"negative_price_invalid" => "",
|
||||
"negative_quantity_invalid" => "",
|
||||
"negative_discount_invalid" => "",
|
||||
"discount_percent_exceeds_100" => "",
|
||||
"discount_exceeds_item_total" => "",
|
||||
"negative_total_invalid" => "",
|
||||
"find_or_scan_item" => "Pronađi/Skeniraj artikal",
|
||||
"find_or_scan_item_or_receipt" => "Pronađi/Skeniraj artikal ili priznanicu",
|
||||
"giftcard" => "Poklon kartica",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
'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' => "کارتی دیاری",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"employee" => "Prodávající",
|
||||
"entry" => "Záznam",
|
||||
"error_editing_item" => "Chyba při úpravě položky",
|
||||
"negative_price_invalid" => "",
|
||||
"negative_quantity_invalid" => "",
|
||||
"negative_discount_invalid" => "",
|
||||
"discount_percent_exceeds_100" => "",
|
||||
"discount_exceeds_item_total" => "",
|
||||
"negative_total_invalid" => "",
|
||||
"find_or_scan_item" => "Najít nebo skenovat položku",
|
||||
"find_or_scan_item_or_receipt" => "Najít nebo skenovat položku či účtenku",
|
||||
"giftcard" => "Dárkový poukaz",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"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" => "Gavekort",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"employee" => "Mitarbeiter",
|
||||
"entry" => "",
|
||||
"error_editing_item" => "Fehler beim Ändern des Artikels",
|
||||
"negative_price_invalid" => "",
|
||||
"negative_quantity_invalid" => "",
|
||||
"negative_discount_invalid" => "",
|
||||
"discount_percent_exceeds_100" => "",
|
||||
"discount_exceeds_item_total" => "",
|
||||
"negative_total_invalid" => "",
|
||||
"find_or_scan_item" => "Finde/Scanne Artikel",
|
||||
"find_or_scan_item_or_receipt" => "Finde/Scanne Artikel oder Quittung",
|
||||
"giftcard" => "Gutschein",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"employee" => "Mitarbeiter",
|
||||
"entry" => "Eintrag",
|
||||
"error_editing_item" => "Fehler beim Ändern des Artikels",
|
||||
"negative_price_invalid" => "",
|
||||
"negative_quantity_invalid" => "",
|
||||
"negative_discount_invalid" => "",
|
||||
"discount_percent_exceeds_100" => "",
|
||||
"discount_exceeds_item_total" => "",
|
||||
"negative_total_invalid" => "",
|
||||
"find_or_scan_item" => "Finde/Scanne Artikel",
|
||||
"find_or_scan_item_or_receipt" => "Finde/Scanne Artikel oder Quittung",
|
||||
"giftcard" => "Gutschein",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"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" => "Δωροκάρτα",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"employee" => "Employee",
|
||||
"entry" => "Entry",
|
||||
"error_editing_item" => "Error editing item",
|
||||
"negative_price_invalid" => "Price cannot be negative.",
|
||||
"negative_quantity_invalid" => "Quantity cannot be negative.",
|
||||
"negative_discount_invalid" => "Discount cannot be negative.",
|
||||
"discount_percent_exceeds_100" => "Percentage discount cannot exceed 100%.",
|
||||
"discount_exceeds_item_total" => "Discount cannot exceed the item total.",
|
||||
"negative_total_invalid" => "Sale total cannot be negative. Check item discounts and quantities.",
|
||||
"find_or_scan_item" => "Find or Scan Item",
|
||||
"find_or_scan_item_or_receipt" => "Find or Scan Item or Receipt",
|
||||
"giftcard" => "Gift Card",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"employee" => "Employee",
|
||||
"entry" => "Entry",
|
||||
"error_editing_item" => "Error editing item",
|
||||
"negative_price_invalid" => "Price cannot be negative.",
|
||||
"negative_quantity_invalid" => "Quantity cannot be negative.",
|
||||
"negative_discount_invalid" => "Discount cannot be negative.",
|
||||
"discount_percent_exceeds_100" => "Percentage discount cannot exceed 100%.",
|
||||
"discount_exceeds_item_total" => "Discount cannot exceed the item total.",
|
||||
"negative_total_invalid" => "Sale total cannot be negative. Check item discounts and quantities.",
|
||||
"find_or_scan_item" => "Find or Scan Item",
|
||||
"find_or_scan_item_or_receipt" => "Find or Scan Item or Receipt",
|
||||
"giftcard" => "Gift Card",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"employee" => "Empleado",
|
||||
"entry" => "Entrada",
|
||||
"error_editing_item" => "Error editando artículo",
|
||||
"negative_price_invalid" => "",
|
||||
"negative_quantity_invalid" => "",
|
||||
"negative_discount_invalid" => "",
|
||||
"discount_percent_exceeds_100" => "",
|
||||
"discount_exceeds_item_total" => "",
|
||||
"negative_total_invalid" => "",
|
||||
"find_or_scan_item" => "Encontrar/Escanear Artículo",
|
||||
"find_or_scan_item_or_receipt" => "Encontrar/Escanear Artículo o Entrada",
|
||||
"giftcard" => "Tarjeta de Regalo",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"employee" => "Empleado",
|
||||
"entry" => "Entrada",
|
||||
"error_editing_item" => "Error editando el artículo",
|
||||
"negative_price_invalid" => "",
|
||||
"negative_quantity_invalid" => "",
|
||||
"negative_discount_invalid" => "",
|
||||
"discount_percent_exceeds_100" => "",
|
||||
"discount_exceeds_item_total" => "",
|
||||
"negative_total_invalid" => "",
|
||||
"find_or_scan_item" => "Buscar o escanear artículo",
|
||||
"find_or_scan_item_or_receipt" => "Buscar o escanear artículo o recibo",
|
||||
"giftcard" => "Tarjeta de regalo",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"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" => "کارت هدیه",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"employee" => "Employé",
|
||||
"entry" => "Entrée",
|
||||
"error_editing_item" => "Érreur lors de l'édition",
|
||||
"negative_price_invalid" => "",
|
||||
"negative_quantity_invalid" => "",
|
||||
"negative_discount_invalid" => "",
|
||||
"discount_percent_exceeds_100" => "",
|
||||
"discount_exceeds_item_total" => "",
|
||||
"negative_total_invalid" => "",
|
||||
"find_or_scan_item" => "Trouver/Scanner Article",
|
||||
"find_or_scan_item_or_receipt" => "Trouver/Scanner Article OU Reçu",
|
||||
"giftcard" => "Carte Cadeau",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"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" => "כרטיס מתנה",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"employee" => "Radnik",
|
||||
"entry" => "",
|
||||
"error_editing_item" => "Greška kod uređivanja artikla",
|
||||
"negative_price_invalid" => "",
|
||||
"negative_quantity_invalid" => "",
|
||||
"negative_discount_invalid" => "",
|
||||
"discount_percent_exceeds_100" => "",
|
||||
"discount_exceeds_item_total" => "",
|
||||
"negative_total_invalid" => "",
|
||||
"find_or_scan_item" => "Pronađi/Skaniraj artikal",
|
||||
"find_or_scan_item_or_receipt" => "Pronađi/Skaniraj artikal ili račun",
|
||||
"giftcard" => "Poklon bon",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"employee" => "Dolgozó",
|
||||
"entry" => "",
|
||||
"error_editing_item" => "Termék módositási hiba",
|
||||
"negative_price_invalid" => "",
|
||||
"negative_quantity_invalid" => "",
|
||||
"negative_discount_invalid" => "",
|
||||
"discount_percent_exceeds_100" => "",
|
||||
"discount_exceeds_item_total" => "",
|
||||
"negative_total_invalid" => "",
|
||||
"find_or_scan_item" => "Termék keresés/scan",
|
||||
"find_or_scan_item_or_receipt" => "Termék keresése",
|
||||
"giftcard" => "Ajándék utalvány",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"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" => "",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"employee" => "Karyawan",
|
||||
"entry" => "Entri",
|
||||
"error_editing_item" => "mengubah item salah",
|
||||
"negative_price_invalid" => "",
|
||||
"negative_quantity_invalid" => "",
|
||||
"negative_discount_invalid" => "",
|
||||
"discount_percent_exceeds_100" => "",
|
||||
"discount_exceeds_item_total" => "",
|
||||
"negative_total_invalid" => "",
|
||||
"find_or_scan_item" => "Cari/Scan Item",
|
||||
"find_or_scan_item_or_receipt" => "Temukan atau pindai Item atau Faktur",
|
||||
"giftcard" => "Kartu Hadiah",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"employee" => "Impiegato",
|
||||
"entry" => "Voce",
|
||||
"error_editing_item" => "Errore modificando un articolo",
|
||||
"negative_price_invalid" => "",
|
||||
"negative_quantity_invalid" => "",
|
||||
"negative_discount_invalid" => "",
|
||||
"discount_percent_exceeds_100" => "",
|
||||
"discount_exceeds_item_total" => "",
|
||||
"negative_total_invalid" => "",
|
||||
"find_or_scan_item" => "Scansiona o Cerca Articolo",
|
||||
"find_or_scan_item_or_receipt" => "Scansiona o Cerca Articolo o Scontrino",
|
||||
"giftcard" => "Carta Regalo",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"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" => "កាតអំណោយ",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"employee" => "Employee",
|
||||
"entry" => "Entry",
|
||||
"error_editing_item" => "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",
|
||||
"find_or_scan_item_or_receipt" => "Find or Scan Item or Receipt",
|
||||
"giftcard" => "Gift Card",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"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" => "",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"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" => "",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"employee" => "Werknemer",
|
||||
"entry" => "Rij",
|
||||
"error_editing_item" => "Fout bij bewerken",
|
||||
"negative_price_invalid" => "",
|
||||
"negative_quantity_invalid" => "",
|
||||
"negative_discount_invalid" => "",
|
||||
"discount_percent_exceeds_100" => "",
|
||||
"discount_exceeds_item_total" => "",
|
||||
"negative_total_invalid" => "",
|
||||
"find_or_scan_item" => "Zoek/Scan Product",
|
||||
"find_or_scan_item_or_receipt" => "Zoek/Scan Product of Ticket",
|
||||
"giftcard" => "Cadeaubon",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"employee" => "Werknemer",
|
||||
"entry" => "Vermelding",
|
||||
"error_editing_item" => "Fout bij artikel bewerken",
|
||||
"negative_price_invalid" => "",
|
||||
"negative_quantity_invalid" => "",
|
||||
"negative_discount_invalid" => "",
|
||||
"discount_percent_exceeds_100" => "",
|
||||
"discount_exceeds_item_total" => "",
|
||||
"negative_total_invalid" => "",
|
||||
"find_or_scan_item" => "Artikel zoeken of scannen",
|
||||
"find_or_scan_item_or_receipt" => "Artikel of kassabon vinden of scannen",
|
||||
"giftcard" => "Cadeaubon",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
'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' => "Karta Podarunkowa",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"employee" => "Empregado",
|
||||
"entry" => "Entrada",
|
||||
"error_editing_item" => "Erro editando 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" => "Pesquisar Item",
|
||||
"find_or_scan_item_or_receipt" => "Produto",
|
||||
"giftcard" => "Cupom",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"employee" => "Salariat",
|
||||
"entry" => "Intrare",
|
||||
"error_editing_item" => "Eroare editare articol",
|
||||
"negative_price_invalid" => "",
|
||||
"negative_quantity_invalid" => "",
|
||||
"negative_discount_invalid" => "",
|
||||
"discount_percent_exceeds_100" => "",
|
||||
"discount_exceeds_item_total" => "",
|
||||
"negative_total_invalid" => "",
|
||||
"find_or_scan_item" => "Gaseste sau scaneaza Articol",
|
||||
"find_or_scan_item_or_receipt" => "Gaseste sau scaneaza Articol sau Chitanta",
|
||||
"giftcard" => "Card Cadou",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"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" => "Подарочная карта",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"employee" => "Anställd",
|
||||
"entry" => "Post",
|
||||
"error_editing_item" => "Ändra artikel misslyckades",
|
||||
"negative_price_invalid" => "",
|
||||
"negative_quantity_invalid" => "",
|
||||
"negative_discount_invalid" => "",
|
||||
"discount_percent_exceeds_100" => "",
|
||||
"discount_exceeds_item_total" => "",
|
||||
"negative_total_invalid" => "",
|
||||
"find_or_scan_item" => "Hitta eller skanna artikel",
|
||||
"find_or_scan_item_or_receipt" => "Hitta eller skanna artikel eller kvitto",
|
||||
"giftcard" => "Presentkort",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"employee" => "Mfanyakazi",
|
||||
"entry" => "Ingizo",
|
||||
"error_editing_item" => "Hitilafu katika kuhariri bidhaa",
|
||||
"negative_price_invalid" => "",
|
||||
"negative_quantity_invalid" => "",
|
||||
"negative_discount_invalid" => "",
|
||||
"discount_percent_exceeds_100" => "",
|
||||
"discount_exceeds_item_total" => "",
|
||||
"negative_total_invalid" => "",
|
||||
"find_or_scan_item" => "Tafuta au Changanua Bidhaa",
|
||||
"find_or_scan_item_or_receipt" => "Tafuta au Changanua Bidhaa au Risiti",
|
||||
"giftcard" => "Kadi ya Zawadi",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"employee" => "Mfanyakazi",
|
||||
"entry" => "Ingizo",
|
||||
"error_editing_item" => "Hitilafu katika kuhariri bidhaa",
|
||||
"negative_price_invalid" => "",
|
||||
"negative_quantity_invalid" => "",
|
||||
"negative_discount_invalid" => "",
|
||||
"discount_percent_exceeds_100" => "",
|
||||
"discount_exceeds_item_total" => "",
|
||||
"negative_total_invalid" => "",
|
||||
"find_or_scan_item" => "Tafuta au Changanua Bidhaa",
|
||||
"find_or_scan_item_or_receipt" => "Tafuta au Changanua Bidhaa au Risiti",
|
||||
"giftcard" => "Kadi ya Zawadi",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"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" => "பரிசு அட்டை",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"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" => "บัตรของขวัญ",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"employee" => "Employee",
|
||||
"entry" => "Entry",
|
||||
"error_editing_item" => "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",
|
||||
"find_or_scan_item_or_receipt" => "Find or Scan Item or Receipt",
|
||||
"giftcard" => "Gift Card",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"employee" => "Personel",
|
||||
"entry" => "Girdi",
|
||||
"error_editing_item" => "Ürün düzenleme hatası",
|
||||
"negative_price_invalid" => "",
|
||||
"negative_quantity_invalid" => "",
|
||||
"negative_discount_invalid" => "",
|
||||
"discount_percent_exceeds_100" => "",
|
||||
"discount_exceeds_item_total" => "",
|
||||
"negative_total_invalid" => "",
|
||||
"find_or_scan_item" => "Ürün Bul/Oku",
|
||||
"find_or_scan_item_or_receipt" => "Ürün yada Fiş Bul/Oku",
|
||||
"giftcard" => "Hediye Çeki",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"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" => "Подарункова карта",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"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" => "",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"employee" => "Nhân viên",
|
||||
"entry" => "Mục nhập",
|
||||
"error_editing_item" => "Lỗi sửa hàng hóa",
|
||||
"negative_price_invalid" => "",
|
||||
"negative_quantity_invalid" => "",
|
||||
"negative_discount_invalid" => "",
|
||||
"discount_percent_exceeds_100" => "",
|
||||
"discount_exceeds_item_total" => "",
|
||||
"negative_total_invalid" => "",
|
||||
"find_or_scan_item" => "Tìm hay quét Hàng hóa",
|
||||
"find_or_scan_item_or_receipt" => "Tìm hay quét Hàng hóa hay Biên lai",
|
||||
"giftcard" => "Thẻ quà tặng",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"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" => "禮金券",
|
||||
|
||||
@@ -73,6 +73,12 @@ return [
|
||||
"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" => "禮金券",
|
||||
|
||||
Reference in new issue
Block a user