mirror of
https://github.com/opensourcepos/opensourcepos.git
synced 2026-09-13 22:08:16 -04:00
Merge branch 'master' into feature-optimize-items-view-queries
This commit is contained in:
55 files changed
+586
-154
No files matched your search
@@ -225,4 +225,24 @@ class OSPOSRules
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that the candidate is a plain filesystem path: only letters, digits,
|
||||
* underscore, dash, dot and forward slash. Uses \A...\z (not ^...$) because PCRE's $
|
||||
* also matches immediately before a single trailing newline, which would let a
|
||||
* value like "/usr/bin/php\n" slip through — the bug behind GHSA-jc56-j8m6-q627.
|
||||
*
|
||||
* @param string $candidate
|
||||
* @param string|null $error
|
||||
* @return bool
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
public function valid_path_strict(string $candidate, ?string &$error = null): bool
|
||||
{
|
||||
if ($candidate === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (bool) preg_match('/\A[a-zA-Z0-9_\-\/.]+\z/', $candidate);
|
||||
}
|
||||
}
|
||||
@@ -540,16 +540,21 @@ class Config extends Secure_Controller
|
||||
$protocol = $this->request->getPost('protocol');
|
||||
$mailpath = $this->request->getPost('mailpath');
|
||||
|
||||
// Validate mailpath: required for sendmail, optional for others but must be safe if provided
|
||||
$isMailpathRequired = ($protocol === 'sendmail');
|
||||
$isMailpathProvided = !empty($mailpath);
|
||||
$isMailpathValid = $isMailpathProvided && preg_match('/^[a-zA-Z0-9_\-\/.]+$/', $mailpath);
|
||||
$rules = [
|
||||
'mailpath' => [
|
||||
'label' => lang('Config.email_mailpath'),
|
||||
'rules' => ($protocol === 'sendmail' ? 'required' : 'permit_empty') . '|valid_path_strict'
|
||||
]
|
||||
];
|
||||
$messages = [
|
||||
'mailpath' => [
|
||||
'required' => lang('Config.mailpath_invalid'),
|
||||
'valid_path_strict' => lang('Config.mailpath_invalid')
|
||||
]
|
||||
];
|
||||
|
||||
if (($isMailpathRequired && !$isMailpathProvided) || ($isMailpathProvided && !$isMailpathValid)) {
|
||||
return $this->response->setJSON([
|
||||
'success' => false,
|
||||
'message' => lang('Config.mailpath_invalid')
|
||||
]);
|
||||
if ($error = $this->validateFields($rules, $messages)) {
|
||||
return $error;
|
||||
}
|
||||
|
||||
$batch_save_data = [
|
||||
|
||||
+88
-59
@@ -408,6 +408,22 @@ class Sales extends Secure_Controller
|
||||
$giftcard = model(Giftcard::class);
|
||||
$paymentType = $this->request->getPost('payment_type', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
|
||||
|
||||
if (!is_string($paymentType) || $paymentType === '') {
|
||||
$data['error'] = lang('Sales.must_enter_numeric');
|
||||
|
||||
return $this->reload($data);
|
||||
}
|
||||
|
||||
if (
|
||||
$paymentType !== lang('Sales.giftcard')
|
||||
&& $paymentType !== lang('Sales.rewards')
|
||||
&& (str_contains($paymentType, lang('Sales.giftcard')) || str_contains($paymentType, lang('Sales.rewards')))
|
||||
) {
|
||||
$data['error'] = lang('Sales.must_enter_numeric');
|
||||
|
||||
return $this->reload($data);
|
||||
}
|
||||
|
||||
if ($paymentType === lang('Sales.giftcard')) {
|
||||
$rules = ['amount_tendered' => 'trim|required|integer']; //For giftcards, amount_tendered becomes the giftcard number which must be an integer
|
||||
$messages = ['amount_tendered' => lang('Sales.must_enter_numeric_giftcard')];
|
||||
@@ -415,12 +431,14 @@ class Sales extends Secure_Controller
|
||||
$min = (int)($this->config['payment_reference_code_min'] ?? 3);
|
||||
$max = (int)($this->config['payment_reference_code_max'] ?? 20);
|
||||
$rules = [
|
||||
'amount_tendered' => 'trim|required|decimal_locale',
|
||||
'amount_tendered' => 'trim|required|decimal_locale|nonNegativeDecimal',
|
||||
'reference_code' => "trim|required|alpha_numeric|min_length[$min]|max_length[$max]",
|
||||
];
|
||||
$messages = [
|
||||
'amount_tendered' => [
|
||||
'required' => lang('Sales.must_enter_numeric'),
|
||||
'required' => lang('Sales.must_enter_numeric'),
|
||||
'decimal_locale' => lang('Sales.must_enter_numeric'),
|
||||
'nonNegativeDecimal' => lang('Sales.negative_amount_invalid'),
|
||||
],
|
||||
'reference_code' => [
|
||||
'required' => lang('Sales.must_enter_reference_code'),
|
||||
@@ -430,8 +448,14 @@ class Sales extends Secure_Controller
|
||||
],
|
||||
];
|
||||
} else {
|
||||
$rules = ['amount_tendered' => 'trim|required|decimal_locale'];
|
||||
$messages = ['amount_tendered' => lang('Sales.must_enter_numeric')];
|
||||
$rules = ['amount_tendered' => 'trim|required|decimal_locale|nonNegativeDecimal'];
|
||||
$messages = [
|
||||
'amount_tendered' => [
|
||||
'required' => lang('Sales.must_enter_numeric'),
|
||||
'decimal_locale' => lang('Sales.must_enter_numeric'),
|
||||
'nonNegativeDecimal' => lang('Sales.negative_amount_invalid'),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
if (!$this->validate($rules, $messages)) {
|
||||
@@ -730,21 +754,21 @@ class Sales extends Secure_Controller
|
||||
*/
|
||||
public function postComplete(): string // TODO: this function is huge. Probably should be refactored.
|
||||
{
|
||||
$sale_id = $this->sale_lib->get_sale_id();
|
||||
$saleId = $this->sale_lib->get_sale_id();
|
||||
$data = [];
|
||||
$data['dinner_table'] = $this->sale_lib->get_dinner_table();
|
||||
|
||||
$data['cart'] = $this->sale_lib->get_cart();
|
||||
|
||||
$data['include_hsn'] = (bool)$this->config['include_hsn'];
|
||||
$__time = time();
|
||||
$data['transaction_time'] = to_datetime($__time);
|
||||
$data['transaction_date'] = to_date($__time);
|
||||
$time = time();
|
||||
$data['transaction_time'] = to_datetime($time);
|
||||
$data['transaction_date'] = to_date($time);
|
||||
$data['show_stock_locations'] = $this->stock_location->show_locations('sales');
|
||||
$data['comments'] = $this->sale_lib->get_comment();
|
||||
$employee_id = $this->employee->get_logged_in_employee_info()->person_id;
|
||||
$employee_info = $this->employee->get_info($employee_id);
|
||||
$data['employee'] = $employee_info->first_name . ' ' . mb_substr($employee_info->last_name, 0, 1);
|
||||
$employeeId = $this->employee->get_logged_in_employee_info()->person_id;
|
||||
$employeeInfo = $this->employee->get_info($employeeId);
|
||||
$data['employee'] = $employeeInfo->first_name . ' ' . mb_substr($employeeInfo->last_name, 0, 1);
|
||||
|
||||
$data['company_info'] = implode("\n", [$this->config['address'], $this->config['phone']]);
|
||||
|
||||
@@ -762,26 +786,26 @@ class Sales extends Secure_Controller
|
||||
$data['print_after_sale'] = $this->session->get('sales_print_after_sale');
|
||||
$data['price_work_orders'] = $this->sale_lib->is_price_work_orders();
|
||||
$data['email_receipt'] = $this->sale_lib->is_email_receipt();
|
||||
$customer_id = $this->sale_lib->get_customer();
|
||||
$invoice_number = $this->sale_lib->get_invoice_number();
|
||||
$data["invoice_number"] = $invoice_number;
|
||||
$work_order_number = $this->sale_lib->get_work_order_number();
|
||||
$data["work_order_number"] = $work_order_number;
|
||||
$quote_number = $this->sale_lib->get_quote_number();
|
||||
$data["quote_number"] = $quote_number;
|
||||
$customer_info = $this->_load_customer_data($customer_id, $data);
|
||||
$customerId = $this->sale_lib->get_customer();
|
||||
$invoiceNumber = $this->sale_lib->get_invoice_number();
|
||||
$data["invoice_number"] = $invoiceNumber;
|
||||
$workOrderNumber = $this->sale_lib->get_work_order_number();
|
||||
$data["work_order_number"] = $workOrderNumber;
|
||||
$quoteNumber = $this->sale_lib->get_quote_number();
|
||||
$data["quote_number"] = $quoteNumber;
|
||||
$customerInfo = $this->_load_customer_data($customerId, $data);
|
||||
|
||||
if ($customer_info != null) {
|
||||
$data["customer_comments"] = $customer_info->comments;
|
||||
$data['tax_id'] = $customer_info->tax_id;
|
||||
if ($customerInfo != null) {
|
||||
$data["customer_comments"] = $customerInfo->comments;
|
||||
$data['tax_id'] = $customerInfo->tax_id;
|
||||
}
|
||||
$tax_details = $this->tax_lib->get_taxes($data['cart']); // TODO: Duplicated code
|
||||
$data['taxes'] = $tax_details[0];
|
||||
$taxDetails = $this->tax_lib->get_taxes($data['cart']); // TODO: Duplicated code
|
||||
$data['taxes'] = $taxDetails[0];
|
||||
$data['discount'] = $this->sale_lib->get_discount();
|
||||
$data['payments'] = $this->sale_lib->getPayments();
|
||||
|
||||
// Returns 'subtotal', 'total', 'cash_total', 'payment_total', 'amount_due', 'cash_amount_due', 'payments_cover_total'
|
||||
$totals = $this->sale_lib->get_totals($tax_details[0]);
|
||||
$totals = $this->sale_lib->get_totals($taxDetails[0]);
|
||||
$data['subtotal'] = $totals['subtotal'];
|
||||
$data['total'] = $totals['total'];
|
||||
$data['payments_total'] = $totals['payment_total'];
|
||||
@@ -800,6 +824,11 @@ class Sales extends Secure_Controller
|
||||
return $this->reload($data);
|
||||
}
|
||||
|
||||
if (!$totals['payments_cover_total'] && !$this->sale_lib->is_invoice_mode() && !$this->sale_lib->is_quote_mode()) {
|
||||
$data['error'] = lang('Sales.amount_due_not_covered');
|
||||
return $this->reload($data);
|
||||
}
|
||||
|
||||
if ($data['cash_mode']) { // TODO: Convert this to ternary notation
|
||||
$data['amount_due'] = $totals['cash_amount_due'];
|
||||
} else {
|
||||
@@ -829,31 +858,31 @@ class Sales extends Secure_Controller
|
||||
$data['print_price_info'] = true;
|
||||
|
||||
if ($this->sale_lib->is_invoice_mode()) {
|
||||
$invoice_format = $this->config['sales_invoice_format'];
|
||||
$invoiceFormat = $this->config['sales_invoice_format'];
|
||||
|
||||
// Generate final invoice number (if using the invoice in sales by receipt mode then the invoice number can be manually entered or altered in some way
|
||||
if (!empty($invoice_format) && $invoice_number == null) {
|
||||
if (!empty($invoiceFormat) && $invoiceNumber == null) {
|
||||
// The user can retain the default encoded format or can manually override it. It still passes through the rendering step.
|
||||
$invoice_number = $this->token_lib->render($invoice_format);
|
||||
$invoiceNumber = $this->token_lib->render($invoiceFormat);
|
||||
}
|
||||
|
||||
|
||||
if ($sale_id == NEW_ENTRY && $this->sale->check_invoice_number_exists($invoice_number)) {
|
||||
$data['error'] = lang('Sales.invoice_number_duplicate', [$invoice_number]);
|
||||
if ($saleId == NEW_ENTRY && $this->sale->check_invoice_number_exists($invoiceNumber)) {
|
||||
$data['error'] = lang('Sales.invoice_number_duplicate', [$invoiceNumber]);
|
||||
return $this->reload($data);
|
||||
} else {
|
||||
$data['invoice_number'] = $invoice_number;
|
||||
$data['invoice_number'] = $invoiceNumber;
|
||||
$data['sale_status'] = COMPLETED;
|
||||
$sale_type = SALE_TYPE_INVOICE;
|
||||
$saleType = SALE_TYPE_INVOICE;
|
||||
|
||||
$invoice_type = $this->config['invoice_type'];
|
||||
if (!Sale_lib::isValidInvoiceType($invoice_type)) {
|
||||
$invoice_type = 'invoice';
|
||||
$invoiceType = $this->config['invoice_type'];
|
||||
if (!Sale_lib::isValidInvoiceType($invoiceType)) {
|
||||
$invoiceType = 'invoice';
|
||||
}
|
||||
$invoice_view = $invoice_type;
|
||||
$invoiceView = $invoiceType;
|
||||
|
||||
// Save the data to the sales table
|
||||
$data['sale_id_num'] = $this->sale->save_value($sale_id, $data['sale_status'], $data['cart'], $customer_id, $employee_id, $data['comments'], $invoice_number, $work_order_number, $quote_number, $sale_type, $data['payments'], $data['dinner_table'], $tax_details);
|
||||
$data['sale_id_num'] = $this->sale->save_value($saleId, $data['sale_status'], $data['cart'], $customerId, $employeeId, $data['comments'], $invoiceNumber, $workOrderNumber, $quoteNumber, $saleType, $data['payments'], $data['dinner_table'], $taxDetails);
|
||||
$data['sale_id'] = 'POS ' . $data['sale_id_num'];
|
||||
|
||||
// Resort and filter cart lines for printing
|
||||
@@ -871,7 +900,7 @@ class Sales extends Secure_Controller
|
||||
} else {
|
||||
$data['barcode'] = $this->barcode_lib->generate_receipt_barcode($data['sale_id']);
|
||||
$this->sale_lib->clear_all();
|
||||
return view('sales/' . $invoice_view, $data);
|
||||
return view('sales/' . $invoiceView, $data);
|
||||
}
|
||||
}
|
||||
} elseif ($this->sale_lib->is_work_order_mode()) {
|
||||
@@ -883,21 +912,21 @@ class Sales extends Secure_Controller
|
||||
$data['sales_work_order'] = lang('Sales.work_order');
|
||||
$data['work_order_number_label'] = lang('Sales.work_order_number');
|
||||
|
||||
if ($work_order_number == null) {
|
||||
if ($workOrderNumber == null) {
|
||||
// Generate work order number
|
||||
$work_order_format = $this->config['work_order_format'];
|
||||
$work_order_number = $this->token_lib->render($work_order_format);
|
||||
$workOrderFormat = $this->config['work_order_format'];
|
||||
$workOrderNumber = $this->token_lib->render($workOrderFormat);
|
||||
}
|
||||
|
||||
if ($sale_id == NEW_ENTRY && $this->sale->check_work_order_number_exists($work_order_number)) {
|
||||
if ($saleId == NEW_ENTRY && $this->sale->check_work_order_number_exists($workOrderNumber)) {
|
||||
$data['error'] = lang('Sales.work_order_number_duplicate');
|
||||
return $this->reload($data);
|
||||
} else {
|
||||
$data['work_order_number'] = $work_order_number;
|
||||
$data['work_order_number'] = $workOrderNumber;
|
||||
$data['sale_status'] = SUSPENDED;
|
||||
$sale_type = SALE_TYPE_WORK_ORDER;
|
||||
$saleType = SALE_TYPE_WORK_ORDER;
|
||||
|
||||
$data['sale_id_num'] = $this->sale->save_value($sale_id, $data['sale_status'], $data['cart'], $customer_id, $employee_id, $data['comments'], $invoice_number, $work_order_number, $quote_number, $sale_type, $data['payments'], $data['dinner_table'], $tax_details);
|
||||
$data['sale_id_num'] = $this->sale->save_value($saleId, $data['sale_status'], $data['cart'], $customerId, $employeeId, $data['comments'], $invoiceNumber, $workOrderNumber, $quoteNumber, $saleType, $data['payments'], $data['dinner_table'], $taxDetails);
|
||||
|
||||
if ($data['sale_id_num'] === INSUFFICIENT_GIFTCARD_BALANCE) {
|
||||
$data['error_message'] = lang('Sales.insufficient_giftcard_balance');
|
||||
@@ -923,21 +952,21 @@ class Sales extends Secure_Controller
|
||||
$data['sales_quote'] = lang('Sales.quote');
|
||||
$data['quote_number_label'] = lang('Sales.quote_number');
|
||||
|
||||
if ($quote_number == null) {
|
||||
if ($quoteNumber == null) {
|
||||
// Generate quote number
|
||||
$quote_format = $this->config['sales_quote_format'];
|
||||
$quote_number = $this->token_lib->render($quote_format);
|
||||
$quoteFormat = $this->config['sales_quote_format'];
|
||||
$quoteNumber = $this->token_lib->render($quoteFormat);
|
||||
}
|
||||
|
||||
if ($sale_id == NEW_ENTRY && $this->sale->check_quote_number_exists($quote_number)) {
|
||||
if ($saleId == NEW_ENTRY && $this->sale->check_quote_number_exists($quoteNumber)) {
|
||||
$data['error'] = lang('Sales.quote_number_duplicate');
|
||||
return $this->reload($data);
|
||||
} else {
|
||||
$data['quote_number'] = $quote_number;
|
||||
$data['quote_number'] = $quoteNumber;
|
||||
$data['sale_status'] = SUSPENDED;
|
||||
$sale_type = SALE_TYPE_QUOTE;
|
||||
$saleType = SALE_TYPE_QUOTE;
|
||||
|
||||
$data['sale_id_num'] = $this->sale->save_value($sale_id, $data['sale_status'], $data['cart'], $customer_id, $employee_id, $data['comments'], $invoice_number, $work_order_number, $quote_number, $sale_type, $data['payments'], $data['dinner_table'], $tax_details);
|
||||
$data['sale_id_num'] = $this->sale->save_value($saleId, $data['sale_status'], $data['cart'], $customerId, $employeeId, $data['comments'], $invoiceNumber, $workOrderNumber, $quoteNumber, $saleType, $data['payments'], $data['dinner_table'], $taxDetails);
|
||||
|
||||
if ($data['sale_id_num'] === INSUFFICIENT_GIFTCARD_BALANCE) {
|
||||
$data['error_message'] = lang('Sales.insufficient_giftcard_balance');
|
||||
@@ -962,12 +991,12 @@ class Sales extends Secure_Controller
|
||||
// Save the data to the sales table
|
||||
$data['sale_status'] = COMPLETED;
|
||||
if ($this->sale_lib->is_return_mode()) {
|
||||
$sale_type = SALE_TYPE_RETURN;
|
||||
$saleType = SALE_TYPE_RETURN;
|
||||
} else {
|
||||
$sale_type = SALE_TYPE_POS;
|
||||
$saleType = SALE_TYPE_POS;
|
||||
}
|
||||
|
||||
$data['sale_id_num'] = $this->sale->save_value($sale_id, $data['sale_status'], $data['cart'], $customer_id, $employee_id, $data['comments'], $invoice_number, $work_order_number, $quote_number, $sale_type, $data['payments'], $data['dinner_table'], $tax_details);
|
||||
$data['sale_id_num'] = $this->sale->save_value($saleId, $data['sale_status'], $data['cart'], $customerId, $employeeId, $data['comments'], $invoiceNumber, $workOrderNumber, $quoteNumber, $saleType, $data['payments'], $data['dinner_table'], $taxDetails);
|
||||
|
||||
$data['sale_id'] = 'POS ' . $data['sale_id_num'];
|
||||
|
||||
@@ -986,11 +1015,11 @@ class Sales extends Secure_Controller
|
||||
$data['barcode'] = $this->barcode_lib->generate_receipt_barcode($data['sale_id']);
|
||||
|
||||
// Validate receipt template to prevent path traversal
|
||||
$receipt_template = $this->config['receipt_template'] ?? '';
|
||||
if (!Sale_lib::isValidReceiptTemplate($receipt_template)) {
|
||||
$receipt_template = 'receipt_default';
|
||||
$receiptTemplate = $this->config['receipt_template'] ?? '';
|
||||
if (!Sale_lib::isValidReceiptTemplate($receiptTemplate)) {
|
||||
$receiptTemplate = 'receipt_default';
|
||||
}
|
||||
$data['receipt_template_view'] = $receipt_template;
|
||||
$data['receipt_template_view'] = $receiptTemplate;
|
||||
|
||||
$this->sale_lib->clear_all();
|
||||
return view('sales/receipt', $data);
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => 'حساب',
|
||||
'add_payment' => 'إضافة دفع',
|
||||
'amount_due' => 'المبلغ المطلوب',
|
||||
'amount_due_not_covered' => 'المدفوعات لا تغطي المبلغ المستحق.',
|
||||
'amount_tendered' => 'المبلغ المدفوع',
|
||||
'authorized_signature' => 'توقيع معتمد',
|
||||
'cancel_sale' => 'الغاء عملية البيع',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => 'يجب إدخال رقم للمبلغ الفعلى المدفوع.',
|
||||
'must_enter_numeric_giftcard' => 'رقم بطاقة الهدية يجب أن يكون رقم.',
|
||||
'must_enter_reference_code' => 'يجب إدخال رقم المرجع/الاسترداد.',
|
||||
'negative_amount_invalid' => 'لا يمكن أن يكون المبلغ المدفوع سالبًا.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => 'حساب',
|
||||
'add_payment' => 'إضافة دفع',
|
||||
'amount_due' => 'المبلغ المطلوب',
|
||||
'amount_due_not_covered' => 'المدفوعات لا تغطي المبلغ المستحق.',
|
||||
'amount_tendered' => 'المبلغ المدفوع',
|
||||
'authorized_signature' => 'توقيع معتمد',
|
||||
'cancel_sale' => 'الغاء عملية البيع',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => 'يجب إدخال رقم للمبلغ الفعلى المدفوع.',
|
||||
'must_enter_numeric_giftcard' => 'رمز بطاقة الهدية يجب أن يكتون ارقام فقط.',
|
||||
'must_enter_reference_code' => 'يجب إدخال رقم المرجع/الاسترداد.',
|
||||
'negative_amount_invalid' => 'لا يمكن أن يكون المبلغ المدفوع سالبًا.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => 'Hesab #',
|
||||
'add_payment' => 'Ödəniş Əlavə Etmək',
|
||||
'amount_due' => 'Qalıq',
|
||||
'amount_due_not_covered' => 'Ödənişlər ödəniləcək məbləği əhatə etmir.',
|
||||
'amount_tendered' => 'Ödənilən məbləğ',
|
||||
'authorized_signature' => 'Səlahiyyətli İmza',
|
||||
'cancel_sale' => 'İmtina',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'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.',
|
||||
'must_enter_reference_code' => 'İstinad/Axtarış nömrəsi daxil edilməlidir.',
|
||||
'negative_amount_invalid' => 'Ödənilən məbləğ mənfi ola bilməz.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => 'Номер на акаунт',
|
||||
'add_payment' => 'Добавяне на плащане',
|
||||
'amount_due' => 'Дължима сума',
|
||||
'amount_due_not_covered' => 'Плащанията не покриват дължимата сума.',
|
||||
'amount_tendered' => 'Предоставена сума',
|
||||
'authorized_signature' => 'Оторизиран подпис',
|
||||
'cancel_sale' => 'Отказ',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => 'Сумата Предложена трябва да е число.',
|
||||
'must_enter_numeric_giftcard' => 'Gift Card номера трябва да бъде число.',
|
||||
'must_enter_reference_code' => 'Трябва да се въведе референтен/извличащ номер.',
|
||||
'negative_amount_invalid' => 'Предоставената сума не може да бъде отрицателна.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => 'Broj računa',
|
||||
'add_payment' => 'Plaćanje',
|
||||
'amount_due' => 'Iznos duga',
|
||||
'amount_due_not_covered' => 'Uplate ne pokrivaju dospjeli iznos.',
|
||||
'amount_tendered' => 'Ponuđeni iznos',
|
||||
'authorized_signature' => 'Ovlašćeni potpis',
|
||||
'cancel_sale' => 'Otkaži',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => 'Ponuđeni iznos mora biti broj.',
|
||||
'must_enter_numeric_giftcard' => 'Broj poklon kartice mora biti broj.',
|
||||
'must_enter_reference_code' => 'Referentni/broj za preuzimanje mora biti unesen.',
|
||||
'negative_amount_invalid' => 'Ponuđeni iznos ne može biti negativan.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => 'هەژمار #',
|
||||
'add_payment' => 'زیادکردنی پارەدان',
|
||||
'amount_due' => 'بڕی پارە کە دەبێ بدرێت',
|
||||
'amount_due_not_covered' => 'پارەدانەکان بڕی پێویست دانپۆشین نەکردووە.',
|
||||
'amount_tendered' => 'بڕی پێشکەشکراو',
|
||||
'authorized_signature' => 'واژۆی ڕێگەپێدراو',
|
||||
'cancel_sale' => 'هەڵوەشاندنەوە',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => 'بڕی پێشکەشکراو دەبێت ژمارەیەک بێت.',
|
||||
'must_enter_numeric_giftcard' => 'ژمارەی کارتی دیاری دەبێت ژمارەیەک بێت.',
|
||||
'must_enter_reference_code' => 'ژمارەی مەرجع/وەرگرتن دەبێت بنووسرێت.',
|
||||
'negative_amount_invalid' => 'بڕی پێشکەشکراو ناتوانێت نەرێنی بێت.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => '',
|
||||
'add_payment' => 'Přidat platbu',
|
||||
'amount_due' => 'K úhradě',
|
||||
'amount_due_not_covered' => 'Platby nepokrývají splatnou částku.',
|
||||
'amount_tendered' => 'Uhrazeno',
|
||||
'authorized_signature' => '',
|
||||
'cancel_sale' => 'Zrušit',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => '',
|
||||
'must_enter_numeric_giftcard' => 'Číslo dárkového poukazu musí být číslo.',
|
||||
'must_enter_reference_code' => 'Je nutné zadat referenční/vyhledávací číslo.',
|
||||
'negative_amount_invalid' => 'Uhrazená částka nemůže být záporná.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => '',
|
||||
'add_payment' => '',
|
||||
'amount_due' => '',
|
||||
'amount_due_not_covered' => 'Betalingerne dækker ikke det skyldige beløb.',
|
||||
'amount_tendered' => '',
|
||||
'authorized_signature' => '',
|
||||
'cancel_sale' => '',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => '',
|
||||
'must_enter_numeric_giftcard' => '',
|
||||
'must_enter_reference_code' => 'Reference-/hentningsnummer skal angives.',
|
||||
'negative_amount_invalid' => 'Det modtagne beløb kan ikke være negativt.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => '',
|
||||
'add_payment' => 'Zahlung',
|
||||
'amount_due' => 'fälliger Betrag',
|
||||
'amount_due_not_covered' => 'Die Zahlungen decken den fälligen Betrag nicht.',
|
||||
'amount_tendered' => 'Erhalten',
|
||||
'authorized_signature' => '',
|
||||
'cancel_sale' => 'Annullieren',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => 'Eingabe muss eine Zahl sein',
|
||||
'must_enter_numeric_giftcard' => 'Gutschein-Nr. muss eine Zahl sein',
|
||||
'must_enter_reference_code' => 'Referenz-/Abrufnummer muss eingegeben werden.',
|
||||
'negative_amount_invalid' => 'Der erhaltene Betrag darf nicht negativ sein.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => 'Kundennummer',
|
||||
'add_payment' => 'Zahlung',
|
||||
'amount_due' => 'fälliger Betrag',
|
||||
'amount_due_not_covered' => 'Die Zahlungen decken den fälligen Betrag nicht.',
|
||||
'amount_tendered' => 'Erhalten',
|
||||
'authorized_signature' => 'Unterschrift',
|
||||
'cancel_sale' => 'Annullieren',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => 'Eingabe muss eine Zahl sein.',
|
||||
'must_enter_numeric_giftcard' => 'Gutschein-Nr. muss eine Zahl sein.',
|
||||
'must_enter_reference_code' => 'Referenz-/Abrufnummer muss eingegeben werden.',
|
||||
'negative_amount_invalid' => 'Der erhaltene Betrag darf nicht negativ sein.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => 'Λογαριασμός #',
|
||||
'add_payment' => 'Προσθήκη Πληρωμής',
|
||||
'amount_due' => 'Ποσό επιστροφής',
|
||||
'amount_due_not_covered' => 'Οι πληρωμές δεν καλύπτουν το οφειλόμενο ποσό.',
|
||||
'amount_tendered' => 'Ποσό Είσπραξης',
|
||||
'authorized_signature' => 'Εγκεκριμένη Υπογραφή',
|
||||
'cancel_sale' => 'Ακύρωση',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => 'Το Ποσό Είσπραξης πρέπει να είναι Αριθμός.',
|
||||
'must_enter_numeric_giftcard' => 'Ο Αριθμός της Δωροκάρτας πρέπει να είναι αριθμός.',
|
||||
'must_enter_reference_code' => 'Πρέπει να εισαχθεί αριθμός αναφοράς/ανάκτησης.',
|
||||
'negative_amount_invalid' => 'Το ποσό είσπραξης δεν μπορεί να είναι αρνητικό.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => 'Account #',
|
||||
'add_payment' => 'Add Payment',
|
||||
'amount_due' => 'Amount Due',
|
||||
'amount_due_not_covered' => 'Payments do not cover the amount due.',
|
||||
'amount_tendered' => 'Amount Tendered',
|
||||
'authorized_signature' => 'Authorised Signature',
|
||||
'bank_transfer' => 'Bank Transfer',
|
||||
@@ -132,6 +133,7 @@ return [
|
||||
'must_enter_numeric' => 'Amount Tendered must be a number.',
|
||||
'must_enter_numeric_giftcard' => 'Gift Card Number must be a number.',
|
||||
'must_enter_reference_code' => 'Reference/Retrieval Number must be entered.',
|
||||
'negative_amount_invalid' => 'Amount Tendered cannot be negative.',
|
||||
'negative_discount_invalid' => 'Discount cannot be negative.',
|
||||
'negative_price_invalid' => 'Price cannot be negative.',
|
||||
'negative_quantity_invalid' => 'Quantity cannot be negative.',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => 'Account #',
|
||||
'add_payment' => 'Add Payment',
|
||||
'amount_due' => 'Amount Due',
|
||||
'amount_due_not_covered' => 'Payments do not cover the amount due.',
|
||||
'amount_tendered' => 'Amount Tendered',
|
||||
'authorized_signature' => 'Authorized Signature',
|
||||
'bank_transfer' => 'Bank Transfer',
|
||||
@@ -132,6 +133,7 @@ return [
|
||||
'must_enter_numeric' => 'Amount Tendered must be a number.',
|
||||
'must_enter_numeric_giftcard' => 'Gift Card Number must be a number.',
|
||||
'must_enter_reference_code' => 'Reference/Retrieval Number must be entered.',
|
||||
'negative_amount_invalid' => 'Amount Tendered cannot be negative.',
|
||||
'negative_discount_invalid' => 'Discount cannot be negative.',
|
||||
'negative_price_invalid' => 'Price cannot be negative.',
|
||||
'negative_quantity_invalid' => 'Quantity cannot be negative.',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => 'Cuenta #',
|
||||
'add_payment' => 'Agregar Pago',
|
||||
'amount_due' => 'Monto Adeudado',
|
||||
'amount_due_not_covered' => 'Los pagos no cubren el importe adeudado.',
|
||||
'amount_tendered' => 'Cantidad Recibida',
|
||||
'authorized_signature' => 'Firma Autorizada',
|
||||
'bank_transfer' => 'Transferencia Bancaria',
|
||||
@@ -132,6 +133,7 @@ return [
|
||||
'must_enter_numeric' => 'Cantidad Recibida debe ser número.',
|
||||
'must_enter_numeric_giftcard' => 'Número de Tarjeta de Regalo debe ser número.',
|
||||
'must_enter_reference_code' => 'Se debe ingresar el número de referencia/recuperación.',
|
||||
'negative_amount_invalid' => 'La cantidad recibida no puede ser negativa.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => 'Cuenta #',
|
||||
'add_payment' => 'Agregar Pago',
|
||||
'amount_due' => 'Monto de adeudo',
|
||||
'amount_due_not_covered' => 'Los pagos no cubren el monto adeudado.',
|
||||
'amount_tendered' => 'Cantidad Recibida',
|
||||
'authorized_signature' => 'Firma Autorizada',
|
||||
'bank_transfer' => 'Transferencia Bancaria',
|
||||
@@ -132,6 +133,7 @@ return [
|
||||
'must_enter_numeric' => 'Cantidad recibida debe ser un número.',
|
||||
'must_enter_numeric_giftcard' => 'Número de Tarjeta de Regalo debe ser un número.',
|
||||
'must_enter_reference_code' => 'Se debe ingresar el número de referencia/recuperación.',
|
||||
'negative_amount_invalid' => 'La cantidad recibida no puede ser negativa.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => 'حساب #',
|
||||
'add_payment' => 'افزودن پرداخت',
|
||||
'amount_due' => 'مبلغ پرداختی',
|
||||
'amount_due_not_covered' => 'پرداختها مبلغ بدهی را پوشش نمیدهند.',
|
||||
'amount_tendered' => 'مبلغ مناقصه',
|
||||
'authorized_signature' => 'امضای مجاز',
|
||||
'cancel_sale' => 'لغو',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => 'مقدار پیشنهادی باید یک عدد باشد.',
|
||||
'must_enter_numeric_giftcard' => 'شماره کارت هدیه باید یک عدد باشد.',
|
||||
'must_enter_reference_code' => 'شماره مرجع/بازیابی باید وارد شود.',
|
||||
'negative_amount_invalid' => 'مبلغ مناقصه نمیتواند منفی باشد.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => '# Compte',
|
||||
'add_payment' => 'Ajout Paiement',
|
||||
'amount_due' => 'Montant à Payer',
|
||||
'amount_due_not_covered' => 'Les paiements ne couvrent pas le montant dû.',
|
||||
'amount_tendered' => 'Montant Présenté',
|
||||
'authorized_signature' => 'Signature autorisée',
|
||||
'bank_transfer' => 'Virement Bancaire',
|
||||
@@ -132,6 +133,7 @@ return [
|
||||
'must_enter_numeric' => 'Veuillez entrer une valeur numérique pour la somme.',
|
||||
'must_enter_numeric_giftcard' => 'Veuillez entrer une valeur numérique pour le numéro de carte.',
|
||||
'must_enter_reference_code' => 'Le numéro de référence/récupération doit être saisi.',
|
||||
'negative_amount_invalid' => 'Le montant présenté ne peut pas être négatif.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => 'חשבון מס #',
|
||||
'add_payment' => 'הוסף תשלום',
|
||||
'amount_due' => 'סכום לתשלום',
|
||||
'amount_due_not_covered' => 'התשלומים אינם מכסים את הסכום לתשלום.',
|
||||
'amount_tendered' => 'סכום ההצעה',
|
||||
'authorized_signature' => 'חתימת מורשה',
|
||||
'cancel_sale' => 'בטל',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => 'סכום ההצעה חייב להיות מספר.',
|
||||
'must_enter_numeric_giftcard' => 'מספר כרטיס המתנה חייב להיות מספר.',
|
||||
'must_enter_reference_code' => 'יש להזין מספר אסמכתא/אחזור.',
|
||||
'negative_amount_invalid' => 'סכום ההצעה לא יכול להיות שלילי.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => '',
|
||||
'add_payment' => 'Dodaj plaćanje',
|
||||
'amount_due' => 'Iznos duga',
|
||||
'amount_due_not_covered' => 'Uplate ne pokrivaju dospjeli iznos.',
|
||||
'amount_tendered' => 'Ponuđeni iznos',
|
||||
'authorized_signature' => '',
|
||||
'cancel_sale' => 'Otkaži',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => 'Morate unijeti numeričku vrijednost za količinu',
|
||||
'must_enter_numeric_giftcard' => 'Morate unijeti numeričku vrijednost za poklon bon',
|
||||
'must_enter_reference_code' => 'Referentni/broj za preuzimanje mora biti unesen.',
|
||||
'negative_amount_invalid' => 'Ponuđeni iznos ne može biti negativan.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => '',
|
||||
'add_payment' => 'Fiz. hozzáad.',
|
||||
'amount_due' => 'Fennmaradó',
|
||||
'amount_due_not_covered' => 'A befizetések nem fedezik az esedékes összeget.',
|
||||
'amount_tendered' => 'Összeg',
|
||||
'authorized_signature' => '',
|
||||
'cancel_sale' => 'Mégsem',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => 'Számot kell megadnia a megrendelt mennyiséghez',
|
||||
'must_enter_numeric_giftcard' => 'Vásárlási utalvány számát adja meg',
|
||||
'must_enter_reference_code' => 'A hivatkozási/visszakeresési számot meg kell adni.',
|
||||
'negative_amount_invalid' => 'Az összeg nem lehet negatív.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => '',
|
||||
'add_payment' => '',
|
||||
'amount_due' => '',
|
||||
'amount_due_not_covered' => 'Վճարումները չեն ծածկում վճարման ենթակա գումարը.',
|
||||
'amount_tendered' => '',
|
||||
'authorized_signature' => '',
|
||||
'cancel_sale' => '',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => '',
|
||||
'must_enter_numeric_giftcard' => '',
|
||||
'must_enter_reference_code' => 'Պետք է մուտքագրվի հղման/որոնման համարը։',
|
||||
'negative_amount_invalid' => 'Վճարված գումարը չի կարող բացասական լինել.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => 'Akun #',
|
||||
'add_payment' => 'Terima',
|
||||
'amount_due' => 'Uang Kembalian',
|
||||
'amount_due_not_covered' => 'Pembayaran tidak menutupi jumlah yang harus dibayar.',
|
||||
'amount_tendered' => 'Nilai Pembayaran',
|
||||
'authorized_signature' => 'Tanda tangan',
|
||||
'cancel_sale' => 'Batal Jual',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => 'Nilai yang dimasukkan harus berupa angka.',
|
||||
'must_enter_numeric_giftcard' => 'Nomor Gift Card harus berupa angka.',
|
||||
'must_enter_reference_code' => 'Nomor referensi/pengambilan harus dimasukkan.',
|
||||
'negative_amount_invalid' => 'Nilai pembayaran tidak boleh negatif.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => 'Account #',
|
||||
'add_payment' => 'Aggiungi Pagamento',
|
||||
'amount_due' => 'Importo Dovuto',
|
||||
'amount_due_not_covered' => 'I pagamenti non coprono l\'importo dovuto.',
|
||||
'amount_tendered' => 'Importo Offerto',
|
||||
'authorized_signature' => 'Firma Autorizzata',
|
||||
'cancel_sale' => 'Annulla',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => 'Import Offerto deve essere un numero.',
|
||||
'must_enter_numeric_giftcard' => 'Numero Carta Regalo deve essere un numero.',
|
||||
'must_enter_reference_code' => 'Il numero di riferimento/recupero deve essere inserito.',
|
||||
'negative_amount_invalid' => 'L\'importo offerto non può essere negativo.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => '',
|
||||
'add_payment' => '',
|
||||
'amount_due' => '',
|
||||
'amount_due_not_covered' => 'გადახდები არ ფარავს გადასახდელ თანხას.',
|
||||
'amount_tendered' => '',
|
||||
'authorized_signature' => '',
|
||||
'bank_transfer' => '',
|
||||
@@ -132,6 +133,7 @@ return [
|
||||
'must_enter_numeric' => '',
|
||||
'must_enter_numeric_giftcard' => '',
|
||||
'must_enter_reference_code' => 'მიუთითეთ საცნობარო/მოძიების ნომერი.',
|
||||
'negative_amount_invalid' => 'გადახდილი თანხა არ შეიძლება იყოს უარყოფითი.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => 'លេខគណនី',
|
||||
'add_payment' => 'បញ្ជូលរបៀបបង់ប្រាក់',
|
||||
'amount_due' => 'ទឹកប្រាក់ដែលត្រូវបង់',
|
||||
'amount_due_not_covered' => 'ការទូទាត់មិនគ្របដណ្តប់ចំនួនទឹកប្រាក់ដែលត្រូវបង់ទេ។',
|
||||
'amount_tendered' => 'ទឹកប្រាក់បានមកពីការបង់ទាំងផ្សេងៗ',
|
||||
'authorized_signature' => 'ហត្ថលេខា',
|
||||
'cancel_sale' => 'បោះបង់',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => '',
|
||||
'must_enter_numeric_giftcard' => '',
|
||||
'must_enter_reference_code' => 'លេខយោង/ទាញយកត្រូវតែបញ្ចូល។',
|
||||
'negative_amount_invalid' => 'ទឹកប្រាក់បានមកពីការបង់មិនអាចជាចំនួនអវិជ្ជមានបានទេ។',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => '',
|
||||
'add_payment' => 'Add Payment',
|
||||
'amount_due' => 'Amount Due',
|
||||
'amount_due_not_covered' => 'ການຊຳລະເງິນບໍ່ຄຸ້ມຈຳນວນທີ່ຕ້ອງຈ່າຍ.',
|
||||
'amount_tendered' => 'Amount Tendered',
|
||||
'authorized_signature' => '',
|
||||
'cancel_sale' => 'Cancel',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => 'Amount Tendered must be a number.',
|
||||
'must_enter_numeric_giftcard' => 'Gift Card Number must be a number.',
|
||||
'must_enter_reference_code' => 'ຕ້ອງປ້ອນໝາຍເລກອ້າງອີງ/ດຶງຂໍ້ມູນ.',
|
||||
'negative_amount_invalid' => 'ຈຳນວນເງິນທີ່ຈ່າຍບໍ່ສາມາດເປັນຄ່າລົບໄດ້.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => '',
|
||||
'add_payment' => '',
|
||||
'amount_due' => '',
|
||||
'amount_due_not_covered' => 'പേയ്മെന്റുകൾ അടയ്ക്കേണ്ട തുക ഉൾക്കൊള്ളുന്നില്ല.',
|
||||
'amount_tendered' => '',
|
||||
'authorized_signature' => '',
|
||||
'cancel_sale' => '',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => '',
|
||||
'must_enter_numeric_giftcard' => '',
|
||||
'must_enter_reference_code' => 'റഫറൻസ്/റിട്രീവൽ നമ്പർ നൽകണം.',
|
||||
'negative_amount_invalid' => 'നൽകിയ തുക നെഗറ്റീവ് ആകാൻ പാടില്ല.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => '',
|
||||
'add_payment' => '',
|
||||
'amount_due' => '',
|
||||
'amount_due_not_covered' => 'Betalingene dekker ikke det skyldige beløpet.',
|
||||
'amount_tendered' => '',
|
||||
'authorized_signature' => '',
|
||||
'cancel_sale' => '',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => '',
|
||||
'must_enter_numeric_giftcard' => '',
|
||||
'must_enter_reference_code' => 'Referanse-/hentingsnummer må angis.',
|
||||
'negative_amount_invalid' => 'Det mottatte beløpet kan ikke være negativt.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => 'Btw-nummer',
|
||||
'add_payment' => 'Betaal',
|
||||
'amount_due' => 'Te betalen',
|
||||
'amount_due_not_covered' => 'De betalingen dekken het verschuldigde bedrag niet.',
|
||||
'amount_tendered' => 'Ontvangen bedrag',
|
||||
'authorized_signature' => 'Handtekening',
|
||||
'cancel_sale' => 'Annuleer',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => 'Het ontvangen bedrag moet een numerieke waarde zijn.',
|
||||
'must_enter_numeric_giftcard' => 'Er moet een geldige code worden ingevuld voor de cadeaubon.',
|
||||
'must_enter_reference_code' => 'Referentie-/ophaalnummer moet worden ingevoerd.',
|
||||
'negative_amount_invalid' => 'Het ontvangen bedrag mag niet negatief zijn.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => 'Account #',
|
||||
'add_payment' => 'Betaling toevoegen',
|
||||
'amount_due' => 'Te betalen bedrag',
|
||||
'amount_due_not_covered' => 'De betalingen dekken het verschuldigde bedrag niet.',
|
||||
'amount_tendered' => 'Betaald bedrag',
|
||||
'authorized_signature' => 'Geautoriseerde handtekening',
|
||||
'cancel_sale' => 'Annuleren',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => 'Betaald bedrag moet een getal zijn.',
|
||||
'must_enter_numeric_giftcard' => 'Cadeaubonnummer moet een getal zijn.',
|
||||
'must_enter_reference_code' => 'Referentie-/ophaalnummer moet worden ingevoerd.',
|
||||
'negative_amount_invalid' => 'Het betaalde bedrag mag niet negatief zijn.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => '',
|
||||
'add_payment' => '',
|
||||
'amount_due' => '',
|
||||
'amount_due_not_covered' => 'Płatności nie pokrywają należnej kwoty.',
|
||||
'amount_tendered' => '',
|
||||
'authorized_signature' => '',
|
||||
'cancel_sale' => '',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => '',
|
||||
'must_enter_numeric_giftcard' => '',
|
||||
'must_enter_reference_code' => 'Należy podać numer referencyjny/pobierania.',
|
||||
'negative_amount_invalid' => 'Otrzymana kwota nie może być ujemna.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => 'Montante º',
|
||||
'add_payment' => 'Pagar',
|
||||
'amount_due' => 'Diferença',
|
||||
'amount_due_not_covered' => 'Os pagamentos não cobrem o valor devido.',
|
||||
'amount_tendered' => 'A Pagar',
|
||||
'authorized_signature' => 'Assinatura autorizada',
|
||||
'cancel_sale' => 'Cancelar',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => 'Deve entrar valor numérico para montante da proposta apresentada.',
|
||||
'must_enter_numeric_giftcard' => 'Deve entrar valor numérico para o número de cartão presente.',
|
||||
'must_enter_reference_code' => 'O número de referência/recuperação deve ser informado.',
|
||||
'negative_amount_invalid' => 'O valor pago não pode ser negativo.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => 'Cont #',
|
||||
'add_payment' => 'Adauga Plata',
|
||||
'amount_due' => 'Suma datorata',
|
||||
'amount_due_not_covered' => 'Plățile nu acoperă suma datorată.',
|
||||
'amount_tendered' => 'Suma Oferita',
|
||||
'authorized_signature' => 'Semnatura Autorizata',
|
||||
'cancel_sale' => 'Anuleaza',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => 'Valoare ofertata trebuie sa fie numerica.',
|
||||
'must_enter_numeric_giftcard' => 'Numar Card Cadou trebuie sa fie numeric.',
|
||||
'must_enter_reference_code' => 'Numărul de referință/recuperare trebuie introdus.',
|
||||
'negative_amount_invalid' => 'Suma oferită nu poate fi negativă.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => 'Счет #',
|
||||
'add_payment' => 'Добавить оплату',
|
||||
'amount_due' => 'Сумма задолженности',
|
||||
'amount_due_not_covered' => 'Платежи не покрывают причитающуюся сумму.',
|
||||
'amount_tendered' => 'Предложенная сумма',
|
||||
'authorized_signature' => 'Подпись уполномоченного лица',
|
||||
'cancel_sale' => 'Отменить продажу',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => 'Предложенная сумма должна быть числом.',
|
||||
'must_enter_numeric_giftcard' => 'Номер подарочной карты должен быть числом.',
|
||||
'must_enter_reference_code' => 'Необходимо ввести справочный/поисковый номер.',
|
||||
'negative_amount_invalid' => 'Предложенная сумма не может быть отрицательной.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => 'Konto #',
|
||||
'add_payment' => 'Lägg till betalning',
|
||||
'amount_due' => 'Belopp',
|
||||
'amount_due_not_covered' => 'Betalningarna täcker inte det förfallna beloppet.',
|
||||
'amount_tendered' => 'Upplagt belopp',
|
||||
'authorized_signature' => 'Auktoriserad signatur',
|
||||
'cancel_sale' => 'Avbryt',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => 'Belopp som anslås måste vara ett nummer.',
|
||||
'must_enter_numeric_giftcard' => 'Presentkortets nummer måste vara ett nummer.',
|
||||
'must_enter_reference_code' => 'Referens-/hämtningsnummer måste anges.',
|
||||
'negative_amount_invalid' => 'Det upplagda beloppet kan inte vara negativt.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
// "unsuspend_and_delete" => "Hatua (Action)",
|
||||
'account_number' => 'Nambari ya Akaunti',
|
||||
'add_payment' => 'Ongeza Malipo',
|
||||
'amount_due' => 'Kiasi Kinachodaiwa',
|
||||
'amount_due_not_covered' => 'Malipo hayafikii kiwango kinachodaiwa.',
|
||||
'amount_tendered' => 'Kiasi Kilicholipwa',
|
||||
'authorized_signature' => 'Sahihi Iliyothibitishwa',
|
||||
'cancel_sale' => 'Ghairi',
|
||||
@@ -132,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => 'Kiasi Kilicholipwa lazima kiwe Namba.',
|
||||
'must_enter_numeric_giftcard' => 'Namba ya Kadi ya Zawadi lazima iwe Namba.',
|
||||
'must_enter_reference_code' => 'Nambari ya Kumbukumbu/Upatikanaji lazima iingizwe.',
|
||||
'negative_amount_invalid' => 'Kiasi kilicholipwa hakiwezi kuwa hasi.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
@@ -226,14 +227,14 @@ return [
|
||||
'unsuccessfully_suspended_sale' => 'Imeshindikana kusitisha Mauzo.',
|
||||
'unsuccessfully_updated' => 'Kusasisha mauzo kimeshindikana.',
|
||||
'unsuspend' => 'Ondoa Kusitishwa',
|
||||
'unsuspend_and_delete' => 'Hatua',
|
||||
'update' => 'Sasisha',
|
||||
'upi' => 'UPI',
|
||||
'visa' => '',
|
||||
'wholesale' => '',
|
||||
'work_order' => 'Agizo la Kazi (Work Order)',
|
||||
'work_order_number' => 'Nambari ya Agizo la Kazi',
|
||||
'work_order_number_duplicate' => 'Nambari ya Agizo la Kazi lazima iwe ya kipekee.',
|
||||
'work_order_sent' => 'Agizo la Kazi limetumwa kwa',
|
||||
'work_order_unsent' => 'Imeshindikana kutuma Agizo la Kazi kwa',
|
||||
'unsuspend_and_delete' => 'Hatua',
|
||||
'update' => 'Sasisha',
|
||||
'upi' => 'UPI',
|
||||
'visa' => '',
|
||||
'wholesale' => '',
|
||||
'work_order' => 'Agizo la Kazi (Work Order)',
|
||||
'work_order_number' => 'Nambari ya Agizo la Kazi',
|
||||
'work_order_number_duplicate' => 'Nambari ya Agizo la Kazi lazima iwe ya kipekee.',
|
||||
'work_order_sent' => 'Agizo la Kazi limetumwa kwa',
|
||||
'work_order_unsent' => 'Imeshindikana kutuma Agizo la Kazi kwa',
|
||||
];
|
||||
@@ -1,10 +1,10 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
// "unsuspend_and_delete" => "Hatua (Action)",
|
||||
'account_number' => 'Nambari ya Akaunti',
|
||||
'add_payment' => 'Ongeza Malipo',
|
||||
'amount_due' => 'Kiasi Kinachodaiwa',
|
||||
'amount_due_not_covered' => 'Malipo hayafikii kiwango kinachodaiwa.',
|
||||
'amount_tendered' => 'Kiasi Kilicholipwa',
|
||||
'authorized_signature' => 'Sahihi Iliyothibitishwa',
|
||||
'cancel_sale' => 'Ghairi',
|
||||
@@ -132,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => 'Kiasi Kilicholipwa lazima kiwe Namba.',
|
||||
'must_enter_numeric_giftcard' => 'Namba ya Kadi ya Zawadi lazima iwe Namba.',
|
||||
'must_enter_reference_code' => 'Nambari ya Kumbukumbu/Upatikanaji lazima iingizwe.',
|
||||
'negative_amount_invalid' => 'Kiasi kilicholipwa hakiwezi kuwa hasi.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
@@ -226,14 +227,14 @@ return [
|
||||
'unsuccessfully_suspended_sale' => 'Imeshindikana kusitisha Mauzo.',
|
||||
'unsuccessfully_updated' => 'Kusasisha mauzo kimeshindikana.',
|
||||
'unsuspend' => 'Ondoa Kusitishwa',
|
||||
'unsuspend_and_delete' => 'Hatua',
|
||||
'update' => 'Sasisha',
|
||||
'upi' => 'UPI',
|
||||
'visa' => '',
|
||||
'wholesale' => '',
|
||||
'work_order' => 'Agizo la Kazi (Work Order)',
|
||||
'work_order_number' => 'Nambari ya Agizo la Kazi',
|
||||
'work_order_number_duplicate' => 'Nambari ya Agizo la Kazi lazima iwe ya kipekee.',
|
||||
'work_order_sent' => 'Agizo la Kazi limetumwa kwa',
|
||||
'work_order_unsent' => 'Imeshindikana kutuma Agizo la Kazi kwa',
|
||||
'unsuspend_and_delete' => 'Hatua',
|
||||
'update' => 'Sasisha',
|
||||
'upi' => 'UPI',
|
||||
'visa' => '',
|
||||
'wholesale' => '',
|
||||
'work_order' => 'Agizo la Kazi (Work Order)',
|
||||
'work_order_number' => 'Nambari ya Agizo la Kazi',
|
||||
'work_order_number_duplicate' => 'Nambari ya Agizo la Kazi lazima iwe ya kipekee.',
|
||||
'work_order_sent' => 'Agizo la Kazi limetumwa kwa',
|
||||
'work_order_unsent' => 'Imeshindikana kutuma Agizo la Kazi kwa',
|
||||
];
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => 'கணக்கு #',
|
||||
'add_payment' => 'கட்டணத்தைச் சேர்க்கவும்',
|
||||
'amount_due' => 'செலுத்த வேண்டிய தொகை',
|
||||
'amount_due_not_covered' => 'செலுத்தப்பட்ட தொகை நிலுவைத் தொகையை ஈடுசெய்யவில்லை.',
|
||||
'amount_tendered' => 'கொடுத்த தொகை',
|
||||
'authorized_signature' => 'அங்கீகரிக்கப்பட்ட கையெழுத்து',
|
||||
'cancel_sale' => 'ரத்துசெய்',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => 'தொகை ஒரு எண்ணாக இருக்க வேண்டும்.',
|
||||
'must_enter_numeric_giftcard' => 'பரிசு அட்டை எண் ஒரு எண்ணாக இருக்க வேண்டும்.',
|
||||
'must_enter_reference_code' => 'குறிப்பு/மீட்டெடுப்பு எண் உள்ளிட வேண்டும்.',
|
||||
'negative_amount_invalid' => 'கொடுத்த தொகை எதிர்மறையாக இருக்கக்கூடாது.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => 'บัญชี #',
|
||||
'add_payment' => 'เพิ่มบิล',
|
||||
'amount_due' => 'ยอดค้างชำระ',
|
||||
'amount_due_not_covered' => 'การชำระเงินไม่ครอบคลุมจำนวนที่ต้องชำระ',
|
||||
'amount_tendered' => 'ชำระเข้ามา',
|
||||
'authorized_signature' => 'ลายเซ็นผู้มีอำนาจ',
|
||||
'cancel_sale' => 'ยกเลิกการขาย',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => 'จำนวนที่ถุกประมูลต้องใส่ข้อมุลที่เปนตัวเลข',
|
||||
'must_enter_numeric_giftcard' => 'เลขที่บัตรของขวัญ ต้องใส่ตัวเลขเท่านั้น',
|
||||
'must_enter_reference_code' => 'ต้องระบุหมายเลขอ้างอิง/การดึงข้อมูล',
|
||||
'negative_amount_invalid' => 'ชำระเข้ามาไม่สามารถเป็นค่าติดลบได้',
|
||||
'negative_discount_invalid' => 'ส่วนลดไม่สามารถเป็นค่าติดลบได้',
|
||||
'negative_price_invalid' => 'ราคาไม่สามารถเป็นค่าติดลบได้',
|
||||
'negative_quantity_invalid' => 'จำนวนไม่สามารถเป็นค่าติดลบได้',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => 'Account #',
|
||||
'add_payment' => 'Add Payment',
|
||||
'amount_due' => 'Amount Due',
|
||||
'amount_due_not_covered' => 'Hindi sapat ang mga bayad para sa kabuuang dapat bayaran.',
|
||||
'amount_tendered' => 'Amount Tendered',
|
||||
'authorized_signature' => 'Authorized Signature',
|
||||
'cancel_sale' => 'Cancel',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => 'Amount Tendered must be a number.',
|
||||
'must_enter_numeric_giftcard' => 'Gift Card Number must be a number.',
|
||||
'must_enter_reference_code' => 'Ang Numero ng Sanggunian/Pagkuha ay dapat ipasok.',
|
||||
'negative_amount_invalid' => 'Hindi maaaring negatibo ang halagang ibinayad.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => 'Hesap Numarası',
|
||||
'add_payment' => 'Ödeme Ekle',
|
||||
'amount_due' => 'Kalan Ödeme',
|
||||
'amount_due_not_covered' => 'Ödemeler, ödenmesi gereken tutarı karşılamıyor.',
|
||||
'amount_tendered' => 'Ödenen Tutar',
|
||||
'authorized_signature' => 'Yetkili İmza',
|
||||
'cancel_sale' => 'İptal Et',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => 'Ödenen Tutar sayı olmalıdır.',
|
||||
'must_enter_numeric_giftcard' => 'Hediye Çeki Numarası sayı olmalıdır.',
|
||||
'must_enter_reference_code' => 'Referans/Alım numarası girilmelidir.',
|
||||
'negative_amount_invalid' => 'Ödenen tutar negatif olamaz.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => 'Номер рахунку',
|
||||
'add_payment' => 'Додати платіж',
|
||||
'amount_due' => 'Сума заборгованості',
|
||||
'amount_due_not_covered' => 'Платежі не покривають суму до сплати.',
|
||||
'amount_tendered' => 'Запропонована сума',
|
||||
'authorized_signature' => 'Підпис уповноваженої особи',
|
||||
'cancel_sale' => 'Відмінити',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => 'Введена сума повинна бути числом.',
|
||||
'must_enter_numeric_giftcard' => 'Номер подарункової картки повинен бути цифровим.',
|
||||
'must_enter_reference_code' => 'Необхідно ввести довідковий/пошуковий номер.',
|
||||
'negative_amount_invalid' => 'Запропонована сума не може бути від\'ємною.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => 'اکاوٗنٹ',
|
||||
'add_payment' => '',
|
||||
'amount_due' => '',
|
||||
'amount_due_not_covered' => 'ادائیگیاں واجب الادا رقم کو پورا نہیں کرتیں۔',
|
||||
'amount_tendered' => '',
|
||||
'authorized_signature' => '',
|
||||
'cancel_sale' => '',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => '',
|
||||
'must_enter_numeric_giftcard' => '',
|
||||
'must_enter_reference_code' => 'حوالہ/بازیابی نمبر درج کرنا ضروری ہے۔',
|
||||
'negative_amount_invalid' => 'ادا کی گئی رقم منفی نہیں ہو سکتی۔',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => 'Tài khoản #',
|
||||
'add_payment' => 'Thêm thanh toán',
|
||||
'amount_due' => 'Số còn lại phải thanh toán',
|
||||
'amount_due_not_covered' => 'Các khoản thanh toán không đủ để trang trải số tiền phải trả.',
|
||||
'amount_tendered' => 'Số tiền thanh toán',
|
||||
'authorized_signature' => 'Chữ ký ủy quyền',
|
||||
'cancel_sale' => 'Thôi',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => 'Số tiền thanh toán phải là dạng số.',
|
||||
'must_enter_numeric_giftcard' => 'Số Thẻ quà tặng phải là dạng số.',
|
||||
'must_enter_reference_code' => 'Số tham chiếu/truy xuất phải được nhập.',
|
||||
'negative_amount_invalid' => 'Số tiền thanh toán không được là số âm.',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => '',
|
||||
'add_payment' => '新增付款',
|
||||
'amount_due' => '商品金額',
|
||||
'amount_due_not_covered' => '付款金额未覆盖应付金额。',
|
||||
'amount_tendered' => '已收帳款',
|
||||
'authorized_signature' => '',
|
||||
'cancel_sale' => '取消銷售',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => '已收帳款必須輸入數值',
|
||||
'must_enter_numeric_giftcard' => '禮金券編號必須輸入數值',
|
||||
'must_enter_reference_code' => '必须输入参考/检索编号。',
|
||||
'negative_amount_invalid' => '已收帐款不能为负数。',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'account_number' => '帳戶 #',
|
||||
'add_payment' => '新增付款',
|
||||
'amount_due' => '商品金額',
|
||||
'amount_due_not_covered' => '付款金額未涵蓋應付金額。',
|
||||
'amount_tendered' => '已收帳款',
|
||||
'authorized_signature' => '授權簽名',
|
||||
'cancel_sale' => '取消銷售',
|
||||
@@ -131,6 +132,7 @@ return [
|
||||
'must_enter_numeric' => '已收帳款必須輸入數值.',
|
||||
'must_enter_numeric_giftcard' => '禮金券編號必須輸入數值.',
|
||||
'must_enter_reference_code' => '必須輸入參考/檢索編號。',
|
||||
'negative_amount_invalid' => '已收帳款不能為負數。',
|
||||
'negative_discount_invalid' => '',
|
||||
'negative_price_invalid' => '',
|
||||
'negative_quantity_invalid' => '',
|
||||
|
||||
@@ -316,6 +316,10 @@ class Giftcard extends Model
|
||||
*/
|
||||
public function decrementGiftcardValue(string $giftcardNumber, float $amount): bool
|
||||
{
|
||||
if ($amount <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$builder = $this->db->table('giftcards');
|
||||
$builder->where('giftcard_number', $giftcardNumber);
|
||||
$builder->where('deleted', 0);
|
||||
|
||||
+63
-62
@@ -524,13 +524,13 @@ class Sale extends Model
|
||||
int $customerId,
|
||||
int $employeeId,
|
||||
string $comment,
|
||||
?string $invoice_number,
|
||||
?string $work_order_number,
|
||||
?string $quote_number,
|
||||
int $sale_type,
|
||||
?string $invoiceNumber,
|
||||
?string $workOrderNumber,
|
||||
?string $quoteNumber,
|
||||
int $saleType,
|
||||
?array $payments,
|
||||
?int $dinner_table_id,
|
||||
?array &$sales_taxes
|
||||
?int $dinnerTableId,
|
||||
?array &$salesTaxes
|
||||
): int { // TODO: this method returns the sale_id but the override is expecting it to return a bool. The signature needs to be reworked. Generally when there are more than 3 maybe 4 parameters, there's a good chance that an object needs to be passed rather than so many params.
|
||||
$config = config(OSPOS::class)->settings;
|
||||
$attribute = model(Attribute::class);
|
||||
@@ -539,23 +539,23 @@ class Sale extends Model
|
||||
$inventory = model('Inventory');
|
||||
$item = model(Item::class);
|
||||
|
||||
$item_quantity = model(Item_quantity::class);
|
||||
$itemQuantity = model(Item_quantity::class);
|
||||
|
||||
if (count($items) == 0) { // TODO: ===
|
||||
return -1; // TODO: Replace -1 with a constant
|
||||
}
|
||||
|
||||
$sales_data = [
|
||||
$salesData = [
|
||||
'sale_time' => date('Y-m-d H:i:s'),
|
||||
'customer_id' => $customer->exists($customerId) ? $customerId : null,
|
||||
'employee_id' => $employeeId,
|
||||
'comment' => $comment,
|
||||
'sale_status' => $saleStatus,
|
||||
'invoice_number' => $invoice_number,
|
||||
'quote_number' => $quote_number,
|
||||
'work_order_number' => $work_order_number,
|
||||
'dinner_table_id' => $dinner_table_id,
|
||||
'sale_type' => $sale_type
|
||||
'invoice_number' => $invoiceNumber,
|
||||
'quote_number' => $quoteNumber,
|
||||
'work_order_number' => $workOrderNumber,
|
||||
'dinner_table_id' => $dinnerTableId,
|
||||
'sale_type' => $saleType
|
||||
];
|
||||
|
||||
// Run these queries as a transaction, we want to make sure we do all or nothing
|
||||
@@ -567,26 +567,27 @@ class Sale extends Model
|
||||
|
||||
$builder = $this->db->table('sales');
|
||||
if ($saleId == NEW_ENTRY) {
|
||||
$builder->insert($sales_data);
|
||||
$builder->insert($salesData);
|
||||
$saleId = $this->db->insertID();
|
||||
} else {
|
||||
$builder->where('sale_id', $saleId);
|
||||
$builder->update($sales_data);
|
||||
$builder->update($salesData);
|
||||
}
|
||||
|
||||
$total_amount = 0;
|
||||
$totalAmount = 0;
|
||||
$totalAmountUsed = 0;
|
||||
|
||||
foreach ($payments as $payment_id => $payment) {
|
||||
if (!empty(strstr($payment['payment_type'], lang('Sales.giftcard')))) {
|
||||
$splitPayment = explode(':', $payment['payment_type']);
|
||||
foreach ($payments as $paymentId => $payment) {
|
||||
$splitPayment = explode(':', $payment['payment_type'], 2);
|
||||
$paymentPrefix = $splitPayment[0];
|
||||
|
||||
if (! $giftcard->decrementGiftcardValue($splitPayment[1], (float) $payment['payment_amount'])) {
|
||||
if ($paymentPrefix === lang('Sales.giftcard')) {
|
||||
if (empty($splitPayment[1]) || ! $giftcard->decrementGiftcardValue($splitPayment[1], (float) $payment['payment_amount'])) {
|
||||
$this->db->transRollback();
|
||||
|
||||
return INSUFFICIENT_GIFTCARD_BALANCE;
|
||||
}
|
||||
} elseif (!empty(strstr($payment['payment_type'], lang('Sales.rewards')))) {
|
||||
} elseif ($paymentPrefix === lang('Sales.rewards')) {
|
||||
if (! $customer->adjustRewardPoints($customerId, -(float) $payment['payment_amount'])) {
|
||||
$this->db->transRollback();
|
||||
|
||||
@@ -596,7 +597,7 @@ class Sale extends Model
|
||||
$totalAmountUsed = floatval($totalAmountUsed) + floatval($payment['payment_amount']);
|
||||
}
|
||||
|
||||
$sales_payments_data = [
|
||||
$salesPaymentsData = [
|
||||
'sale_id' => $saleId,
|
||||
'payment_type' => $payment['payment_type'],
|
||||
'payment_amount' => $payment['payment_amount'],
|
||||
@@ -607,46 +608,46 @@ class Sale extends Model
|
||||
];
|
||||
|
||||
$builder = $this->db->table('sales_payments');
|
||||
$builder->insert($sales_payments_data);
|
||||
$builder->insert($salesPaymentsData);
|
||||
|
||||
$total_amount = floatval($total_amount) + floatval($payment['payment_amount']) - floatval($payment['cash_refund']);
|
||||
$totalAmount = floatval($totalAmount) + floatval($payment['payment_amount']) - floatval($payment['cash_refund']);
|
||||
}
|
||||
|
||||
$this->save_customer_rewards($customerId, $saleId, $total_amount, $totalAmountUsed);
|
||||
$this->save_customer_rewards($customerId, $saleId, $totalAmount, $totalAmountUsed);
|
||||
|
||||
$customer = $customer->get_info($customerId);
|
||||
|
||||
foreach ($items as $line => $item_data) {
|
||||
$cur_item_info = $item->get_info($item_data['item_id']);
|
||||
foreach ($items as $line => $itemData) {
|
||||
$curItemInfo = $item->get_info($itemData['item_id']);
|
||||
|
||||
if ($item_data['price'] == 0.00) {
|
||||
$item_data['discount'] = 0.00;
|
||||
if ($itemData['price'] == 0.00) {
|
||||
$itemData['discount'] = 0.00;
|
||||
}
|
||||
|
||||
$sales_items_data = [
|
||||
$salesItemsData = [
|
||||
'sale_id' => $saleId,
|
||||
'item_id' => $item_data['item_id'],
|
||||
'line' => $item_data['line'],
|
||||
'description' => character_limiter($item_data['description'], 255),
|
||||
'serialnumber' => character_limiter($item_data['serialnumber'], 30),
|
||||
'quantity_purchased' => $item_data['quantity'],
|
||||
'discount' => $item_data['discount'],
|
||||
'discount_type' => $item_data['discount_type'],
|
||||
'item_cost_price' => $item_data['cost_price'],
|
||||
'item_unit_price' => $item_data['price'],
|
||||
'item_location' => $item_data['item_location'],
|
||||
'print_option' => $item_data['print_option']
|
||||
'item_id' => $itemData['item_id'],
|
||||
'line' => $itemData['line'],
|
||||
'description' => character_limiter($itemData['description'], 255),
|
||||
'serialnumber' => character_limiter($itemData['serialnumber'], 30),
|
||||
'quantity_purchased' => $itemData['quantity'],
|
||||
'discount' => $itemData['discount'],
|
||||
'discount_type' => $itemData['discount_type'],
|
||||
'item_cost_price' => $itemData['cost_price'],
|
||||
'item_unit_price' => $itemData['price'],
|
||||
'item_location' => $itemData['item_location'],
|
||||
'print_option' => $itemData['print_option']
|
||||
];
|
||||
|
||||
$builder = $this->db->table('sales_items');
|
||||
$builder->insert($sales_items_data);
|
||||
$builder->insert($salesItemsData);
|
||||
|
||||
if ($cur_item_info->stock_type == HAS_STOCK && $saleStatus == COMPLETED) { // TODO: === ?
|
||||
if ($curItemInfo->stock_type == HAS_STOCK && $saleStatus == COMPLETED) { // TODO: === ?
|
||||
// Update stock quantity if item type is a standard stock item and the sale is a standard sale
|
||||
if (! $item_quantity->changeQuantity(
|
||||
$item_data['item_id'],
|
||||
$item_data['item_location'],
|
||||
-(float) $item_data['quantity'],
|
||||
if (! $itemQuantity->changeQuantity(
|
||||
$itemData['item_id'],
|
||||
$itemData['item_location'],
|
||||
-(float) $itemData['quantity'],
|
||||
)) {
|
||||
$this->db->transRollback();
|
||||
|
||||
@@ -654,38 +655,38 @@ class Sale extends Model
|
||||
}
|
||||
|
||||
// If an items was deleted but later returned it's restored with this rule
|
||||
if ($item_data['quantity'] < 0) {
|
||||
$item->undelete($item_data['item_id']);
|
||||
if ($itemData['quantity'] < 0) {
|
||||
$item->undelete($itemData['item_id']);
|
||||
}
|
||||
|
||||
// Inventory Count Details
|
||||
$sale_remarks = 'POS ' . $saleId; // TODO: Use string interpolation here.
|
||||
$inv_data = [
|
||||
$saleRemarks = 'POS ' . $saleId; // TODO: Use string interpolation here.
|
||||
$invData = [
|
||||
'trans_date' => date('Y-m-d H:i:s'),
|
||||
'trans_items' => $item_data['item_id'],
|
||||
'trans_items' => $itemData['item_id'],
|
||||
'trans_user' => $employeeId,
|
||||
'trans_location' => $item_data['item_location'],
|
||||
'trans_comment' => $sale_remarks,
|
||||
'trans_inventory' => -$item_data['quantity']
|
||||
'trans_location' => $itemData['item_location'],
|
||||
'trans_comment' => $saleRemarks,
|
||||
'trans_inventory' => -$itemData['quantity']
|
||||
];
|
||||
|
||||
$inventory->insert($inv_data, false);
|
||||
$inventory->insert($invData, false);
|
||||
}
|
||||
|
||||
$attribute->copy_attribute_links($item_data['item_id'], 'sale_id', $saleId);
|
||||
$attribute->copy_attribute_links($itemData['item_id'], 'sale_id', $saleId);
|
||||
}
|
||||
|
||||
if ($customerId == NEW_ENTRY || $customer->taxable) {
|
||||
$this->save_sales_tax($saleId, $sales_taxes[0]);
|
||||
$this->save_sales_items_taxes($saleId, $sales_taxes[1]);
|
||||
$this->save_sales_tax($saleId, $salesTaxes[0]);
|
||||
$this->save_sales_items_taxes($saleId, $salesTaxes[1]);
|
||||
}
|
||||
|
||||
if ($config['dinner_table_enable']) {
|
||||
$dinner_table = model(Dinner_table::class);
|
||||
$dinnerTable = model(Dinner_table::class);
|
||||
if ($saleStatus == COMPLETED) { // TODO: === ?
|
||||
$dinner_table->release($dinner_table_id);
|
||||
$dinnerTable->release($dinnerTableId);
|
||||
} else {
|
||||
$dinner_table->occupy($dinner_table_id);
|
||||
$dinnerTable->occupy($dinnerTableId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -100,6 +100,32 @@ class OSPOSRulesTest extends CIUnitTestCase
|
||||
$this->assertNull($error);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider validPathStrictProvider
|
||||
*/
|
||||
public function testValidPathStrict(string $candidate, bool $expected): void
|
||||
{
|
||||
$rules = new OSPOSRules();
|
||||
|
||||
$this->assertSame($expected, $rules->valid_path_strict($candidate));
|
||||
}
|
||||
|
||||
public static function validPathStrictProvider(): array
|
||||
{
|
||||
return [
|
||||
'plain sendmail path' => ['/usr/sbin/sendmail', true],
|
||||
'plain php path' => ['/usr/bin/php', true],
|
||||
'path with dash and underscore' => ['/opt/my-mail_bin/sendmail.exe', true],
|
||||
'empty string' => ['', false],
|
||||
'trailing newline bypass payload' => ["/usr/bin/php\n", false],
|
||||
'trailing newline plus injected command' => ["/usr/bin/php\nid", false],
|
||||
'embedded newline mid-string' => ["/usr/bin/php\n/bin/sh", false],
|
||||
'semicolon injection' => ['/usr/bin/php;id', false],
|
||||
'pipe injection' => ['/usr/bin/php|id', false],
|
||||
'space separated args' => ['/usr/bin/php -r "phpinfo();"', false],
|
||||
];
|
||||
}
|
||||
|
||||
private function injectSettings(array $settings): void
|
||||
{
|
||||
$ospos = new OSPOS();
|
||||
|
||||
@@ -287,7 +287,7 @@ class SalesControllerTest extends CIUnitTestCase
|
||||
'cost_price' => '1.00',
|
||||
'total' => $price,
|
||||
'discounted_total' => $price,
|
||||
'print_option' => 1,
|
||||
'print_option' => PRINT_YES,
|
||||
'stock_type' => HAS_NO_STOCK,
|
||||
'item_type' => ITEM,
|
||||
'hsn_code' => null,
|
||||
@@ -519,6 +519,185 @@ class SalesControllerTest extends CIUnitTestCase
|
||||
$this->assertEquals('0.01', $cart[1]['price']);
|
||||
}
|
||||
|
||||
protected function createGiftcard(float $value): int
|
||||
{
|
||||
$giftcardNumber = random_int(1000000, 9999999);
|
||||
|
||||
Database::connect()->table('giftcards')->insert([
|
||||
'giftcard_number' => $giftcardNumber,
|
||||
'value' => $value,
|
||||
'deleted' => 0,
|
||||
'person_id' => null,
|
||||
]);
|
||||
|
||||
return $giftcardNumber;
|
||||
}
|
||||
|
||||
protected function getGiftcardValue(int $giftcardNumber): float
|
||||
{
|
||||
$row = Database::connect()->table('giftcards')
|
||||
->where('giftcard_number', $giftcardNumber)
|
||||
->get()
|
||||
->getRow();
|
||||
|
||||
return (float) $row->value;
|
||||
}
|
||||
|
||||
public function testCashierCannotForgeGiftcardPaymentTypeWithNegativeAmount(): void
|
||||
{
|
||||
$cashierId = $this->createCashierEmployee();
|
||||
$itemId = $this->createTestItem(HAS_NO_STOCK);
|
||||
$giftcardNumber = $this->createGiftcard(100.00);
|
||||
$this->loginAs($cashierId);
|
||||
$this->seedCartLine(1, '1.00', $itemId);
|
||||
|
||||
$this->post('/sales/addPayment', [
|
||||
'payment_type' => lang('Sales.giftcard') . ':' . $giftcardNumber,
|
||||
'amount_tendered' => '-500',
|
||||
]);
|
||||
|
||||
$payments = Services::session()->get('sales_payments');
|
||||
$this->assertEmpty($payments);
|
||||
$this->assertEqualsWithDelta(100.00, $this->getGiftcardValue($giftcardNumber), 0.001);
|
||||
}
|
||||
|
||||
public function testCashierCanUseLegitimateGiftcardPayment(): void
|
||||
{
|
||||
$cashierId = $this->createCashierEmployee();
|
||||
$itemId = $this->createTestItem(HAS_NO_STOCK);
|
||||
$giftcardNumber = $this->createGiftcard(100.00);
|
||||
$this->loginAs($cashierId);
|
||||
$this->seedCartLine(1, '1.00', $itemId);
|
||||
|
||||
$this->post('/sales/addPayment', [
|
||||
'payment_type' => lang('Sales.giftcard'),
|
||||
'amount_tendered' => (string) $giftcardNumber,
|
||||
]);
|
||||
|
||||
$payments = Services::session()->get('sales_payments');
|
||||
$this->assertNotEmpty($payments);
|
||||
$this->assertArrayHasKey(lang('Sales.giftcard') . ':' . $giftcardNumber, $payments);
|
||||
}
|
||||
|
||||
public function testCashierCannotSubmitNegativeAmountForReferenceCodePayment(): void
|
||||
{
|
||||
$cashierId = $this->createCashierEmployee();
|
||||
$itemId = $this->createTestItem(HAS_NO_STOCK);
|
||||
$this->loginAs($cashierId);
|
||||
$this->seedCartLine(1, '1.00', $itemId);
|
||||
|
||||
$this->post('/sales/addPayment', [
|
||||
'payment_type' => lang('Sales.debit'),
|
||||
'amount_tendered' => '-25',
|
||||
'reference_code' => 'ABC123',
|
||||
]);
|
||||
|
||||
$payments = Services::session()->get('sales_payments');
|
||||
$this->assertEmpty($payments);
|
||||
}
|
||||
|
||||
public function testCashierCanUseLegitimateReferenceCodePayment(): void
|
||||
{
|
||||
$cashierId = $this->createCashierEmployee();
|
||||
$itemId = $this->createTestItem(HAS_NO_STOCK);
|
||||
$this->loginAs($cashierId);
|
||||
$this->seedCartLine(1, '1.00', $itemId);
|
||||
|
||||
$this->post('/sales/addPayment', [
|
||||
'payment_type' => lang('Sales.debit'),
|
||||
'amount_tendered' => '25.00',
|
||||
'reference_code' => 'ABC123',
|
||||
]);
|
||||
|
||||
$payments = Services::session()->get('sales_payments');
|
||||
$this->assertNotEmpty($payments);
|
||||
$this->assertArrayHasKey(lang('Sales.debit'), $payments);
|
||||
$this->assertSame('ABC123', $payments[lang('Sales.debit')]['reference_code']);
|
||||
}
|
||||
|
||||
public function testCashierCannotSubmitNegativeAmountForCashPayment(): void
|
||||
{
|
||||
$cashierId = $this->createCashierEmployee();
|
||||
$itemId = $this->createTestItem(HAS_NO_STOCK);
|
||||
$this->loginAs($cashierId);
|
||||
$this->seedCartLine(1, '1.00', $itemId);
|
||||
|
||||
$this->post('/sales/addPayment', [
|
||||
'payment_type' => lang('Sales.cash'),
|
||||
'amount_tendered' => '-10',
|
||||
]);
|
||||
|
||||
$payments = Services::session()->get('sales_payments');
|
||||
$this->assertEmpty($payments);
|
||||
}
|
||||
|
||||
public function testCashierCanUseLegitimateCashPayment(): void
|
||||
{
|
||||
$cashierId = $this->createCashierEmployee();
|
||||
$itemId = $this->createTestItem(HAS_NO_STOCK);
|
||||
$this->loginAs($cashierId);
|
||||
$this->seedCartLine(1, '1.00', $itemId);
|
||||
|
||||
$this->post('/sales/addPayment', [
|
||||
'payment_type' => lang('Sales.cash'),
|
||||
'amount_tendered' => '10.00',
|
||||
]);
|
||||
|
||||
$payments = Services::session()->get('sales_payments');
|
||||
$this->assertNotEmpty($payments);
|
||||
$this->assertArrayHasKey(lang('Sales.cash'), $payments);
|
||||
}
|
||||
|
||||
public function testPostCompleteRejectsSaleWithInsufficientPayments(): void
|
||||
{
|
||||
$cashierId = $this->createCashierEmployee();
|
||||
$itemId = $this->createTestItem(HAS_NO_STOCK);
|
||||
$this->loginAs($cashierId);
|
||||
$this->seedCartLine(1, '100.00', $itemId);
|
||||
$this->withSession(array_merge($this->session, ['sale_id' => NEW_ENTRY]));
|
||||
|
||||
$salesCountBefore = Database::connect()->table('sales')->countAllResults();
|
||||
|
||||
$this->post('/sales/complete');
|
||||
|
||||
$salesCountAfter = Database::connect()->table('sales')->countAllResults();
|
||||
$this->assertSame($salesCountBefore, $salesCountAfter);
|
||||
}
|
||||
|
||||
public function testPostCompleteAllowsZeroPaymentQuoteCompletion(): void
|
||||
{
|
||||
$cashierId = $this->createCashierEmployee();
|
||||
$itemId = $this->createTestItem(HAS_NO_STOCK);
|
||||
$this->loginAs($cashierId);
|
||||
$this->seedCartLine(1, '100.00', $itemId);
|
||||
$this->withSession(array_merge($this->session, ['sale_id' => NEW_ENTRY, 'sales_mode' => 'sale_quote']));
|
||||
|
||||
$salesCountBefore = Database::connect()->table('sales')->countAllResults();
|
||||
|
||||
$response = $this->post('/sales/complete');
|
||||
|
||||
$salesCountAfter = Database::connect()->table('sales')->countAllResults();
|
||||
$this->assertSame($salesCountBefore + 1, $salesCountAfter);
|
||||
$response->assertDontSee(lang('Sales.amount_due_not_covered'));
|
||||
}
|
||||
|
||||
public function testPostCompleteAllowsZeroPaymentInvoiceCompletion(): void
|
||||
{
|
||||
$cashierId = $this->createCashierEmployee();
|
||||
$itemId = $this->createTestItem(HAS_NO_STOCK);
|
||||
$this->loginAs($cashierId);
|
||||
$this->seedCartLine(1, '100.00', $itemId);
|
||||
$this->withSession(array_merge($this->session, ['sale_id' => NEW_ENTRY, 'sales_mode' => 'sale_invoice']));
|
||||
|
||||
$salesCountBefore = Database::connect()->table('sales')->countAllResults();
|
||||
|
||||
$response = $this->post('/sales/complete');
|
||||
|
||||
$salesCountAfter = Database::connect()->table('sales')->countAllResults();
|
||||
$this->assertSame($salesCountBefore + 1, $salesCountAfter);
|
||||
$response->assertDontSee(lang('Sales.amount_due_not_covered'));
|
||||
}
|
||||
|
||||
public function testRegisterEscapesMaliciousTaxName(): void
|
||||
{
|
||||
$cashierId = $this->createCashierEmployee();
|
||||
|
||||
@@ -81,6 +81,28 @@ class GiftcardTest extends CIUnitTestCase
|
||||
$this->assertEqualsWithDelta(50.00, $this->getGiftcardValue($giftcardNumber), 0.001);
|
||||
}
|
||||
|
||||
public function testDecrementGiftcardValueRejectsNegativeAmount(): void
|
||||
{
|
||||
$giftcardNumber = $this->createGiftcard(100.00);
|
||||
$giftcardModel = model(Giftcard::class);
|
||||
|
||||
$result = $giftcardModel->decrementGiftcardValue((string) $giftcardNumber, -500.00);
|
||||
|
||||
$this->assertFalse($result);
|
||||
$this->assertEqualsWithDelta(100.00, $this->getGiftcardValue($giftcardNumber), 0.001);
|
||||
}
|
||||
|
||||
public function testDecrementGiftcardValueRejectsZeroAmount(): void
|
||||
{
|
||||
$giftcardNumber = $this->createGiftcard(100.00);
|
||||
$giftcardModel = model(Giftcard::class);
|
||||
|
||||
$result = $giftcardModel->decrementGiftcardValue((string) $giftcardNumber, 0.00);
|
||||
|
||||
$this->assertFalse($result);
|
||||
$this->assertEqualsWithDelta(100.00, $this->getGiftcardValue($giftcardNumber), 0.001);
|
||||
}
|
||||
|
||||
public function testDecrementGiftcardValueExactBalanceSucceeds(): void
|
||||
{
|
||||
$giftcardNumber = $this->createGiftcard(60.00);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Tests\Models;
|
||||
|
||||
use App\Models\Sale;
|
||||
use CodeIgniter\Database\Config;
|
||||
use CodeIgniter\Test\CIUnitTestCase;
|
||||
use CodeIgniter\Test\DatabaseTestTrait;
|
||||
use Tests\Support\EmployeeFixtureTrait;
|
||||
@@ -21,16 +22,31 @@ class SaleTest extends CIUnitTestCase
|
||||
|
||||
protected $migrate = true;
|
||||
protected $migrateOnce = true;
|
||||
protected $refresh = true;
|
||||
protected $seedOnce = true;
|
||||
protected $refresh = false;
|
||||
protected $namespace = null;
|
||||
|
||||
private static bool $doneBootstrap = false;
|
||||
|
||||
private const LOCATION_ID = 1;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
if (self::$doneBootstrap === false) {
|
||||
Config::seeder($this->DBGroup)->call('App\Database\Seeds\TestDatabaseBootstrapSeeder');
|
||||
Config::connect($this->DBGroup)->close();
|
||||
|
||||
self::$doneBootstrap = true;
|
||||
}
|
||||
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
protected function createGiftcard(float $value): int
|
||||
{
|
||||
$giftcardNumber = random_int(1000000, 9999999);
|
||||
@@ -157,6 +173,46 @@ class SaleTest extends CIUnitTestCase
|
||||
$this->assertEqualsWithDelta(40.00, $this->getGiftcardValue($giftcardNumber), 0.001);
|
||||
}
|
||||
|
||||
public function testSaveValueDoesNotMatchGiftcardSinkOnSubstringOnly(): void
|
||||
{
|
||||
$employeeId = $this->createEmployee();
|
||||
$giftcardNumber = $this->createGiftcard(100.00);
|
||||
$itemId = $this->createTestItem(HAS_NO_STOCK);
|
||||
|
||||
$saleModel = model(Sale::class);
|
||||
$saleStatus = COMPLETED;
|
||||
$items = $this->buildCartLine($itemId, 1, 60.00);
|
||||
$payments = [
|
||||
0 => [
|
||||
'payment_type' => 'Foo ' . lang('Sales.giftcard') . ':' . $giftcardNumber,
|
||||
'payment_amount' => 60.00,
|
||||
'cash_refund' => 0,
|
||||
'cash_adjustment' => 0,
|
||||
'reference_code' => null,
|
||||
],
|
||||
];
|
||||
$salesTaxes = [[], []];
|
||||
|
||||
$result = $saleModel->save_value(
|
||||
NEW_ENTRY,
|
||||
$saleStatus,
|
||||
$items,
|
||||
NEW_ENTRY,
|
||||
$employeeId,
|
||||
'test sale',
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
SALE_TYPE_POS,
|
||||
$payments,
|
||||
null,
|
||||
$salesTaxes
|
||||
);
|
||||
|
||||
$this->assertGreaterThan(0, $result);
|
||||
$this->assertEqualsWithDelta(100.00, $this->getGiftcardValue($giftcardNumber), 0.001);
|
||||
}
|
||||
|
||||
public function testSaveValueReturnsInsufficientGiftcardBalanceSentinel(): void
|
||||
{
|
||||
$employeeId = $this->createEmployee();
|
||||
|
||||
Reference in new issue
Block a user