Compare commits

...

2 Commits

Author SHA1 Message Date
jekkos
5450404cb2 fix: cast string returns to int in MY_Migration (#4560)
basename() returns string and database column values are strings,
but get_latest_migration() and get_current_version() declare int
return types. PHP 8.0+ enforces strict return types and no longer
silently coerces strings to int, causing a TypeError on fresh
installs.

Fixes #4559

Co-authored-by: Ollama <ollama@steganos.dev>
2026-05-22 16:07:21 +02:00
objecttothis
b7384296c1 Bugfix: Sale search in register not handling trailing space properly (#4557)
* Fix is_valid_receipt method bug

Strings submitted with a trailing space and no number caused an unhandled exception because Sale::exists() expects an int but a string was passed to it.

- Add guards
- Minor PSR refactor

Signed-off-by: objec <objecttothis@gmail.com>

* Address review comments

Signed-off-by: objec <objecttothis@gmail.com>

---------

Signed-off-by: objec <objecttothis@gmail.com>
2026-05-22 01:43:24 +04:00
3 changed files with 14 additions and 14 deletions

View File

@@ -161,7 +161,7 @@ class Sales extends Secure_Controller
'only_bank_transfer'=> false,
'only_wallet' => false,
'only_invoices' => $this->config['invoice_enable'] && $this->request->getGet('only_invoices', FILTER_SANITIZE_NUMBER_INT),
'is_valid_receipt' => $this->sale->is_valid_receipt($search)
'is_valid_receipt' => $this->sale->isValidReceipt($search)
];
// Check if any filter is set in the multiselect dropdown
@@ -198,7 +198,7 @@ class Sales extends Secure_Controller
? $this->request->getGet('term')
: null;
if ($this->sale_lib->get_mode() == 'return' && $this->sale->is_valid_receipt($receipt)) {
if ($this->sale_lib->get_mode() == 'return' && $this->sale->isValidReceipt($receipt)) {
// If a valid receipt or invoice was found the search term will be replaced with a receipt number (POS #)
$suggestions[] = $receipt;
}
@@ -525,7 +525,7 @@ class Sales extends Secure_Controller
$quantity = ($mode == 'return') ? -$quantity : $quantity;
$item_location = $this->sale_lib->get_sale_location();
if ($mode == 'return' && $this->sale->is_valid_receipt($item_id_or_number_or_item_kit_or_receipt)) {
if ($mode == 'return' && $this->sale->isValidReceipt($item_id_or_number_or_item_kit_or_receipt)) {
$this->sale_lib->return_entire_sale($item_id_or_number_or_item_kit_or_receipt);
} elseif ($this->item_kit->is_valid_item_kit($item_id_or_number_or_item_kit_or_receipt)) {
// Add kit item to order if one is assigned

View File

@@ -25,7 +25,7 @@ class MY_Migration extends MigrationRunner
public function get_latest_migration(): int
{
$migrations = $this->findMigrations();
return basename(end($migrations)->version);
return (int) basename(end($migrations)->version);
}
/**
@@ -41,7 +41,7 @@ class MY_Migration extends MigrationRunner
$builder = $db->table('migrations');
$builder->select('version')->orderBy('version', 'DESC')->limit(1);
$result = $builder->get()->getRow();
return $result ? $result->version : 0;
return $result ? (int) $result->version : 0;
}
} catch (\Exception $e) {
// Database not available yet (e.g. fresh install before schema).

View File

@@ -327,7 +327,7 @@ class Sale extends Model
{
$suggestions = [];
if (!$this->is_valid_receipt($search)) {
if (!$this->isValidReceipt($search)) {
$builder = $this->db->table('sales');
$builder->distinct()->select('first_name, last_name');
$builder->join('people', 'people.person_id = sales.customer_id');
@@ -408,21 +408,21 @@ class Sale extends Model
/**
* Checks if valid receipt
*/
public function is_valid_receipt(string|null &$receipt_sale_id): bool // TODO: like the others, maybe this should be an array rather than a delimited string... either that or the parameter name needs to be changed. $receipt_sale_id implies that it's an int.
public function isValidReceipt(string|null &$receiptSaleId): bool // TODO: like the others, maybe this should be an array rather than a delimited string... either that or the parameter name needs to be changed. $receipt_sale_id implies that it's an int.
{
$config = config(OSPOS::class)->settings;
if (!empty($receipt_sale_id)) {
if (!empty($receiptSaleId)) {
// POS #
$pieces = explode(' ', $receipt_sale_id);
$pieces = explode(' ', trim($receiptSaleId));
if (count($pieces) == 2 && preg_match('/(POS)/i', $pieces[0])) {
return $this->exists($pieces[1]);
if (count($pieces) == 2 && strtoupper($pieces[0]) === 'POS' && ctype_digit($pieces[1])) {
return $this->exists((int)$pieces[1]);
} elseif ($config['invoice_enable']) {
$sale_info = $this->get_sale_by_invoice_number($receipt_sale_id);
$saleInfo = $this->get_sale_by_invoice_number($receiptSaleId);
if ($sale_info->getNumRows() > 0) {
$receipt_sale_id = 'POS ' . $sale_info->getRow()->sale_id;
if ($saleInfo->getNumRows() > 0) {
$receiptSaleId = 'POS ' . $saleInfo->getRow()->sale_id;
return true;
}