Use Content-Type application/json for AJAX responses (#4357)

Complete Content-Type application/json fix for all AJAX responses

- Add missing return statements to all ->response->setJSON() calls
- Fix Items.php method calls from JSON() to setJSON()
- Convert echo statements to proper JSON responses
- Ensure consistent Content-Type headers across all controllers
- Fix 46+ instances across 12 controller files
- Change Config.php methods to : ResponseInterface (all return setJSON only):
  - postSaveRewards(), postSaveBarcode(), postSaveReceipt()
  - postSaveInvoice(), postRemoveLogo()
  - Update PHPDoc @return tags

- Change Receivings.php _reload() to : string (only returns view)
- Change Receivings.php methods to : string (all return _reload()):
  - getIndex(), postSelectSupplier(), postChangeMode(), postAdd()
  - postEditItem(), getDeleteItem(), getRemoveSupplier()
  - postComplete(), postRequisitionComplete(), getReceipt(), postCancelReceiving()
- Change postSave() to : ResponseInterface (returns setJSON)
- Update all PHPDoc @return tags

Fix XSS vulnerabilities in sales templates, login, and config pages

This commit addresses 5 XSS vulnerabilities by adding proper escaping
to all user-controlled configuration values in HTML contexts.

Fixed Files:
- app/Views/sales/invoice.php: Escaped company_logo (URL context) and company (HTML)
- app/Views/sales/work_order.php: Escaped company_logo (URL context)
- app/Views/sales/receipt_email.php: Added file path validation and escaping for logo
- app/Views/login.php: Escaped all config values in title, logo src, and alt
- app/Views/configs/info_config.php: Escaped company_logo (URL context)

Security Impact:
- Prevents stored XSS attacks if configuration is compromised
- Defense-in-depth principle applied to administrative interfaces
- Follows OWASP best practices for output encoding

Testing:
- Verified no script execution with XSS payloads in config values
- Confirmed proper escaping in HTML, URL, and file contexts
- All templates render correctly with valid configuration

Severity: High (4 files), Medium-High (1 file)
CVSS Score: ~6.1
CWE: CWE-79 (Improper Neutralization of Input During Web Page Generation)

Fix critical password validation bypass and add unit tests

This commit addresses a critical security vulnerability where the password
minimum length check was performed on the HASHED password (always 60
characters for bcrypt) instead of the actual password before hashing.

Vulnerability Details:
- Original code: strlen($employee_data['password']) >= 8
- This compared the hash length (always 60) instead of raw password
- Impact: Users could set 1-character passwords like "a"
- Severity: Critical (enables brute force attacks on weak passwords)
- CVE-like issue: CWE-307 (Improper Restriction of Excessive Authentication Attempts)

Fix Applied:
- Validate password length BEFORE hashing
- Clear error message when password is too short
- Added unit tests to verify minimum length enforcement
- Regression test to prevent future vulnerability re-introduction

Test Coverage:
- testPasswordMinLength_Rejects7Characters: Verify 7 chars rejected
- testPasswordMinLength_Accepts8Characters: Verify 8 chars accepted
- testPasswordMinLength_RejectsEmptyString: Verify empty rejected
- testPasswordMinLength_RejectsWhitespaceOnly: Verify whitespace rejected
- testPasswordMinLength_AcceptsSpecialCharacters: Verify special chars OK
- testPasswordMinLength_RejectsPreviousBehavior: Regression test for bug

Files Modified:
- app/Controllers/Home.php: Fixed password validation logic
- tests/Controllers/HomeTest.php: Added comprehensive unit tests

Security Impact:
- Enforces 8-character minimum password policy
- Prevents extremely weak passwords that facilitate brute-force attacks
- Critical for credential security and user account protection

Breaking Changes:
- Users with passwords < 8 characters will need to reset their password
- This is the intended security improvement

Severity: Critical
CVSS Score: ~7.5
CWE: CWE-305 (Authentication Bypass by Primary Weakness), CWE-307

Add GitHub Actions workflow to run PHPUnit tests

Move business logic from views to controllers for better separation of concerns

- Move logo URL computation from info_config view to Config::getIndex()
- Move image base64 encoding from receipt_email view to Sales controller
- Improves separation of concerns by keeping business logic in controllers
- Simplifies view templates to only handle presentation

Fix XSS vulnerabilities in report views - escape user-controllable summary data and labels

Fix base64 encoding URL issue in delete payment - properly URL encode base64 string

Fix remaining return type declarations for Sales controller

Fixed additional methods that call _reload():
- postAdd() - returns _reload($data)
- postAddPayment() - returns _reload($data)
- postEditItem() - returns _reload($data)
- postSuspend() - returns _reload($data)
- postSetPaymentType() - returns _reload()

All methods now return ResponseInterface|string to match _reload() signature.
This resolves PHP TypeError errors.
This commit is contained in:
jekkos
2026-03-04 21:42:35 +01:00
committed by GitHub
parent 0858a1c23c
commit 690f43578d
44 changed files with 1354 additions and 884 deletions

33
.github/workflows/opencode.yml vendored Normal file
View File

@@ -0,0 +1,33 @@
name: opencode
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
jobs:
opencode:
if: |
contains(github.event.comment.body, ' /oc') ||
startsWith(github.event.comment.body, '/oc') ||
contains(github.event.comment.body, ' /opencode') ||
startsWith(github.event.comment.body, '/opencode')
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
pull-requests: read
issues: read
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
persist-credentials: false
- name: Run opencode
uses: anomalyco/opencode/github@latest
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
with:
model: anthropic/claude-3-haiku-20240307

118
.github/workflows/phpunit.yml vendored Normal file
View File

@@ -0,0 +1,118 @@
name: PHPUnit Tests
on:
push:
paths:
- '**.php'
- 'spark'
- 'tests/**'
- '.github/workflows/phpunit.yml'
- 'gulpfile.js'
- 'app/Database/**'
pull_request:
paths:
- '**.php'
- 'spark'
- 'tests/**'
- '.github/workflows/phpunit.yml'
- 'gulpfile.js'
- 'app/Database/**'
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
permissions:
contents: read
jobs:
test:
name: PHP ${{ matrix.php-version }} Tests
runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
php-version:
- '8.1'
- '8.2'
- '8.3'
- '8.4'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
extensions: intl, mbstring, mysqli
coverage: none
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Get npm cache directory
run: echo "NPM_CACHE_DIR=$(npm config get cache)" >> $GITHUB_ENV
- name: Cache npm dependencies
uses: actions/cache@v3
with:
path: ${{ env.NPM_CACHE_DIR }}
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Install npm dependencies
run: npm install
- name: Build database.sql
run: npm run gulp build-database
- name: Start MariaDB
run: |
docker run -d --name mysql \
-e MYSQL_ROOT_PASSWORD=root \
-e MYSQL_DATABASE=ospos \
-e MYSQL_USER=admin \
-e MYSQL_PASSWORD=pointofsale \
-v $PWD/app/Database/database.sql:/docker-entrypoint-initdb.d/database.sql \
-p 3306:3306 \
mariadb:10.5
# Wait for MariaDB to be ready
until docker exec mysql mysqladmin ping -h 127.0.0.1 -u root -proot --silent; do
echo "Waiting for MariaDB..."
sleep 2
done
echo "MariaDB is ready!"
- name: Get composer cache directory
run: echo "COMPOSER_CACHE_FILES_DIR=$(composer config cache-files-dir)" >> $GITHUB_ENV
- name: Cache dependencies
uses: actions/cache@v3
with:
path: ${{ env.COMPOSER_CACHE_FILES_DIR }}
key: ${{ runner.os }}-${{ matrix.php-version }}-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-${{ matrix.php-version }}-
${{ runner.os }}-
- name: Install dependencies
run: composer update --ansi --no-interaction
- name: Create .env file
run: cp .env.example .env
- name: Run PHPUnit tests
env:
CI_ENVIRONMENT: testing
MYSQL_HOST_NAME: 127.0.0.1
run: composer test
- name: Stop MariaDB
if: always()
run: docker stop mysql && docker rm mysql

View File

@@ -1,38 +1,23 @@
<?php
/*
* The environment testing is reserved for PHPUnit testing. It has special
* conditions built into the framework at various places to assist with that.
* You cant use it for your development.
*/
/*
|--------------------------------------------------------------------------
| ERROR DISPLAY
| ERROR DISPLAY
|--------------------------------------------------------------------------
| In development, we want to show as many errors as possible to help
| make sure they don't make it to production. And save us hours of
| painful debugging.
*/
*/
error_reporting(E_ALL);
ini_set('display_errors', '1');
/*
|--------------------------------------------------------------------------
| DEBUG BACKTRACES
| DEBUG BACKTRACES
|--------------------------------------------------------------------------
| If true, this constant will tell the error screens to display debug
| backtraces along with the other error information. If you would
| prefer to not see this, set this value to false.
*/
*/
defined('SHOW_DEBUG_BACKTRACE') || define('SHOW_DEBUG_BACKTRACE', true);
/*
|--------------------------------------------------------------------------
| DEBUG MODE
| DEBUG MODE
|--------------------------------------------------------------------------
| Debug mode is an experimental flag that can allow changes throughout
| the system. It's not widely used currently, and may not survive
| release of the framework.
*/
defined('CI_DEBUG') || define('CI_DEBUG', true);
*/
defined('CI_DEBUG') || define('CI_DEBUG', true);

View File

@@ -100,9 +100,25 @@ class Filters extends BaseFilters
* before or after URI patterns.
*
* Example:
* 'isLoggedIn' => ['before' => ['account/*', 'profiles/*']]
* isLoggedIn' => ['before' => ['account/*', 'profiles/*']]
*
* @var array<string, array<string, list<string>>>
*/
public array $filters = [];
/**
* Constructor to conditionally disable CSRF filter in testing environment
*/
public function __construct()
{
// Check for testing environment via env variable or constant
$isTesting = ($_ENV['CI_ENVIRONMENT'] ?? $_SERVER['CI_ENVIRONMENT'] ?? getenv('CI_ENVIRONMENT')) === 'testing'
|| (defined('ENVIRONMENT') && ENVIRONMENT === 'testing');
// Remove CSRF filter from globals in testing environment
if ($isTesting) {
// Remove the 'csrf' key from $globals['before'] while preserving array structure
$this->globals['before'] = array_filter($this->globals['before'], static fn($key) => $key !== 'csrf', ARRAY_FILTER_USE_KEY);
}
}
}

View File

@@ -13,9 +13,9 @@ class Security extends BaseConfig
*
* Protection Method for Cross Site Request Forgery protection.
*
* @var string 'cookie' or 'session'
* @var string|false 'cookie', 'session', or false
*/
public string $csrfProtection = 'session';
public string|false $csrfProtection = 'session';
/**
* --------------------------------------------------------------------------

View File

@@ -3,6 +3,7 @@
namespace App\Controllers;
use App\Models\Attribute;
use CodeIgniter\HTTP\ResponseInterface;
use Config\Services;
require_once('Secure_Controller.php');
@@ -24,19 +25,19 @@ class Attributes extends Secure_Controller
/**
* Gets and sends the main view for Attributes to the browser.
*
* @return void
* @return string
**/
public function getIndex(): void
public function getIndex(): string
{
$data['table_headers'] = get_attribute_definition_manage_table_headers();
echo view('attributes/manage', $data);
return view('attributes/manage', $data);
}
/**
* Returns attribute table data rows. This will be called with AJAX.
*/
public function getSearch(): void
public function getSearch(): ResponseInterface
{
$search = $this->request->getGet('search');
$limit = $this->request->getGet('limit', FILTER_SANITIZE_NUMBER_INT);
@@ -53,15 +54,15 @@ class Attributes extends Secure_Controller
$data_rows[] = get_attribute_definition_data_row($attribute_row);
}
echo json_encode(['total' => $total_rows, 'rows' => $data_rows]);
return $this->response->setJSON(['total' => $total_rows, 'rows' => $data_rows]);
}
/**
* AJAX called function which saves the attribute value sent via POST by using the model save function.
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postSaveAttributeValue(): void
public function postSaveAttributeValue(): ResponseInterface
{
$success = $this->attribute->saveAttributeValue(
html_entity_decode($this->request->getPost('attribute_value')),
@@ -70,32 +71,32 @@ class Attributes extends Secure_Controller
$this->request->getPost('attribute_id', FILTER_SANITIZE_NUMBER_INT) ?? false
);
echo json_encode(['success' => $success != 0]);
return $this->response->setJSON(['success' => $success != 0]);
}
/**
* AJAX called function deleting an attribute value using the model delete function.
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postDeleteDropdownAttributeValue(): void
public function postDeleteDropdownAttributeValue(): ResponseInterface
{
$success = $this->attribute->deleteDropdownAttributeValue(
html_entity_decode($this->request->getPost('attribute_value')),
$this->request->getPost('definition_id', FILTER_SANITIZE_NUMBER_INT)
);
echo json_encode(['success' => $success]);
return $this->response->setJSON(['success' => $success]);
}
/**
* AJAX called function which saves the attribute definition.
*
* @param int $definition_id
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postSaveDefinition(int $definition_id = NO_DEFINITION_ID): void
public function postSaveDefinition(int $definition_id = NO_DEFINITION_ID): ResponseInterface
{
$definition_flags = 0;
@@ -128,20 +129,20 @@ class Attributes extends Secure_Controller
$this->attribute->saveAttributeValue($definition_value, $definition_data['definition_id']);
}
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Attributes.definition_successful_adding') . ' ' . $definition_name,
'id' => $definition_data['definition_id']
]);
} else { // Existing definition
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Attributes.definition_successful_updating') . ' ' . $definition_name,
'id' => $definition_id
]);
}
} else { // Failure
echo json_encode([
return $this->response->setJSON([
'success' => false,
'message' => lang('Attributes.definition_error_adding_updating', [$definition_name]),
'id' => NEW_ENTRY
@@ -152,27 +153,27 @@ class Attributes extends Secure_Controller
/**
*
* @param int $definition_id
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function getSuggestAttribute(int $definition_id): void
public function getSuggestAttribute(int $definition_id): ResponseInterface
{
$suggestions = $this->attribute->get_suggestions($definition_id, html_entity_decode($this->request->getGet('term')));
echo json_encode($suggestions);
return $this->response->setJSON($suggestions);
}
/**
* @param int $row_id
* @return void
* @return ResponseInterface
*/
public function getRow(int $row_id): void
public function getRow(int $row_id): ResponseInterface
{
$attribute_definition_info = $this->attribute->getAttributeInfo($row_id);
$attribute_definition_info->definition_flags = $this->get_attributes($attribute_definition_info->definition_flags);
$data_row = get_attribute_definition_data_row($attribute_definition_info);
echo json_encode($data_row);
return $this->response->setJSON($data_row);
}
/**
@@ -192,9 +193,9 @@ class Attributes extends Secure_Controller
/**
* @param int $definition_id
* @return void
* @return string
*/
public function getView(int $definition_id = NO_DEFINITION_ID): void
public function getView(int $definition_id = NO_DEFINITION_ID): string
{
$info = $this->attribute->getAttributeInfo($definition_id);
foreach (get_object_vars($info) as $property => $value) {
@@ -212,22 +213,22 @@ class Attributes extends Secure_Controller
$selected_flags = $info->definition_flags === '' ? $show_all : $info->definition_flags;
$data['selected_definition_flags'] = $this->get_attributes($selected_flags);
echo view('attributes/form', $data);
return view('attributes/form', $data);
}
/**
* Deletes an attribute definition
* @return void
* @return ResponseInterface
*/
public function postDelete(): void
public function postDelete(): ResponseInterface
{
$attributes_to_delete = $this->request->getPost('ids', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
if($this->attribute->deleteDefinitionList($attributes_to_delete)) {
$message = lang('Attributes.definition_successful_deleted') . ' ' . count($attributes_to_delete) . ' ' . lang('Attributes.definition_one_or_multiple');
echo json_encode(['success' => true, 'message' => $message]);
return $this->response->setJSON(['success' => true, 'message' => $message]);
} else {
echo json_encode(['success' => false, 'message' => lang('Attributes.definition_cannot_be_deleted')]);
return $this->response->setJSON(['success' => false, 'message' => lang('Attributes.definition_cannot_be_deleted')]);
}
}
}

View File

@@ -5,6 +5,7 @@ namespace App\Controllers;
use App\Models\Cashup;
use App\Models\Expense;
use App\Models\Reports\Summary_payments;
use CodeIgniter\HTTP\ResponseInterface;
use Config\OSPOS;
use Config\Services;
@@ -26,22 +27,22 @@ class Cashups extends Secure_Controller
}
/**
* @return void
* @return string
*/
public function getIndex(): void
public function getIndex(): string
{
$data['table_headers'] = get_cashups_manage_table_headers();
// filters that will be loaded in the multiselect dropdown
$data['filters'] = ['is_deleted' => lang('Cashups.is_deleted')];
echo view('cashups/manage', $data);
return view('cashups/manage', $data);
}
/**
* @return void
*/
public function getSearch(): void
public function getSearch(): ResponseInterface
{
$search = $this->request->getGet('search');
$limit = $this->request->getGet('limit', FILTER_SANITIZE_NUMBER_INT);
@@ -64,14 +65,14 @@ class Cashups extends Secure_Controller
$data_rows[] = get_cash_up_data_row($cash_up);
}
echo json_encode(['total' => $total_rows, 'rows' => $data_rows]);
return $this->response->setJSON(['total' => $total_rows, 'rows' => $data_rows]);
}
/**
* @param int $cashup_id
* @return void
* @return string
*/
public function getView(int $cashup_id = NEW_ENTRY): void
public function getView(int $cashup_id = NEW_ENTRY): string
{
$data = [];
@@ -180,26 +181,26 @@ class Cashups extends Secure_Controller
$data['cash_ups_info'] = $cash_ups_info;
echo view("cashups/form", $data);
return view("cashups/form", $data);
}
/**
* @param int $row_id
* @return void
* @return ResponseInterface
*/
public function getRow(int $row_id): void
public function getRow(int $row_id): ResponseInterface
{
$cash_ups_info = $this->cashup->get_info($row_id);
$data_row = get_cash_up_data_row($cash_ups_info);
echo json_encode($data_row);
return $this->response->setJSON($data_row);
}
/**
* @param int $cashup_id
* @return void
* @return ResponseInterface
*/
public function postSave(int $cashup_id = NEW_ENTRY): void
public function postSave(int $cashup_id = NEW_ENTRY): ResponseInterface
{
$open_date = $this->request->getPost('open_date');
$open_date_formatter = date_create_from_format($this->config['dateformat'] . ' ' . $this->config['timeformat'], $open_date);
@@ -227,36 +228,36 @@ class Cashups extends Secure_Controller
if ($this->cashup->save_value($cash_up_data, $cashup_id)) {
// New cashup_id
if ($cashup_id == NEW_ENTRY) {
echo json_encode(['success' => true, 'message' => lang('Cashups.successful_adding'), 'id' => $cash_up_data['cashup_id']]);
return $this->response->setJSON(['success' => true, 'message' => lang('Cashups.successful_adding'), 'id' => $cash_up_data['cashup_id']]);
} else { // Existing Cashup
echo json_encode(['success' => true, 'message' => lang('Cashups.successful_updating'), 'id' => $cashup_id]);
return $this->response->setJSON(['success' => true, 'message' => lang('Cashups.successful_updating'), 'id' => $cashup_id]);
}
} else { // Failure
echo json_encode(['success' => false, 'message' => lang('Cashups.error_adding_updating'), 'id' => NEW_ENTRY]);
return $this->response->setJSON(['success' => false, 'message' => lang('Cashups.error_adding_updating'), 'id' => NEW_ENTRY]);
}
}
/**
* @return void
* @return ResponseInterface
*/
public function postDelete(): void
public function postDelete(): ResponseInterface
{
$cash_ups_to_delete = $this->request->getPost('ids', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
if ($this->cashup->delete_list($cash_ups_to_delete)) {
echo json_encode(['success' => true, 'message' => lang('Cashups.successful_deleted') . ' ' . count($cash_ups_to_delete) . ' ' . lang('Cashups.one_or_multiple'), 'ids' => $cash_ups_to_delete]);
return $this->response->setJSON(['success' => true, 'message' => lang('Cashups.successful_deleted') . ' ' . count($cash_ups_to_delete) . ' ' . lang('Cashups.one_or_multiple'), 'ids' => $cash_ups_to_delete]);
} else {
echo json_encode(['success' => false, 'message' => lang('Cashups.cannot_be_deleted'), 'ids' => $cash_ups_to_delete]);
return $this->response->setJSON(['success' => false, 'message' => lang('Cashups.cannot_be_deleted'), 'ids' => $cash_ups_to_delete]);
}
}
/**
* Calculate the total for cashups. Used in app\Views\cashups\form.php
*
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postAjax_cashup_total(): void
public function postAjax_cashup_total(): ResponseInterface
{
$open_amount_cash = parse_decimals($this->request->getPost('open_amount_cash'));
$transfer_amount_cash = parse_decimals($this->request->getPost('transfer_amount_cash'));
@@ -267,7 +268,7 @@ class Cashups extends Secure_Controller
$total = $this->_calculate_total($open_amount_cash, $transfer_amount_cash, $closed_amount_due, $closed_amount_cash, $closed_amount_card, $closed_amount_check); // TODO: hungarian notation
echo json_encode(['total' => to_currency_no_money($total)]);
return $this->response->setJSON(['total' => to_currency_no_money($total)]);
}
/**

View File

@@ -17,6 +17,7 @@ use App\Models\Stock_location;
use App\Models\Tax;
use CodeIgniter\Database\BaseConnection;
use CodeIgniter\Encryption\EncrypterInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Config\Database;
use Config\OSPOS;
use Config\Services;
@@ -215,8 +216,9 @@ class Config extends Secure_Controller
}
/**
* @return string
*/
public function getIndex(): void
public function getIndex(): string
{
$data['stock_locations'] = $this->stock_location->get_all()->getResultArray();
$data['dinner_tables'] = $this->dinner_table->get_all()->getResultArray();
@@ -224,6 +226,7 @@ class Config extends Secure_Controller
$data['support_barcode'] = $this->barcode_lib->get_list_barcodes();
$data['barcode_fonts'] = $this->barcode_lib->listfonts('fonts');
$data['logo_exists'] = $this->config['company_logo'] != '';
$data['logo_src'] = !empty($this->config['company_logo']) ? base_url('uploads/' . $this->config['company_logo']) : '';
$data['line_sequence_options'] = $this->sale_lib->get_line_sequence_options();
$data['register_mode_options'] = $this->sale_lib->get_register_mode_options();
$data['invoice_type_options'] = $this->sale_lib->get_invoice_type_options();
@@ -272,17 +275,17 @@ class Config extends Secure_Controller
$data['mailchimp']['lists'] = $this->_mailchimp();
echo view('configs/manage', $data);
return view('configs/manage', $data);
}
/**
* Saves company information. Used in app/Views/configs/info_config.php
*
* @throws ReflectionException
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postSaveInfo(): void
public function postSaveInfo(): ResponseInterface
{
$upload_data = $this->upload_logo();
$upload_success = empty($upload_data['error']);
@@ -306,7 +309,7 @@ class Config extends Secure_Controller
$message = lang('Config.saved_' . ($success ? '' : 'un') . 'successfully');
$message = $upload_success ? $message : strip_tags($upload_data['error']);
echo json_encode(['success' => $success, 'message' => $message]);
return $this->response->setJSON(['success' => $success, 'message' => $message]);
}
@@ -358,9 +361,10 @@ class Config extends Secure_Controller
* Saves general configuration. Used in app/Views/configs/general_config.php
*
* @throws ReflectionException
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postSaveGeneral(): void
public function postSaveGeneral(): ResponseInterface
{
$batch_save_data = [
'theme' => $this->request->getPost('theme'),
@@ -407,16 +411,16 @@ class Config extends Secure_Controller
$success = $this->appconfig->batch_save($batch_save_data);
echo json_encode(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
return $this->response->setJSON(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
}
/**
* Checks a number against the currently selected locale. Used in app/Views/configs/locale_config.php
*
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postCheckNumberLocale(): void
public function postCheckNumberLocale(): ResponseInterface
{
$number_locale = $this->request->getPost('number_locale');
$save_number_locale = $this->request->getPost('save_number_locale');
@@ -438,7 +442,7 @@ class Config extends Secure_Controller
$fmt->setSymbol(NumberFormatter::CURRENCY_SYMBOL, $currency_symbol);
$number_local_example = $fmt->format(1234567890.12300);
echo json_encode([
return $this->response->setJSON([
'success' => $number_local_example != false,
'save_number_locale' => $save_number_locale,
'number_locale_example' => $number_local_example,
@@ -451,10 +455,10 @@ class Config extends Secure_Controller
* Saves locale configuration. Used in app/Views/configs/locale_config.php
*
* @throws ReflectionException
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postSaveLocale(): void
public function postSaveLocale(): ResponseInterface
{
$exploded = explode(":", $this->request->getPost('language'));
$batch_save_data = [
@@ -480,17 +484,17 @@ class Config extends Secure_Controller
$success = $this->appconfig->batch_save($batch_save_data);
echo json_encode(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
return $this->response->setJSON(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
}
/**
* Saves email configuration. Used in app/Views/configs/email_config.php
*
* @throws ReflectionException
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postSaveEmail(): void
public function postSaveEmail(): ResponseInterface
{
$password = '';
@@ -511,17 +515,17 @@ class Config extends Secure_Controller
$success = $this->appconfig->batch_save($batch_save_data);
echo json_encode(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
return $this->response->setJSON(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
}
/**
* Saves SMS message configuration. Used in app/Views/configs/message_config.php.
*
* @throws ReflectionException
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postSaveMessage(): void
public function postSaveMessage(): ResponseInterface
{
$password = '';
@@ -538,7 +542,7 @@ class Config extends Secure_Controller
$success = $this->appconfig->batch_save($batch_save_data);
echo json_encode(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
return $this->response->setJSON(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
}
/**
@@ -565,15 +569,15 @@ class Config extends Secure_Controller
/**
* Gets Mailchimp lists when a valid API key is inserted. Used in app/Views/configs/integrations_config.php
*
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postCheckMailchimpApiKey(): void
public function postCheckMailchimpApiKey(): ResponseInterface
{
$lists = $this->_mailchimp($this->request->getPost('mailchimp_api_key'));
$success = count($lists) > 0;
echo json_encode([
return $this->response->setJSON([
'success' => $success,
'message' => lang('Config.mailchimp_key_' . ($success ? '' : 'un') . 'successfully'),
'mailchimp_lists' => $lists
@@ -584,10 +588,10 @@ class Config extends Secure_Controller
* Saves Mailchimp configuration. Used in app/Views/configs/integrations_config.php
*
* @throws ReflectionException
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postSaveMailchimp(): void
public function postSaveMailchimp(): ResponseInterface
{
$api_key = '';
$list_id = '';
@@ -608,56 +612,56 @@ class Config extends Secure_Controller
$success = $this->appconfig->batch_save($batch_save_data);
echo json_encode(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
return $this->response->setJSON(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
}
/**
* Gets all stock locations. Used in app/Views/configs/stock_config.php
*
* @return void
* @return string
* @noinspection PhpUnused
*/
public function getStockLocations(): void
public function getStockLocations(): string
{
$stock_locations = $this->stock_location->get_all()->getResultArray();
echo view('partial/stock_locations', ['stock_locations' => $stock_locations]);
return view('partial/stock_locations', ['stock_locations' => $stock_locations]);
}
/**
* @return void
* @return string
*/
public function getDinnerTables(): void
public function getDinnerTables(): string
{
$dinner_tables = $this->dinner_table->get_all()->getResultArray();
echo view('partial/dinner_tables', ['dinner_tables' => $dinner_tables]);
return view('partial/dinner_tables', ['dinner_tables' => $dinner_tables]);
}
/**
* Gets all tax categories.
*
* @return void
* @return string
*/
public function ajax_tax_categories(): void // TODO: Is this function called anywhere in the code?
public function ajax_tax_categories(): string // TODO: Is this function called anywhere in the code?
{
$tax_categories = $this->tax->get_all_tax_categories()->getResultArray();
echo view('partial/tax_categories', ['tax_categories' => $tax_categories]);
return view('partial/tax_categories', ['tax_categories' => $tax_categories]);
}
/**
* Gets all customer rewards. Used in app/Views/configs/reward_config.php
*
* @return void
* @return string
* @noinspection PhpUnused
*/
public function getCustomerRewards(): void
public function getCustomerRewards(): string
{
$customer_rewards = $this->customer_rewards->get_all()->getResultArray();
echo view('partial/customer_rewards', ['customer_rewards' => $customer_rewards]);
return view('partial/customer_rewards', ['customer_rewards' => $customer_rewards]);
}
/**
@@ -677,10 +681,10 @@ class Config extends Secure_Controller
/**
* Saves stock locations. Used in app/Views/configs/stock_config.php
*
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postSaveLocations(): void
public function postSaveLocations(): ResponseInterface
{
$this->db->transStart();
@@ -712,17 +716,17 @@ class Config extends Secure_Controller
$success = $this->db->transStatus();
echo json_encode(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
return $this->response->setJSON(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
}
/**
* Saves all dinner tables. Used in app/Views/configs/table_config.php
*
* @throws ReflectionException
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postSaveTables(): void
public function postSaveTables(): ResponseInterface
{
$this->db->transStart();
@@ -759,17 +763,17 @@ class Config extends Secure_Controller
$success = $this->db->transStatus();
echo json_encode(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
return $this->response->setJSON(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
}
/**
* Saves tax configuration. Used in app/Views/configs/tax_config.php
*
* @throws ReflectionException
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postSaveTax(): void
public function postSaveTax(): ResponseInterface
{
$default_tax_1_rate = $this->request->getPost('default_tax_1_rate');
$default_tax_2_rate = $this->request->getPost('default_tax_2_rate');
@@ -791,17 +795,17 @@ class Config extends Secure_Controller
$message = lang('Config.saved_' . ($success ? '' : 'un') . 'successfully');
echo json_encode(['success' => $success, 'message' => $message]);
return $this->response->setJSON(['success' => $success, 'message' => $message]);
}
/**
* Saves customer rewards configuration. Used in app/Views/configs/reward_config.php
*
* @throws ReflectionException
* @return void
* @noinspection PhpUnused
*/
public function postSaveRewards(): void
* @throws ReflectionException
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postSaveRewards(): ResponseInterface
{
$this->db->transStart();
@@ -845,17 +849,17 @@ class Config extends Secure_Controller
$success = $this->db->transStatus();
echo json_encode(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
return $this->response->setJSON(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
}
/**
* Saves barcode configuration. Used in app/Views/configs/barcode_config.php
*
* @throws ReflectionException
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postSaveBarcode(): void
public function postSaveBarcode(): ResponseInterface
{
$batch_save_data = [
'barcode_type' => $this->request->getPost('barcode_type'),
@@ -877,17 +881,17 @@ class Config extends Secure_Controller
$success = $this->appconfig->batch_save($batch_save_data);
echo json_encode(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
return $this->response->setJSON(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
}
/**
* Saves receipt configuration. Used in app/Views/configs/receipt_config.php.
*
* @throws ReflectionException
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postSaveReceipt(): void
public function postSaveReceipt(): ResponseInterface
{
$batch_save_data = [
'receipt_template' => $this->request->getPost('receipt_template'),
@@ -912,17 +916,17 @@ class Config extends Secure_Controller
$success = $this->appconfig->batch_save($batch_save_data);
echo json_encode(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
return $this->response->setJSON(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
}
/**
* Saves invoice configuration. Used in app/Views/configs/invoice_config.php.
*
* @throws ReflectionException
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postSaveInvoice(): void
public function postSaveInvoice(): ResponseInterface
{
$batch_save_data = [
'invoice_enable' => $this->request->getPost('invoice_enable') != null,
@@ -953,20 +957,20 @@ class Config extends Secure_Controller
}
}
echo json_encode(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
return $this->response->setJSON(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
}
/**
* Removes the company logo from the database. Used in app/Views/configs/info_config.php.
*
* @return void
* @return ResponseInterface
* @throws ReflectionException
* @noinspection PhpUnused
*/
public function postRemoveLogo(): void
public function postRemoveLogo(): ResponseInterface
{
$success = $this->appconfig->save(['company_logo' => '']);
echo json_encode(['success' => $success]);
return $this->response->setJSON(['success' => $success]);
}
}

View File

@@ -8,6 +8,7 @@ use App\Models\Customer;
use App\Models\Customer_rewards;
use App\Models\Tax_code;
use CodeIgniter\HTTP\DownloadResponse;
use CodeIgniter\HTTP\ResponseInterface;
use Config\OSPOS;
use Config\Services;
use stdClass;
@@ -40,19 +41,20 @@ class Customers extends Persons
}
/**
* @return void
* @return string
*/
public function getIndex(): void
public function getIndex(): string
{
$data['table_headers'] = get_customer_manage_table_headers();
echo view('people/manage', $data);
return view('people/manage', $data);
}
/**
* Gets one row for a customer manage table. This is called using AJAX to update one row.
* @return ResponseInterface
*/
public function getRow(int $row_id): void
public function getRow(int $row_id): ResponseInterface
{
$person = $this->customer->get_info($row_id);
@@ -72,7 +74,7 @@ class Customers extends Persons
$data_row = get_customer_data_row($person, $stats);
echo json_encode($data_row);
return $this->response->setJSON($data_row);
}
@@ -81,7 +83,7 @@ class Customers extends Persons
*
* @return void
*/
public function getSearch(): void
public function getSearch(): ResponseInterface
{
$search = $this->request->getGet('search');
$limit = $this->request->getGet('limit', FILTER_SANITIZE_NUMBER_INT);
@@ -111,35 +113,37 @@ class Customers extends Persons
$data_rows[] = get_customer_data_row($person, $stats);
}
echo json_encode(['total' => $total_rows, 'rows' => $data_rows]);
return $this->response->setJSON(['total' => $total_rows, 'rows' => $data_rows]);
}
/**
* Gives search suggestions based on what is being searched for
* @return ResponseInterface
*/
public function getSuggest(): void
public function getSuggest(): ResponseInterface
{
$search = $this->request->getGet('term');
$suggestions = $this->customer->get_search_suggestions($search);
echo json_encode($suggestions);
return $this->response->setJSON($suggestions);
}
/**
* @return void
* @return ResponseInterface
*/
public function suggest_search(): void
public function suggest_search(): ResponseInterface
{
$search = $this->request->getGet('term');
$suggestions = $this->customer->get_search_suggestions($search, 25, false);
echo json_encode($suggestions);
return $this->response->setJSON($suggestions);
}
/**
* Loads the customer edit form
* @return string
*/
public function getView(int $customer_id = NEW_ENTRY): void
public function getView(int $customer_id = NEW_ENTRY): string
{
// Set default values
if ($customer_id == null) $customer_id = NEW_ENTRY;
@@ -227,13 +231,14 @@ class Customers extends Persons
}
}
echo view("customers/form", $data);
return view("customers/form", $data);
}
/**
* Inserts/updates a customer
* @return ResponseInterface
*/
public function postSave(int $customer_id = NEW_ENTRY): void
public function postSave(int $customer_id = NEW_ENTRY): ResponseInterface
{
$first_name = $this->request->getPost('first_name');
$last_name = $this->request->getPost('last_name');
@@ -288,20 +293,20 @@ class Customers extends Persons
// New customer
if ($customer_id == NEW_ENTRY) {
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Customers.successful_adding') . ' ' . $first_name . ' ' . $last_name,
'id' => $customer_data['person_id']
]);
} else { // Existing customer
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Customers.successful_updating') . ' ' . $first_name . ' ' . $last_name,
'id' => $customer_id
]);
}
} else { // Failure
echo json_encode([
return $this->response->setJSON([
'success' => false,
'message' => lang('Customers.error_adding_updating') . ' ' . $first_name . ' ' . $last_name,
'id' => NEW_ENTRY
@@ -312,36 +317,37 @@ class Customers extends Persons
/**
* Verifies if an email address already exists. Used in app/Views/customers/form.php
*
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postCheckEmail(): void
public function postCheckEmail(): ResponseInterface
{
$email = strtolower($this->request->getPost('email', FILTER_SANITIZE_EMAIL));
$person_id = $this->request->getPost('person_id', FILTER_SANITIZE_NUMBER_INT);
$exists = $this->customer->check_email_exists($email, $person_id);
echo !$exists ? 'true' : 'false';
return $this->response->setJSON(!$exists ? 'true' : 'false');
}
/**
* Verifies if an account number already exists. Used in app/Views/customers/form.php
*
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postCheckAccountNumber(): void
public function postCheckAccountNumber(): ResponseInterface
{
$exists = $this->customer->check_account_number_exists($this->request->getPost('account_number'), $this->request->getPost('person_id', FILTER_SANITIZE_NUMBER_INT));
echo !$exists ? 'true' : 'false';
return $this->response->setJSON(!$exists ? 'true' : 'false');
}
/**
* This deletes customers from the customers table
* @return ResponseInterface
*/
public function postDelete(): void
public function postDelete(): ResponseInterface
{
$customers_to_delete = $this->request->getPost('ids');
$customers_info = $this->customer->get_multiple_info($customers_to_delete);
@@ -358,12 +364,12 @@ class Customers extends Persons
}
if ($count == count($customers_to_delete)) {
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Customers.successful_deleted') . ' ' . $count . ' ' . lang('Customers.one_or_multiple')
]);
} else {
echo json_encode(['success' => false, 'message' => lang('Customers.cannot_be_deleted')]);
return $this->response->setJSON(['success' => false, 'message' => lang('Customers.cannot_be_deleted')]);
}
}
@@ -383,24 +389,24 @@ class Customers extends Persons
/**
* Displays the customer CSV import modal. Used in app/Views/people/manage.php
*
* @return void
* @return string
* @noinspection PhpUnused
*/
public function getCsvImport(): void
public function getCsvImport(): string
{
echo view('customers/form_csv_import');
return view('customers/form_csv_import');
}
/**
* Imports a CSV file containing customers. Used in app/Views/customers/form_csv_import.php
*
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postImportCsvFile(): void
public function postImportCsvFile(): ResponseInterface
{
if ($_FILES['file_path']['error'] != UPLOAD_ERR_OK) {
echo json_encode(['success' => false, 'message' => lang('Customers.csv_import_failed')]);
return $this->response->setJSON(['success' => false, 'message' => lang('Customers.csv_import_failed')]);
} else {
if (($handle = fopen($_FILES['file_path']['tmp_name'], 'r')) !== false) {
// Skip the first row as it's the table description
@@ -467,12 +473,12 @@ class Customers extends Persons
if (count($failCodes) > 0) {
$message = lang('Customers.csv_import_partially_failed', [count($failCodes), implode(', ', $failCodes)]);
echo json_encode(['success' => false, 'message' => $message]);
return $this->response->setJSON(['success' => false, 'message' => $message]);
} else {
echo json_encode(['success' => true, 'message' => lang('Customers.csv_import_success')]);
return $this->response->setJSON(['success' => true, 'message' => lang('Customers.csv_import_success')]);
}
} else {
echo json_encode(['success' => false, 'message' => lang('Customers.csv_import_nodata_wrongformat')]);
return $this->response->setJSON(['success' => false, 'message' => lang('Customers.csv_import_nodata_wrongformat')]);
}
}
}

View File

@@ -3,6 +3,7 @@
namespace App\Controllers;
use App\Models\Module;
use CodeIgniter\HTTP\ResponseInterface;
use Config\Services;
/**
@@ -25,7 +26,7 @@ class Employees extends Persons
*
* @return void
*/
public function getSearch(): void
public function getSearch(): ResponseInterface
{
$search = $this->request->getGet('search');
$limit = $this->request->getGet('limit', FILTER_SANITIZE_NUMBER_INT);
@@ -41,37 +42,38 @@ class Employees extends Persons
$data_rows[] = get_person_data_row($person);
}
echo json_encode(['total' => $total_rows, 'rows' => $data_rows]);
return $this->response->setJSON(['total' => $total_rows, 'rows' => $data_rows]);
}
/**
* AJAX called function gives search suggestions based on what is being searched for.
*
* @return void
* @return ResponseInterface
*/
public function getSuggest(): void
public function getSuggest(): ResponseInterface
{
$search = $this->request->getGet('term');
$suggestions = $this->employee->get_search_suggestions($search, 25, true);
echo json_encode($suggestions);
return $this->response->setJSON($suggestions);
}
/**
* @return void
* @return ResponseInterface
*/
public function suggest_search(): void
public function suggest_search(): ResponseInterface
{
$search = $this->request->getPost('term');
$suggestions = $this->employee->get_search_suggestions($search);
echo json_encode($suggestions);
return $this->response->setJSON($suggestions);
}
/**
* Loads the employee edit form
* @return string
*/
public function getView(int $employee_id = NEW_ENTRY): void
public function getView(int $employee_id = NEW_ENTRY): string
{
$person_info = $this->employee->get_info($employee_id);
foreach (get_object_vars($person_info) as $property => $value) {
@@ -98,13 +100,14 @@ class Employees extends Persons
}
$data['all_subpermissions'] = $permissions;
echo view('employees/form', $data);
return view('employees/form', $data);
}
/**
* Inserts/updates an employee
* @return ResponseInterface
*/
public function postSave(int $employee_id = NEW_ENTRY): void
public function postSave(int $employee_id = NEW_ENTRY): ResponseInterface
{
$first_name = $this->request->getPost('first_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS); // TODO: duplicated code
$last_name = $this->request->getPost('last_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
@@ -163,20 +166,20 @@ class Employees extends Persons
if ($this->employee->save_employee($person_data, $employee_data, $grants_array, $employee_id)) {
// New employee
if ($employee_id == NEW_ENTRY) {
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Employees.successful_adding') . ' ' . $first_name . ' ' . $last_name,
'id' => $employee_data['person_id']
]);
} else { // Existing employee
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Employees.successful_updating') . ' ' . $first_name . ' ' . $last_name,
'id' => $employee_id
]);
}
} else { // Failure
echo json_encode([
return $this->response->setJSON([
'success' => false,
'message' => lang('Employees.error_adding_updating') . ' ' . $first_name . ' ' . $last_name,
'id' => NEW_ENTRY
@@ -186,18 +189,19 @@ class Employees extends Persons
/**
* This deletes employees from the employees table
* @return ResponseInterface
*/
public function postDelete(): void
public function postDelete(): ResponseInterface
{
$employees_to_delete = $this->request->getPost('ids', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
if ($this->employee->delete_list($employees_to_delete)) { // TODO: this is passing a string, but delete_list expects an array
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Employees.successful_deleted') . ' ' . count($employees_to_delete) . ' ' . lang('Employees.one_or_multiple')
]);
} else {
echo json_encode(['success' => false, 'message' => lang('Employees.cannot_be_deleted')]);
return $this->response->setJSON(['success' => false, 'message' => lang('Employees.cannot_be_deleted')]);
}
}
@@ -205,12 +209,12 @@ class Employees extends Persons
* Checks an employee username against the database. Used in app\Views\employees\form.php
*
* @param $employee_id
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function getCheckUsername($employee_id): void
public function getCheckUsername($employee_id): ResponseInterface
{
$exists = $this->employee->username_exists($employee_id, $this->request->getGet('username'));
echo !$exists ? 'true' : 'false';
return $this->response->setJSON(!$exists ? 'true' : 'false');
}
}

View File

@@ -4,6 +4,7 @@ namespace App\Controllers;
use App\Models\Expense;
use App\Models\Expense_category;
use CodeIgniter\HTTP\ResponseInterface;
use Config\OSPOS;
use Config\Services;
@@ -23,7 +24,7 @@ class Expenses extends Secure_Controller
/**
* @return void
*/
public function getIndex(): void
public function getIndex(): string
{
$data['table_headers'] = get_expenses_manage_table_headers();
@@ -37,13 +38,13 @@ class Expenses extends Secure_Controller
'is_deleted' => lang('Expenses.is_deleted')
];
echo view('expenses/manage', $data);
return view('expenses/manage', $data);
}
/**
* @return void
*/
public function getSearch(): void
public function getSearch(): ResponseInterface
{
$search = $this->request->getGet('search');
$limit = $this->request->getGet('limit', FILTER_SANITIZE_NUMBER_INT);
@@ -78,14 +79,14 @@ class Expenses extends Secure_Controller
$data_rows[] = get_expenses_data_last_row($expenses);
}
echo json_encode(['total' => $total_rows, 'rows' => $data_rows, 'payment_summary' => $payment_summary]);
return $this->response->setJSON(['total' => $total_rows, 'rows' => $data_rows, 'payment_summary' => $payment_summary]);
}
/**
* @param int $expense_id
* @return void
*/
public function getView(int $expense_id = NEW_ENTRY): void
public function getView(int $expense_id = NEW_ENTRY): string
{
$data = []; // TODO: Duplicated code
@@ -125,26 +126,26 @@ class Expenses extends Secure_Controller
// Don't allow gift card to be a payment option in a sale transaction edit because it's a complex change
$data['payment_options'] = $this->expense->get_payment_options();
echo view("expenses/form", $data);
return view("expenses/form", $data);
}
/**
* @param int $row_id
* @return void
* @return ResponseInterface
*/
public function getRow(int $row_id): void
public function getRow(int $row_id): ResponseInterface
{
$expense_info = $this->expense->get_info($row_id);
$data_row = get_expenses_data_row($expense_info);
echo json_encode($data_row);
return $this->response->setJSON($data_row);
}
/**
* @param int $expense_id
* @return void
* @return ResponseInterface
*/
public function postSave(int $expense_id = NEW_ENTRY): void
public function postSave(int $expense_id = NEW_ENTRY): ResponseInterface
{
$config = config(OSPOS::class)->settings;
$newdate = $this->request->getPost('date', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
@@ -167,26 +168,26 @@ class Expenses extends Secure_Controller
if ($this->expense->save_value($expense_data, $expense_id)) {
// New Expense
if ($expense_id == NEW_ENTRY) {
echo json_encode(['success' => true, 'message' => lang('Expenses.successful_adding'), 'id' => $expense_data['expense_id']]);
return $this->response->setJSON(['success' => true, 'message' => lang('Expenses.successful_adding'), 'id' => $expense_data['expense_id']]);
} else { // Existing Expense
echo json_encode(['success' => true, 'message' => lang('Expenses.successful_updating'), 'id' => $expense_id]);
return $this->response->setJSON(['success' => true, 'message' => lang('Expenses.successful_updating'), 'id' => $expense_id]);
}
} else { // Failure
echo json_encode(['success' => false, 'message' => lang('Expenses.error_adding_updating'), 'id' => NEW_ENTRY]);
return $this->response->setJSON(['success' => false, 'message' => lang('Expenses.error_adding_updating'), 'id' => NEW_ENTRY]);
}
}
/**
* @return void
* @return ResponseInterface
*/
public function postDelete(): void
public function postDelete(): ResponseInterface
{
$expenses_to_delete = $this->request->getPost('ids', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
if ($this->expense->delete_list($expenses_to_delete)) {
echo json_encode(['success' => true, 'message' => lang('Expenses.successful_deleted') . ' ' . count($expenses_to_delete) . ' ' . lang('Expenses.one_or_multiple'), 'ids' => $expenses_to_delete]);
return $this->response->setJSON(['success' => true, 'message' => lang('Expenses.successful_deleted') . ' ' . count($expenses_to_delete) . ' ' . lang('Expenses.one_or_multiple'), 'ids' => $expenses_to_delete]);
} else {
echo json_encode(['success' => false, 'message' => lang('Expenses.cannot_be_deleted'), 'ids' => $expenses_to_delete]);
return $this->response->setJSON(['success' => false, 'message' => lang('Expenses.cannot_be_deleted'), 'ids' => $expenses_to_delete]);
}
}
}

View File

@@ -3,6 +3,7 @@
namespace App\Controllers;
use App\Models\Expense_category;
use CodeIgniter\HTTP\ResponseInterface;
use Config\Services;
class Expenses_categories extends Secure_Controller // TODO: Is this class ever used?
@@ -19,17 +20,17 @@ class Expenses_categories extends Secure_Controller // TODO: Is this class ev
/**
* @return void
*/
public function getIndex(): void
public function getIndex(): string
{
$data['table_headers'] = get_expense_category_manage_table_headers();
echo view('expenses_categories/manage', $data);
return view('expenses_categories/manage', $data);
}
/**
* Returns expense_category_manage table data rows. This will be called with AJAX.
**/
public function getSearch(): void
public function getSearch(): ResponseInterface
{
$search = $this->request->getGet('search');
$limit = $this->request->getGet('limit', FILTER_SANITIZE_NUMBER_INT);
@@ -45,36 +46,36 @@ class Expenses_categories extends Secure_Controller // TODO: Is this class ev
$data_rows[] = get_expense_category_data_row($expense_category);
}
echo json_encode(['total' => $total_rows, 'rows' => $data_rows]);
return $this->response->setJSON(['total' => $total_rows, 'rows' => $data_rows]);
}
/**
* @param int $row_id
* @return void
*/
public function getRow(int $row_id): void
public function getRow(int $row_id): ResponseInterface
{
$data_row = get_expense_category_data_row($this->expense_category->get_info($row_id));
echo json_encode($data_row);
return $this->response->setJSON($data_row);
}
/**
* @param int $expense_category_id
* @return void
*/
public function getView(int $expense_category_id = NEW_ENTRY): void
public function getView(int $expense_category_id = NEW_ENTRY): string
{
$data['category_info'] = $this->expense_category->get_info($expense_category_id);
echo view("expenses_categories/form", $data);
return view("expenses_categories/form", $data);
}
/**
* @param int $expense_category_id
* @return void
*/
public function postSave(int $expense_category_id = NEW_ENTRY): void
public function postSave(int $expense_category_id = NEW_ENTRY): ResponseInterface
{
$expense_category_data = [
'category_name' => $this->request->getPost('category_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
@@ -84,20 +85,20 @@ class Expenses_categories extends Secure_Controller // TODO: Is this class ev
if ($this->expense_category->save_value($expense_category_data, $expense_category_id)) {
// New expense_category
if ($expense_category_id == NEW_ENTRY) {
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Expenses_categories.successful_adding'),
'id' => $expense_category_data['expense_category_id']
]);
} else { // Existing Expense Category
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Expenses_categories.successful_updating'),
'id' => $expense_category_id
]);
}
} else { // Failure
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Expenses_categories.error_adding_updating') . ' ' . $expense_category_data['category_name'],
'id' => NEW_ENTRY
@@ -108,17 +109,17 @@ class Expenses_categories extends Secure_Controller // TODO: Is this class ev
/**
* @return void
*/
public function postDelete(): void
public function postDelete(): ResponseInterface
{
$expense_category_to_delete = $this->request->getPost('ids', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
if ($this->expense_category->delete_list($expense_category_to_delete)) { // TODO: Convert to ternary notation.
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Expenses_categories.successful_deleted') . ' ' . count($expense_category_to_delete) . ' ' . lang('Expenses_categories.one_or_multiple')
]);
} else {
echo json_encode(['success' => false, 'message' => lang('Expenses_categories.cannot_be_deleted')]);
return $this->response->setJSON(['success' => false, 'message' => lang('Expenses_categories.cannot_be_deleted')]);
}
}
}

View File

@@ -3,6 +3,7 @@
namespace App\Controllers;
use App\Models\Giftcard;
use CodeIgniter\HTTP\ResponseInterface;
use Config\OSPOS;
use Config\Services;
@@ -18,19 +19,19 @@ class Giftcards extends Secure_Controller
}
/**
* @return void
* @return string
*/
public function getIndex(): void
public function getIndex(): string
{
$data['table_headers'] = get_giftcards_manage_table_headers();
echo view('giftcards/manage', $data);
return view('giftcards/manage', $data);
}
/**
* Returns Giftcards table data rows. This will be called with AJAX.
*/
public function getSearch(): void
public function getSearch(): ResponseInterface
{
$search = $this->request->getGet('search');
$limit = $this->request->getGet('limit', FILTER_SANITIZE_NUMBER_INT);
@@ -46,50 +47,50 @@ class Giftcards extends Secure_Controller
$data_rows[] = get_giftcard_data_row($giftcard);
}
echo json_encode(['total' => $total_rows, 'rows' => $data_rows]);
return $this->response->setJSON(['total' => $total_rows, 'rows' => $data_rows]);
}
/**
* Gets search suggestions for giftcards. Used in app\Views\sales\register.php
*
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function getSuggest(): void
public function getSuggest(): ResponseInterface
{
$search = $this->request->getGet('term');
$suggestions = $this->giftcard->get_search_suggestions($search, true);
echo json_encode($suggestions);
return $this->response->setJSON($suggestions);
}
/**
* @return void
* @return ResponseInterface
*/
public function suggest_search(): void
public function suggest_search(): ResponseInterface
{
$search = $this->request->getPost('term');
$suggestions = $this->giftcard->get_search_suggestions($search);
echo json_encode($suggestions);
return $this->response->setJSON($suggestions);
}
/**
* @param int $row_id
* @return void
* @return ResponseInterface
*/
public function getRow(int $row_id): void
public function getRow(int $row_id): ResponseInterface
{
$data_row = get_giftcard_data_row($this->giftcard->get_info($row_id));
echo json_encode($data_row);
return $this->response->setJSON($data_row);
}
/**
* @param int $giftcard_id
* @return void
* @return string
*/
public function getView(int $giftcard_id = NEW_ENTRY): void
public function getView(int $giftcard_id = NEW_ENTRY): string
{
$config = config(OSPOS::class)->settings;
$giftcard_info = $this->giftcard->get_info($giftcard_id);
@@ -106,14 +107,14 @@ class Giftcards extends Secure_Controller
$data['giftcard_id'] = $giftcard_id;
$data['giftcard_value'] = $giftcard_info->value;
echo view("giftcards/form", $data);
return view("giftcards/form", $data);
}
/**
* @param int $giftcard_id
* @return void
* @return ResponseInterface
*/
public function postSave(int $giftcard_id = NEW_ENTRY): void
public function postSave(int $giftcard_id = NEW_ENTRY): ResponseInterface
{
$giftcard_number = $this->request->getPost('giftcard_number', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
@@ -131,20 +132,20 @@ class Giftcards extends Secure_Controller
if ($this->giftcard->save_value($giftcard_data, $giftcard_id)) {
// New giftcard
if ($giftcard_id == NEW_ENTRY) { // TODO: Constant needed
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Giftcards.successful_adding') . ' ' . $giftcard_data['giftcard_number'],
'id' => $giftcard_data['giftcard_id']
]);
} else { // Existing giftcard
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Giftcards.successful_updating') . ' ' . $giftcard_data['giftcard_number'],
'id' => $giftcard_id
]);
}
} else { // Failure
echo json_encode([
return $this->response->setJSON([
'success' => false,
'message' => lang('Giftcards.error_adding_updating') . ' ' . $giftcard_data['giftcard_number'],
'id' => NEW_ENTRY
@@ -158,30 +159,30 @@ class Giftcards extends Secure_Controller
* @return void
* @noinspection PhpUnused
*/
public function postCheckNumberGiftcard(): void
public function postCheckNumberGiftcard(): ResponseInterface
{
$existing_id = $this->request->getPost('giftcard_id', FILTER_SANITIZE_NUMBER_INT);
$giftcard_number = $this->request->getPost('giftcard_number', FILTER_SANITIZE_NUMBER_INT);
$giftcard_id = $this->giftcard->get_giftcard_id($giftcard_number);
$success = ($giftcard_id == (int) $existing_id || !$giftcard_id );
echo $success ? 'true' : 'false';
return $this->response->setJSON($success ? 'true' : 'false');
}
/**
* @return void
* @return ResponseInterface
*/
public function postDelete(): void
public function postDelete(): ResponseInterface
{
$giftcards_to_delete = $this->request->getPost('ids', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
if ($this->giftcard->delete_list($giftcards_to_delete)) {
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Giftcards.successful_deleted') . ' ' . count($giftcards_to_delete) . ' ' . lang('Giftcards.one_or_multiple')
]);
} else {
echo json_encode(['success' => false, 'message' => lang('Giftcards.cannot_be_deleted')]);
return $this->response->setJSON(['success' => false, 'message' => lang('Giftcards.cannot_be_deleted')]);
}
}
}

View File

@@ -3,6 +3,7 @@
namespace App\Controllers;
use CodeIgniter\HTTP\RedirectResponse;
use CodeIgniter\HTTP\ResponseInterface;
class Home extends Secure_Controller
{
@@ -12,12 +13,12 @@ class Home extends Secure_Controller
}
/**
* @return void
* @return string
*/
public function getIndex(): void
public function getIndex(): string
{
$logged_in = $this->employee->is_logged_in();
echo view('home/home');
return view('home/home');
}
/**
@@ -35,9 +36,10 @@ class Home extends Secure_Controller
/**
* Load "change employee password" form
*
* @return string
* @noinspection PhpUnused
*/
public function getChangePassword(int $employee_id = -1): void // TODO: Replace -1 with a constant
public function getChangePassword(int $employee_id = -1): string // TODO: Replace -1 with a constant
{
$person_info = $this->employee->get_info($employee_id);
foreach (get_object_vars($person_info) as $property => $value) {
@@ -45,44 +47,57 @@ class Home extends Secure_Controller
}
$data['person_info'] = $person_info;
echo view('home/form_change_password', $data);
return view('home/form_change_password', $data);
}
/**
* Change employee password
*
* @return ResponseInterface
*/
public function postSave(int $employee_id = -1): void // TODO: Replace -1 with a constant
public function postSave(int $employee_id = -1): ResponseInterface // TODO: Replace -1 with a constant
{
if (!empty($this->request->getPost('current_password')) && $employee_id != -1) {
if ($this->employee->check_password($this->request->getPost('username', FILTER_SANITIZE_FULL_SPECIAL_CHARS), $this->request->getPost('current_password'))) {
// Validate password length BEFORE hashing
$new_password = $this->request->getPost('password');
if (strlen($new_password) < 8) {
return $this->response->setJSON([
'success' => false,
'message' => lang('Employees.password_minlength'),
'id' => -1
]);
}
$employee_data = [
'username' => $this->request->getPost('username', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
'password' => password_hash($this->request->getPost('password'), PASSWORD_DEFAULT),
'password' => password_hash($new_password, PASSWORD_DEFAULT),
'hash_version' => 2
];
if ($this->employee->change_password($employee_data, $employee_id) && strlen($employee_data['password']) >= 8) {
echo json_encode([
if ($this->employee->change_password($employee_data, $employee_id)) {
return $this->response->setJSON([
'success' => true,
'message' => lang('Employees.successful_change_password'),
'id' => $employee_id
]);
} else { // Failure // TODO: Replace -1 with constant
echo json_encode([
return $this->response->setJSON([
'success' => false,
'message' => lang('Employees.unsuccessful_change_password'),
'id' => -1
]);
}
} else { // TODO: Replace -1 with constant
echo json_encode([
return $this->response->setJSON([
'success' => false,
'message' => lang('Employees.current_password_invalid'),
'id' => -1
]);
}
} else { // TODO: Replace -1 with constant
echo json_encode([
return $this->response->setJSON([
'success' => false,
'message' => lang('Employees.current_password_invalid'),
'id' => -1

View File

@@ -7,6 +7,7 @@ use App\Libraries\Barcode_lib;
use App\Models\Item;
use App\Models\Item_kit;
use App\Models\Item_kit_items;
use CodeIgniter\HTTP\ResponseInterface;
use Config\Services;
class Item_kits extends Secure_Controller
@@ -59,19 +60,19 @@ class Item_kits extends Secure_Controller
}
/**
* @return void
* @return string
*/
public function getIndex(): void
public function getIndex(): string
{
$data['table_headers'] = get_item_kits_manage_table_headers();
echo view('item_kits/manage', $data);
return view('item_kits/manage', $data);
}
/**
* Returns Item_kit table data rows. This will be called with AJAX.
*/
public function getSearch(): void
public function getSearch(): ResponseInterface
{
$search = $this->request->getGet('search') ?? '';
$limit = $this->request->getGet('limit', FILTER_SANITIZE_NUMBER_INT);
@@ -89,37 +90,37 @@ class Item_kits extends Secure_Controller
$data_rows[] = get_item_kit_data_row($item_kit);
}
echo json_encode(['total' => $total_rows, 'rows' => $data_rows]);
return $this->response->setJSON(['total' => $total_rows, 'rows' => $data_rows]);
}
/**
* @return void
* @return ResponseInterface
*/
public function suggest_search(): void
public function suggest_search(): ResponseInterface
{
$search = $this->request->getPost('term');
$suggestions = $this->item_kit->get_search_suggestions($search);
echo json_encode($suggestions);
return $this->response->setJSON($suggestions);
}
/**
* @param int $row_id
* @return void
* @return ResponseInterface
*/
public function getRow(int $row_id): void
public function getRow(int $row_id): ResponseInterface
{
// Calculate the total cost and retail price of the Kit, so it can be added to the table refresh
$item_kit = $this->_add_totals_to_item_kit($this->item_kit->get_info($row_id));
echo json_encode(get_item_kit_data_row($item_kit));
return $this->response->setJSON(get_item_kit_data_row($item_kit));
}
/**
* @param int $item_kit_id
* @return void
* @return string
*/
public function getView(int $item_kit_id = NEW_ENTRY): void
public function getView(int $item_kit_id = NEW_ENTRY): string
{
$info = $this->item_kit->get_info($item_kit_id);
@@ -153,14 +154,14 @@ class Item_kits extends Secure_Controller
$data['selected_kit_item_id'] = $info->kit_item_id;
$data['selected_kit_item'] = ($item_kit_id > 0 && isset($info->kit_item_id)) ? $info->item_name : '';
echo view("item_kits/form", $data);
return view("item_kits/form", $data);
}
/**
* @param int $item_kit_id
* @return void
* @return ResponseInterface
*/
public function postSave(int $item_kit_id = NEW_ENTRY): void
public function postSave(int $item_kit_id = NEW_ENTRY): ResponseInterface
{
$item_kit_data = [
'name' => $this->request->getPost('name'),
@@ -201,20 +202,20 @@ class Item_kits extends Secure_Controller
}
if ($new_item) {
echo json_encode([
return $this->response->setJSON([
'success' => $success,
'message' => lang('Item_kits.successful_adding') . ' ' . $item_kit_data['name'],
'id' => $item_kit_id
]);
} else {
echo json_encode([
return $this->response->setJSON([
'success' => $success,
'message' => lang('Item_kits.successful_updating') . ' ' . $item_kit_data['name'],
'id' => $item_kit_id
]);
}
} else { // Failure
echo json_encode([
return $this->response->setJSON([
'success' => false,
'message' => lang('Item_kits.error_adding_updating') . ' ' . $item_kit_data['name'],
'id' => NEW_ENTRY
@@ -223,42 +224,42 @@ class Item_kits extends Secure_Controller
}
/**
* @return void
* @return ResponseInterface
*/
public function postDelete(): void
public function postDelete(): ResponseInterface
{
$item_kits_to_delete = $this->request->getPost('ids', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
if ($this->item_kit->delete_list($item_kits_to_delete)) {
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Item_kits.successful_deleted') . ' ' . count($item_kits_to_delete) . ' ' . lang('Item_kits.one_or_multiple')
]);
} else {
echo json_encode(['success' => false, 'message' => lang('Item_kits.cannot_be_deleted')]);
return $this->response->setJSON(['success' => false, 'message' => lang('Item_kits.cannot_be_deleted')]);
}
}
/**
* Checks the validity of the item kit number. Used in app/Views/item_kits/form.php
*
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postCheckItemNumber(): void
public function postCheckItemNumber(): ResponseInterface
{
$exists = $this->item_kit->item_number_exists($this->request->getPost('item_kit_number', FILTER_SANITIZE_FULL_SPECIAL_CHARS), $this->request->getPost('item_kit_id', FILTER_SANITIZE_NUMBER_INT));
echo !$exists ? 'true' : 'false';
return $this->response->setJSON(!$exists ? 'true' : 'false');
}
/**
* AJAX called function that generates barcodes for selected item_kits.
*
* @param string $item_kit_ids Colon separated list of item_kit_id values to generate barcodes for.
* @return void
* @return string
* @noinspection PhpUnused
*/
public function getGenerateBarcodes(string $item_kit_ids): void
public function getGenerateBarcodes(string $item_kit_ids): string
{
$barcode_lib = new Barcode_lib();
$result = [];
@@ -289,6 +290,6 @@ class Item_kits extends Secure_Controller
$data['barcode_config'] = $barcode_config;
// Display barcodes
echo view("barcodes/barcode_sheet", $data);
return view("barcodes/barcode_sheet", $data);
}
}

View File

@@ -15,6 +15,7 @@ use App\Models\Stock_location;
use App\Models\Supplier;
use App\Models\Tax_category;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Images\Handlers\BaseHandler;
use CodeIgniter\HTTP\DownloadResponse;
use Config\OSPOS;
@@ -65,9 +66,9 @@ class Items extends Secure_Controller
}
/**
* @return void
* @return string
*/
public function getIndex(): void
public function getIndex(): string
{
$this->session->set('allow_temp_items', 0);
@@ -86,14 +87,14 @@ class Items extends Secure_Controller
'temporary' => lang('Items.temp')
];
echo view('items/manage', $data);
return view('items/manage', $data);
}
/**
* Returns Items table data rows. This will be called with AJAX.
* @noinspection PhpUnused
**/
public function getSearch(): void
public function getSearch(): ResponseInterface
{
$search = $this->request->getGet('search');
$limit = $this->request->getGet('limit', FILTER_SANITIZE_NUMBER_INT);
@@ -134,16 +135,16 @@ class Items extends Secure_Controller
}
}
echo json_encode(['total' => $total_rows, 'rows' => $data_rows]);
return $this->response->setJSON(['total' => $total_rows, 'rows' => $data_rows]);
}
/**
* AJAX function. Processes thumbnail of image. Called via tabular_helper
* @param string $pic_filename
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function getPicThumb(string $pic_filename): void
public function getPicThumb(string $pic_filename): ResponseInterface
{
helper('file');
@@ -164,15 +165,17 @@ class Items extends Secure_Controller
$this->response->setContentType(mime_content_type($thumb_path));
$this->response->setBody(file_get_contents($thumb_path));
$this->response->send();
}
return $this->response;
}
/**
* Gives search suggestions based on what is being searched for
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function suggest_search(): void
public function suggest_search(): ResponseInterface
{
$options = [
'search_custom' => $this->request->getPost('search_custom'),
@@ -182,71 +185,73 @@ class Items extends Secure_Controller
$search = $this->request->getPost('term');
$suggestions = $this->item->get_search_suggestions($search, $options);
echo json_encode($suggestions);
return $this->response->setJSON($suggestions);
}
/**
* AJAX Function used to get search suggestions from the model and return them in JSON format
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function getSuggest(): void
public function getSuggest(): ResponseInterface
{
$search = $this->request->getGet('term');
$suggestions = $this->item->get_search_suggestions($search, ['search_custom' => false, 'is_deleted' => false], true);
echo json_encode($suggestions);
return $this->response->setJSON($suggestions);
}
/**
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function getSuggestLowSell(): void
public function getSuggestLowSell(): ResponseInterface
{
$suggestions = $this->item->get_low_sell_suggestions($this->request->getPostGet('name'));
echo json_encode($suggestions);
return $this->response->setJSON($suggestions);
}
/**
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function getSuggestKits(): void
public function getSuggestKits(): ResponseInterface
{
$suggestions = $this->item->get_kit_search_suggestions($this->request->getGet('term'), ['search_custom' => false, 'is_deleted' => false], true);
echo json_encode($suggestions);
return $this->response->setJSON($suggestions);
}
/**
* Gives search suggestions based on what is being searched for. Called from the view.
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function getSuggestCategory(): void
public function getSuggestCategory(): ResponseInterface
{
$suggestions = $this->item->get_category_suggestions($this->request->getGet('term'));
echo json_encode($suggestions);
return $this->response->setJSON($suggestions);
}
/**
* Gives search suggestions based on what is being searched for.
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function getSuggestLocation(): void
public function getSuggestLocation(): ResponseInterface
{
$suggestions = $this->item->get_location_suggestions($this->request->getGet('term'));
echo json_encode($suggestions);
return $this->response->setJSON($suggestions);
}
/**
* @param string $item_ids
* @return void
* @return ResponseInterface
*/
public function getRow(string $item_ids): void // TODO: An array would be better for parameter.
public function getRow(string $item_ids): ResponseInterface // TODO: An array would be better for parameter.
{
$item_infos = $this->item->get_multiple_info(explode(':', $item_ids), $this->item_lib->get_item_location());
@@ -256,14 +261,14 @@ class Items extends Secure_Controller
$result[$item_info->item_id] = get_item_data_row($item_info);
}
echo json_encode($result);
return $this->response->setJSON($result);
}
/**
* @param int $item_id
* @return void
* @return string
*/
public function getView(int $item_id = NEW_ENTRY): void // TODO: Long function. Perhaps we need to refactor out some methods.
public function getView(int $item_id = NEW_ENTRY): string // TODO: Long function. Perhaps we need to refactor out some methods.
{
$item_id ??= NEW_ENTRY;
@@ -395,17 +400,17 @@ class Items extends Secure_Controller
$data['selected_low_sell_item'] = '';
}
echo view('items/form', $data);
return view('items/form', $data);
}
/**
* AJAX called function which returns the update inventory form view for an item
*
* @param int $item_id
* @return void
* @return string
* @noinspection PhpUnused
*/
public function getInventory(int $item_id = NEW_ENTRY): void
public function getInventory(int $item_id = NEW_ENTRY): string
{
$item_info = $this->item->get_info($item_id); // TODO: Duplicate code
@@ -424,15 +429,15 @@ class Items extends Secure_Controller
$data['item_quantities'][$location['location_id']] = $quantity;
}
echo view('items/form_inventory', $data);
return view('items/form_inventory', $data);
}
/**
* @param int $item_id
* @return void
* @return string
* @noinspection PhpUnused
*/
public function getCountDetails(int $item_id = NEW_ENTRY): void
public function getCountDetails(int $item_id = NEW_ENTRY): string
{
$item_info = $this->item->get_info($item_id); // TODO: Duplicate code
@@ -451,17 +456,17 @@ class Items extends Secure_Controller
$data['item_quantities'][$location['location_id']] = $quantity;
}
echo view('items/form_count_details', $data);
return view('items/form_count_details', $data);
}
/**
* AJAX called function that generates barcodes for selected items.
*
* @param string $item_ids Colon separated list of item_id values to generate barcodes for.
* @return void
* @return string
* @noinspection PhpUnused
*/
public function getGenerateBarcodes(string $item_ids): void // TODO: Passing these through as a string instead of an array limits the contents of the item_ids. Perhaps a better approach would to serialize as JSON in an array and pass through post variables?
public function getGenerateBarcodes(string $item_ids): string // TODO: Passing these through as a string instead of an array limits the contents of the item_ids. Perhaps a better approach would to serialize as JSON in an array and pass through post variables?
{
$item_ids = explode(':', $item_ids);
$result = $this->item->get_multiple_info($item_ids, $this->item_lib->get_item_location())->getResultArray();
@@ -477,16 +482,16 @@ class Items extends Secure_Controller
}
$data['items'] = $result;
echo view('barcodes/barcode_sheet', $data);
return view('barcodes/barcode_sheet', $data);
}
/**
* Gathers attribute value information for an item and returns it in a view.
*
* @param int $item_id
* @return void
* @return string
*/
public function getAttributes(int $item_id = NEW_ENTRY): void
public function getAttributes(int $item_id = NEW_ENTRY): string
{
$data['item_id'] = $item_id;
$definition_ids = json_decode($this->request->getGet('definition_ids') ?? '', true);
@@ -514,15 +519,15 @@ class Items extends Secure_Controller
unset($data['definition_names'][$definition_id]);
}
echo view('attributes/item', $data);
return view('attributes/item', $data);
}
/**
* @param int $item_id
* @return void
* @return string
* @noinspection PhpUnused
*/
public function postAttributes(int $item_id = NEW_ENTRY): void
public function postAttributes(int $item_id = NEW_ENTRY): string
{
$data['item_id'] = $item_id;
$definition_ids = json_decode($this->request->getPost('definition_ids'), true);
@@ -550,16 +555,16 @@ class Items extends Secure_Controller
unset($data['definition_names'][$definition_id]);
}
echo view('attributes/item', $data);
return view('attributes/item', $data);
}
/**
* Edit multiple items. Used in app/Views/items/manage.php
*
* @return void
* @return string
* @noinspection PhpUnused
*/
public function getBulkEdit(): void
public function getBulkEdit(): string
{
$suppliers = ['' => lang('Items.none')];
@@ -580,14 +585,15 @@ class Items extends Secure_Controller
0 => lang('Items.change_all_to_unserialized')
];
echo view('items/form_bulk', $data);
return view('items/form_bulk', $data);
}
/**
* @param int $item_id
* @return ResponseInterface
* @throws ReflectionException
*/
public function postSave(int $item_id = NEW_ENTRY): void
public function postSave(int $item_id = NEW_ENTRY): ResponseInterface
{
$upload_data = $this->upload_image();
$upload_success = empty($upload_data['error']);
@@ -717,16 +723,16 @@ class Items extends Secure_Controller
if ($success && $upload_success) {
$message = lang('Items.successful_' . ($new_item ? 'adding' : 'updating')) . ' ' . $item_data['name'];
echo json_encode(['success' => true, 'message' => $message, 'id' => $item_id]);
return $this->response->setJSON(['success' => true, 'message' => $message, 'id' => $item_id]);
} else {
$message = $upload_success ? lang('Items.error_adding_updating') . ' ' . $item_data['name'] : strip_tags($upload_data['error']);
echo json_encode(['success' => false, 'message' => $message, 'id' => $item_id]);
return $this->response->setJSON(['success' => false, 'message' => $message, 'id' => $item_id]);
}
} else {
$message = lang('Items.error_adding_updating') . ' ' . $item_data['name'];
echo json_encode(['success' => false, 'message' => $message, 'id' => NEW_ENTRY]);
return $this->response->setJSON(['success' => false, 'message' => $message, 'id' => NEW_ENTRY]);
}
}
@@ -777,49 +783,51 @@ class Items extends Secure_Controller
/**
* Ajax call to check to see if the item number, a.k.a. barcode, is already used by another item
* If it exists then that is an error condition so return true for "error found"
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postCheckItemNumber(): void
public function postCheckItemNumber(): ResponseInterface
{
$exists = $this->item->item_number_exists($this->request->getPost('item_number'), $this->request->getPost('item_id'));
echo !$exists ? 'true' : 'false';
return $this->response->setJSON(!$exists ? 'true' : 'false');
}
/**
* Checks to see if an item kit with the same name as the item already exists.
*
* @return void
* @return ResponseInterface
*/
public function check_kit_exists(): void // TODO: This function appears to be never called in the code. Need to confirm.
public function check_kit_exists(): ResponseInterface // TODO: This function appears to be never called in the code. Need to confirm.
{
if ($this->request->getPost('item_number') === NEW_ENTRY) {
$exists = $this->item_kit->item_kit_exists_for_name($this->request->getPost('name')); // TODO: item_kit_exists_for_name doesn't exist in Item_kit. I looked at the blame and it appears to have never existed.
} else {
$exists = false;
}
echo !$exists ? 'true' : 'false';
return $this->response->setJSON(!$exists ? 'true' : 'false');
}
/**
* @param $item_id
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function getRemoveLogo($item_id): void
public function getRemoveLogo($item_id): ResponseInterface
{
$item_data = ['pic_filename' => null];
$result = $this->item->save_value($item_data, $item_id);
echo json_encode(['success' => $result]);
return $this->response->setJSON(['success' => $result]);
}
/**
* @return ResponseInterface
* @throws ReflectionException
* @noinspection PhpUnused
*/
public function postSaveInventory($item_id = NEW_ENTRY): void
public function postSaveInventory($item_id = NEW_ENTRY): ResponseInterface
{
$employee_id = $this->employee->get_logged_in_employee_info()->person_id;
$cur_item_info = $this->item->get_info($item_id);
@@ -847,19 +855,19 @@ class Items extends Secure_Controller
if ($this->item_quantity->save_value($item_quantity_data, $item_id, $location_id)) {
$message = lang('Items.successful_updating') . " $cur_item_info->name";
echo json_encode(['success' => true, 'message' => $message, 'id' => $item_id]);
return $this->response->setJSON(['success' => true, 'message' => $message, 'id' => $item_id]);
} else {
$message = lang('Items.error_adding_updating') . " $cur_item_info->name";
echo json_encode(['success' => false, 'message' => $message, 'id' => NEW_ENTRY]);
return $this->response->setJSON(['success' => false, 'message' => $message, 'id' => NEW_ENTRY]);
}
}
/**
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postBulkUpdate(): void
public function postBulkUpdate(): ResponseInterface
{
$items_to_update = $this->request->getPost('item_ids');
$item_data = [];
@@ -891,23 +899,24 @@ class Items extends Secure_Controller
$this->item_taxes->save_multiple($items_taxes_data, $items_to_update);
}
echo json_encode(['success' => true, 'message' => lang('Items.successful_bulk_edit'), 'id' => $items_to_update]);
return $this->response->setJSON(['success' => true, 'message' => lang('Items.successful_bulk_edit'), 'id' => $items_to_update]);
} else {
echo json_encode(['success' => false, 'message' => lang('Items.error_updating_multiple')]);
return $this->response->setJSON(['success' => false, 'message' => lang('Items.error_updating_multiple')]);
}
}
/**
* @return ResponseInterface
*/
public function postDelete(): void
public function postDelete(): ResponseInterface
{
$items_to_delete = $this->request->getPost('ids');
if ($this->item->delete_list($items_to_delete)) {
$message = lang('Items.successful_deleted') . ' ' . count($items_to_delete) . ' ' . lang('Items.one_or_multiple');
echo json_encode(['success' => true, 'message' => $message]);
return $this->response->setJSON(['success' => true, 'message' => $message]);
} else {
echo json_encode(['success' => false, 'message' => lang('Items.cannot_be_deleted')]);
return $this->response->setJSON(['success' => false, 'message' => lang('Items.cannot_be_deleted')]);
}
}
@@ -929,25 +938,26 @@ class Items extends Secure_Controller
}
/**
* @return void
* @return string
* @noinspection PhpUnused
*/
public function getCsvImport(): void
public function getCsvImport(): string
{
echo view('items/form_csv_import');
return view('items/form_csv_import');
}
/**
* Imports items from CSV formatted file.
* @return ResponseInterface
* @throws ReflectionException
* @noinspection PhpUnused
*/
public function postImportCsvFile(): void
public function postImportCsvFile(): ResponseInterface
{
helper('importfile_helper');
try {
if ($_FILES['file_path']['error'] !== UPLOAD_ERR_OK) {
echo json_encode(['success' => false, 'message' => lang('Items.csv_import_failed')]);
return $this->response->setJSON(['success' => false, 'message' => lang('Items.csv_import_failed')]);
} else {
if (file_exists($_FILES['file_path']['tmp_name'])) {
set_time_limit(240);
@@ -1037,19 +1047,18 @@ class Items extends Secure_Controller
if (count($failCodes) > 0) {
$message = lang('Items.csv_import_partially_failed', [count($failCodes), implode(', ', $failCodes)]);
$db->transRollback();
echo json_encode(['success' => false, 'message' => $message]);
return $this->response->setJSON(['success' => false, 'message' => $message]);
} else {
$db->transCommit();
echo json_encode(['success' => true, 'message' => lang('Items.csv_import_success')]);
return $this->response->setJSON(['success' => true, 'message' => lang('Items.csv_import_success')]);
}
} else {
echo json_encode(['success' => false, 'message' => lang('Items.csv_import_nodata_wrongformat')]);
return $this->response->setJSON(['success' => false, 'message' => lang('Items.csv_import_nodata_wrongformat')]);
}
}
} catch (Exception $e) {
echo json_encode(['success' => false, 'message' => $e->getMessage()]);
return;
return $this->response->setJSON(['success' => false, 'message' => $e->getMessage()]);
}
}

View File

@@ -5,6 +5,7 @@ namespace App\Controllers;
use App\Libraries\Sms_lib;
use App\Models\Person;
use CodeIgniter\HTTP\ResponseInterface;
class Messages extends Secure_Controller
{
@@ -18,18 +19,18 @@ class Messages extends Secure_Controller
}
/**
* @return void
* @return string
*/
public function getIndex(): void
public function getIndex(): string
{
echo view('messages/sms');
return view('messages/sms');
}
/**
* @param int $person_id
* @return void
* @return string
*/
public function getView(int $person_id = NEW_ENTRY): void
public function getView(int $person_id = NEW_ENTRY): string
{
$person = model(Person::class);
$info = $person->get_info($person_id);
@@ -39,13 +40,13 @@ class Messages extends Secure_Controller
}
$data['person_info'] = $info;
echo view('messages/form_sms', $data);
return view('messages/form_sms', $data);
}
/**
* @return void
* @return ResponseInterface
*/
public function send(): void
public function send(): ResponseInterface
{
$phone = $this->request->getPost('phone', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$message = $this->request->getPost('message', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
@@ -53,9 +54,9 @@ class Messages extends Secure_Controller
$response = $this->sms_lib->sendSMS($phone, $message);
if ($response) {
echo json_encode(['success' => true, 'message' => lang('Messages.successfully_sent') . ' ' . esc($phone)]);
return $this->response->setJSON(['success' => true, 'message' => lang('Messages.successfully_sent') . ' ' . esc($phone)]);
} else {
echo json_encode(['success' => false, 'message' => lang('Messages.unsuccessfully_sent') . ' ' . esc($phone)]);
return $this->response->setJSON(['success' => false, 'message' => lang('Messages.unsuccessfully_sent') . ' ' . esc($phone)]);
}
}
@@ -63,10 +64,10 @@ class Messages extends Secure_Controller
* Sends an SMS message to a user. Used in app/Views/messages/form_sms.php.
*
* @param int $person_id
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function send_form(int $person_id = NEW_ENTRY): void
public function send_form(int $person_id = NEW_ENTRY): ResponseInterface
{
$phone = $this->request->getPost('phone', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$message = $this->request->getPost('message', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
@@ -74,13 +75,13 @@ class Messages extends Secure_Controller
$response = $this->sms_lib->sendSMS($phone, $message);
if ($response) {
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Messages.successfully_sent') . ' ' . esc($phone),
'person_id' => $person_id
]);
} else {
echo json_encode([
return $this->response->setJSON([
'success' => false,
'message' => lang('Messages.unsuccessfully_sent') . ' ' . esc($phone),
'person_id' => NEW_ENTRY

View File

@@ -3,6 +3,7 @@
namespace App\Controllers;
use App\Models\Module;
use CodeIgniter\HTTP\ResponseInterface;
/**
* Part of the grants mechanism to restrict access to modules that the user doesn't have permission for.
@@ -22,13 +23,13 @@ class No_access extends BaseController
/**
* @param string $module_id
* @param string $permission_id
* @return void
* @return string
*/
public function getIndex(string $module_id = '', string $permission_id = ''): void
public function getIndex(string $module_id = '', string $permission_id = ''): string
{
$data['module_name'] = $this->module->get_module_name($module_id);
$data['permission_id'] = $permission_id;
echo view('no_access', $data);
return view('no_access', $data);
}
}

View File

@@ -3,6 +3,7 @@
namespace App\Controllers;
use App\Models\Employee;
use CodeIgniter\HTTP\ResponseInterface;
/**
* @property Employee employee
@@ -17,11 +18,11 @@ class Office extends Secure_Controller
}
/**
* @return void
* @return string
*/
public function getIndex(): void
public function getIndex(): string
{
echo view('home/office');
return view('home/office');
}
/**

View File

@@ -3,6 +3,7 @@
namespace App\Controllers;
use App\Models\Person;
use CodeIgniter\HTTP\ResponseInterface;
use Config\Services;
use function Tamtamchik\NameCase\str_name_case;
@@ -21,34 +22,36 @@ abstract class Persons extends Secure_Controller
}
/**
* @return void
* @return string
*/
public function getIndex(): void
public function getIndex(): string
{
$data['table_headers'] = get_people_manage_table_headers();
echo view('people/manage', $data);
return view('people/manage', $data);
}
/**
* Gives search suggestions based on what is being searched for
* @return ResponseInterface
*/
public function getSuggest(): void
public function getSuggest(): ResponseInterface
{
$search = $this->request->getGet('term');
$suggestions = $this->person->get_search_suggestions($search);
echo json_encode($suggestions);
return $this->response->setJSON($suggestions);
}
/**
* Gets one row for a person manage table. This is called using AJAX to update one row.
* @return ResponseInterface
*/
public function getRow(int $row_id): void
public function getRow(int $row_id): ResponseInterface
{
$data_row = get_person_data_row($this->person->get_info($row_id));
echo json_encode($data_row);
return $this->response->setJSON($data_row);
}
/**

View File

@@ -11,6 +11,7 @@ use App\Models\Item_kit;
use App\Models\Receiving;
use App\Models\Stock_location;
use App\Models\Supplier;
use CodeIgniter\HTTP\ResponseInterface;
use Config\OSPOS;
use Config\Services;
use ReflectionException;
@@ -46,66 +47,66 @@ class Receivings extends Secure_Controller
}
/**
* @return void
* @return string
*/
public function getIndex(): void
public function getIndex(): string
{
$this->_reload();
return $this->_reload();
}
/**
* Returns search suggestions for an item. Used in app/Views/sales/register.php
*
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function getItemSearch(): void
public function getItemSearch(): ResponseInterface
{
$search = $this->request->getGet('term');
$suggestions = $this->item->get_search_suggestions($search, ['search_custom' => false, 'is_deleted' => false], true);
$suggestions = array_merge($suggestions, $this->item_kit->get_search_suggestions($search));
echo json_encode($suggestions);
return $this->response->setJSON($suggestions);
}
/**
* Gets search suggestions for a stock item. Used in app/Views/receivings/receiving.php
*
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function getStockItemSearch(): void
public function getStockItemSearch(): ResponseInterface
{
$search = $this->request->getGet('term');
$suggestions = $this->item->get_stock_search_suggestions($search, ['search_custom' => false, 'is_deleted' => false], true);
$suggestions = array_merge($suggestions, $this->item_kit->get_search_suggestions($search));
echo json_encode($suggestions);
return $this->response->setJSON($suggestions);
}
/**
* Set supplier if it exists in the database. Used in app/Views/receivings/receiving.php
*
* @return void
* @return string
* @noinspection PhpUnused
*/
public function postSelectSupplier(): void
public function postSelectSupplier(): string
{
$supplier_id = $this->request->getPost('supplier', FILTER_SANITIZE_NUMBER_INT);
if ($this->supplier->exists($supplier_id)) {
$this->receiving_lib->set_supplier($supplier_id);
}
$this->_reload(); // TODO: Hungarian notation
return $this->_reload(); // TODO: Hungarian notation
}
/**
* Change receiving mode for current receiving. Used in app/Views/receivings/receiving.php
*
* @return void
* @return string
* @noinspection PhpUnused
*/
public function postChangeMode(): void
public function postChangeMode(): string
{
$stock_destination = $this->request->getPost('stock_destination', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$stock_source = $this->request->getPost('stock_source', FILTER_SANITIZE_NUMBER_INT);
@@ -121,49 +122,49 @@ class Receivings extends Secure_Controller
$this->receiving_lib->set_stock_destination($stock_destination);
}
$this->_reload(); // TODO: Hungarian notation
return $this->_reload(); // TODO: Hungarian notation
}
/**
* Sets receiving comment. Used in app/Views/receivings/receiving.php
*
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postSetComment(): void
public function postSetComment(): ResponseInterface
{
$this->receiving_lib->set_comment($this->request->getPost('comment', FILTER_SANITIZE_FULL_SPECIAL_CHARS));
return $this->response->setJSON(['success' => true]);
}
/**
* Sets the print after sale flag for the receiving. Used in app/Views/receivings/receiving.php
*
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postSetPrintAfterSale(): void
public function postSetPrintAfterSale(): ResponseInterface
{
$this->receiving_lib->set_print_after_sale($this->request->getPost('recv_print_after_sale') != null);
return $this->response->setJSON(['success' => true]);
}
/**
* Sets the reference number for the receiving. Used in app/Views/receivings/receiving.php
*
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postSetReference(): void
public function postSetReference(): ResponseInterface
{
$this->receiving_lib->set_reference($this->request->getPost('recv_reference', FILTER_SANITIZE_FULL_SPECIAL_CHARS));
return $this->response->setJSON(['success' => true]);
}
/**
* Add an item to the receiving. Used in app/Views/receivings/receiving.php
*
* @return void
* @return string
* @noinspection PhpUnused
*/
public function postAdd(): void
public function postAdd(): string
{
$data = [];
@@ -183,17 +184,17 @@ class Receivings extends Secure_Controller
$data['error'] = lang('Receivings.unable_to_add_item');
}
$this->_reload($data); // TODO: Hungarian notation
return $this->_reload($data); // TODO: Hungarian notation
}
/**
* Edit line item in current receiving. Used in app/Views/receivings/receiving.php
*
* @param $item_id
* @return void
* @param string|int|null $item_id
* @return string
* @noinspection PhpUnused
*/
public function postEditItem($item_id): void
public function postEditItem($item_id): string
{
$data = [];
@@ -222,17 +223,16 @@ class Receivings extends Secure_Controller
$data['error'] = lang('Receivings.error_editing_item');
}
$this->_reload($data); // TODO: Hungarian notation
return $this->_reload($data); // TODO: Hungarian notation
}
/**
* Edit a receiving. Used in app/Controllers/Receivings.php
*
* @param $receiving_id
* @return void
* @return string
* @noinspection PhpUnused
*/
public function getEdit($receiving_id): void
public function getEdit($receiving_id): string
{
$data = [];
@@ -251,63 +251,65 @@ class Receivings extends Secure_Controller
$data['selected_supplier_id'] = $receiving_info['supplier_id'];
$data['receiving_info'] = $receiving_info;
echo view('receivings/form', $data);
return view('receivings/form', $data);
}
/**
* Deletes an item from the current receiving. Used in app/Views/receivings/receiving.php
*
* @param $item_number
* @return void
* @return string
* @noinspection PhpUnused
*/
public function getDeleteItem($item_number): void
public function getDeleteItem($item_number): string
{
$this->receiving_lib->delete_item($item_number);
$this->_reload(); // TODO: Hungarian notation
return $this->_reload(); // TODO: Hungarian notation
}
/**
* @throws ReflectionException
* @return ResponseInterface
*/
public function postDelete(int $receiving_id = -1, bool $update_inventory = true): void
public function postDelete(int $receiving_id = -1, bool $update_inventory = true): ResponseInterface
{
$employee_id = $this->employee->get_logged_in_employee_info()->person_id;
$receiving_ids = $receiving_id == -1 ? $this->request->getPost('ids', FILTER_SANITIZE_NUMBER_INT) : [$receiving_id]; // TODO: Replace -1 with constant
if ($this->receiving->delete_list($receiving_ids, $employee_id, $update_inventory)) { // TODO: Likely need to surround this block of code in a try-catch to catch the ReflectionException
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Receivings.successfully_deleted') . ' ' . count($receiving_ids) . ' ' . lang('Receivings.one_or_multiple'),
'ids' => $receiving_ids
]);
} else {
echo json_encode(['success' => false, 'message' => lang('Receivings.cannot_be_deleted')]);
return $this->response->setJSON(['success' => false, 'message' => lang('Receivings.cannot_be_deleted')]);
}
}
/**
* Removes a supplier from a receiving. Used in app/Views/receivings/receiving.php
*
* @return void
* @return string
* @noinspection PhpUnused
*/
public function getRemoveSupplier(): void
public function getRemoveSupplier(): string
{
$this->receiving_lib->clear_reference();
$this->receiving_lib->remove_supplier();
$this->_reload(); // TODO: Hungarian notation
return $this->_reload(); // TODO: Hungarian notation
}
/**
* Complete and finalize receiving. Used in app/Views/receivings/receiving.php
*
* @return string
* @throws ReflectionException
* @noinspection PhpUnused
*/
public function postComplete(): void
public function postComplete(): string
{
$data = [];
@@ -356,18 +358,21 @@ class Receivings extends Secure_Controller
$data['print_after_sale'] = $this->receiving_lib->is_print_after_sale();
echo view("receivings/receipt", $data);
$view = view("receivings/receipt", $data);
$this->receiving_lib->clear_all();
return $view;
}
/**
* Complete a receiving requisition. Used in app/Views/receivings/receiving.php.
*
* @return string
* @throws ReflectionException
* @noinspection PhpUnused
*/
public function postRequisitionComplete(): void
public function postRequisitionComplete(): string
{
if ($this->receiving_lib->get_stock_source() != $this->receiving_lib->get_stock_destination()) {
foreach ($this->receiving_lib->get_cart() as $item) {
@@ -376,11 +381,11 @@ class Receivings extends Secure_Controller
$this->receiving_lib->add_item($item['item_id'], -$item['quantity'], $this->receiving_lib->get_stock_source(), $item['discount_type']);
}
$this->postComplete();
return $this->postComplete();
} else {
$data['error'] = lang('Receivings.error_requisition');
$this->_reload($data); // TODO: Hungarian notation
return $this->_reload($data); // TODO: Hungarian notation
}
}
@@ -388,10 +393,10 @@ class Receivings extends Secure_Controller
* Gets the receipt for a receiving. Used in app/Views/receivings/form.php
*
* @param $receiving_id
* @return void
* @return string
* @noinspection PhpUnused
*/
public function getReceipt($receiving_id): void
public function getReceipt($receiving_id): string
{
$receiving_info = $this->receiving->get_info($receiving_id)->getRowArray();
$this->receiving_lib->copy_entire_receiving($receiving_id);
@@ -424,16 +429,18 @@ class Receivings extends Secure_Controller
$data['print_after_sale'] = false;
echo view("receivings/receipt", $data);
$view = view("receivings/receipt", $data);
$this->receiving_lib->clear_all();
return $view;
}
/**
* @param array $data
* @return void
* @return string
*/
private function _reload(array $data = []): void // TODO: Hungarian notation
private function _reload(array $data = []): string // TODO: Hungarian notation
{
$data['cart'] = $this->receiving_lib->get_cart();
$data['modes'] = ['receive' => lang('Receivings.receiving'), 'return' => lang('Receivings.return')];
@@ -470,13 +477,14 @@ class Receivings extends Secure_Controller
$data['print_after_sale'] = $this->receiving_lib->is_print_after_sale();
echo view("receivings/receiving", $data);
return view("receivings/receiving", $data);
}
/**
* @return ResponseInterface
* @throws ReflectionException
*/
public function postSave(int $receiving_id = -1): void // TODO: Replace -1 with a constant
public function postSave(int $receiving_id = -1): ResponseInterface // TODO: Replace -1 with a constant
{
$newdate = $this->request->getPost('date', FILTER_SANITIZE_FULL_SPECIAL_CHARS); // TODO: newdate does not follow naming conventions
@@ -493,13 +501,13 @@ class Receivings extends Secure_Controller
$this->inventory->update('RECV ' . $receiving_id, ['trans_date' => $receiving_time]);
if ($this->receiving->update($receiving_id, $receiving_data)) {
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Receivings.successfully_updated'),
'id' => $receiving_id
]);
} else {
echo json_encode([
return $this->response->setJSON([
'success' => false,
'message' => lang('Receivings.unsuccessfully_updated'),
'id' => $receiving_id
@@ -510,13 +518,13 @@ class Receivings extends Secure_Controller
/**
* Cancel an in-process receiving. Used in app/Views/receivings/receiving.php
*
* @return void
* @return string
* @noinspection PhpUnused
*/
public function postCancelReceiving(): void
public function postCancelReceiving(): string
{
$this->receiving_lib->clear_all();
$this->_reload(); // TODO: Hungarian Notation
return $this->_reload(); // TODO: Hungarian Notation
}
}

View File

@@ -25,6 +25,7 @@ use App\Models\Reports\Summary_sales;
use App\Models\Reports\Summary_sales_taxes;
use App\Models\Reports\Summary_suppliers;
use App\Models\Reports\Summary_taxes;
use CodeIgniter\HTTP\ResponseInterface;
use Config\OSPOS;
use Config\Services;
@@ -102,8 +103,9 @@ class Reports extends Secure_Controller
/**
* Initial Report listing screen
* @return string
*/
public function getIndex(): void
public function getIndex(): string
{
$person_id = $this->session->get('person_id');
$grants = $this->employee->get_employee_grants($this->session->get('person_id'));
@@ -115,7 +117,7 @@ class Reports extends Secure_Controller
'permission_ids' => $permissions_ids,
];
echo view('reports/listing', $data);
return view('reports/listing', $data);
}
/**
@@ -124,9 +126,9 @@ class Reports extends Secure_Controller
* @param string $end_date
* @param string $sale_type
* @param string $location_id
* @return void
* @return string
*/
public function summary_sales(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void // TODO: Perhaps these need to be passed as an array? Too many parameters in the signature.
public function summary_sales(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string // TODO: Perhaps these need to be passed as an array? Too many parameters in the signature.
{ // TODO: Duplicated code
$this->clearCache();
@@ -162,7 +164,7 @@ class Reports extends Secure_Controller
'summary_data' => $summary
];
echo view('reports/tabular', $data);
return view('reports/tabular', $data);
}
/**
@@ -171,9 +173,9 @@ class Reports extends Secure_Controller
* @param string $end_date
* @param string $sale_type
* @param string $location_id
* @return void
* @return string
*/
public function summary_categories(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void
public function summary_categories(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{ // TODO: Duplicated code
$this->clearCache();
@@ -208,7 +210,7 @@ class Reports extends Secure_Controller
'summary_data' => $summary
];
echo view('reports/tabular', $data);
return view('reports/tabular', $data);
}
/**
@@ -216,9 +218,9 @@ class Reports extends Secure_Controller
* @param string $start_date
* @param string $end_date
* @param string $sale_type
* @return void
* @return string
*/
public function summary_expenses_categories(string $start_date, string $end_date, string $sale_type): void
public function summary_expenses_categories(string $start_date, string $end_date, string $sale_type): string
{
$this->clearCache();
@@ -245,7 +247,7 @@ class Reports extends Secure_Controller
'summary_data' => $summary
];
echo view('reports/tabular', $data);
return view('reports/tabular', $data);
}
/**
@@ -254,9 +256,9 @@ class Reports extends Secure_Controller
* @param string $end_date
* @param string $sale_type
* @param string $location_id
* @return void
* @return string
*/
public function summary_customers(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void
public function summary_customers(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{
$this->clearCache();
@@ -293,7 +295,7 @@ class Reports extends Secure_Controller
'summary_data' => $summary
];
echo view('reports/tabular', $data);
return view('reports/tabular', $data);
}
/**
@@ -302,9 +304,9 @@ class Reports extends Secure_Controller
* @param string $end_date
* @param string $sale_type
* @param string $location_id
* @return void
* @return string
*/
public function summary_suppliers(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void
public function summary_suppliers(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{ // TODO: Duplicated Code
$this->clearCache();
@@ -339,7 +341,7 @@ class Reports extends Secure_Controller
'summary_data' => $summary
];
echo view('reports/tabular', $data);
return view('reports/tabular', $data);
}
/**
@@ -348,9 +350,9 @@ class Reports extends Secure_Controller
* @param string $end_date
* @param string $sale_type
* @param string $location_id
* @return void
* @return string
*/
public function summary_items(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void
public function summary_items(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{
$this->clearCache();
@@ -389,7 +391,7 @@ class Reports extends Secure_Controller
'summary_data' => $summary
];
echo view('reports/tabular', $data);
return view('reports/tabular', $data);
}
/**
@@ -398,9 +400,9 @@ class Reports extends Secure_Controller
* @param string $end_date
* @param string $sale_type
* @param string $location_id
* @return void
* @return string
*/
public function summary_employees(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void
public function summary_employees(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{
$this->clearCache();
@@ -437,7 +439,7 @@ class Reports extends Secure_Controller
'summary_data' => $summary
];
echo view('reports/tabular', $data);
return view('reports/tabular', $data);
}
/**
@@ -446,9 +448,9 @@ class Reports extends Secure_Controller
* @param string $end_date
* @param string $sale_type
* @param string $location_id
* @return void
* @return string
*/
public function summary_taxes(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void
public function summary_taxes(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{ // TODO: Duplicate Code
$this->clearCache();
@@ -483,13 +485,14 @@ class Reports extends Secure_Controller
'summary_data' => $summary
];
echo view('reports/tabular', $data);
return view('reports/tabular', $data);
}
/**
* Summary Sales Taxes report
* @return string
*/
public function summary_sales_taxes(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void
public function summary_sales_taxes(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{ // TODO: Duplicated code
$this->clearCache();
@@ -522,16 +525,16 @@ class Reports extends Secure_Controller
'summary_data' => $summary
];
echo view('reports/tabular', $data);
return view('reports/tabular', $data);
}
/**
* Summary Discounts report input. Used in app/Config/Routes.php
*
* @return void
* @return string
* @noinspection PhpUnused
*/
public function summary_discounts_input(): void
public function summary_discounts_input(): string
{
$this->clearCache();
@@ -542,13 +545,14 @@ class Reports extends Secure_Controller
$data['discount_type_options'] = ['0' => lang('Reports.discount_percent'), '1' => lang('Reports.discount_fixed')];
$data['sale_type_options'] = $this->get_sale_type_options();
echo view('reports/date_input', $data);
return view('reports/date_input', $data);
}
/**
* Summary Discounts report
* @return string
**/
public function summary_discounts(string $start_date, string $end_date, string $sale_type, string $location_id = 'all', int $discount_type = 0): void
public function summary_discounts(string $start_date, string $end_date, string $sale_type, string $location_id = 'all', int $discount_type = 0): string
{ // TODO: Duplicated Code
$this->clearCache();
@@ -580,13 +584,14 @@ class Reports extends Secure_Controller
'summary_data' => $summary
];
echo view('reports/tabular', $data);
return view('reports/tabular', $data);
}
/**
* Summary Payments report
* @return string
*/
public function summary_payments(string $start_date, string $end_date): void
public function summary_payments(string $start_date, string $end_date): string
{
$this->clearCache();
@@ -638,16 +643,16 @@ class Reports extends Secure_Controller
'summary_data' => $summary
];
echo view('reports/tabular', $data);
return view('reports/tabular', $data);
}
/**
* Input for reports that require only a date range. Used in app/Config/Routes.php
*
* @return void
* @return string
* @noinspection PhpUnused
*/
public function date_input(): void
public function date_input(): string
{ // TODO: Duplicated Code
$this->clearCache();
@@ -657,30 +662,30 @@ class Reports extends Secure_Controller
$data['mode'] = 'sale';
$data['sale_type_options'] = $this->get_sale_type_options();
echo view('reports/date_input', $data);
return view('reports/date_input', $data);
}
/**
* Input for reports that require only a date range. Used in app/Config/Routes.php
*
* @return void
* @return string
* @noinspection PhpUnused
*/
public function date_input_only(): void
public function date_input_only(): string
{
$this->clearCache();
$data = [];
echo view('reports/date_input', $data);
return view('reports/date_input', $data);
}
/**
* Input for reports that require only a date range. Used in app/Config/Routes.php
*
* @return void
* @return string
* @noinspection PhpUnused
*/
public function date_input_sales(): void
public function date_input_sales(): string
{ // TODO: Duplicated Code
$this->clearCache();
@@ -690,23 +695,23 @@ class Reports extends Secure_Controller
$data['mode'] = 'sale';
$data['sale_type_options'] = $this->get_sale_type_options();
echo view('reports/date_input', $data);
return view('reports/date_input', $data);
}
/**
* Receivings date input. Used in app/Config/Routes.php
*
* @return void
* @return string
* @noinspection PhpUnused
*/
public function date_input_recv(): void
public function date_input_recv(): string
{
$stock_locations = $data = $this->stock_location->get_allowed_locations('receivings');
$stock_locations['all'] = lang('Reports.all');
$data['stock_locations'] = array_reverse($stock_locations, true);
$data['mode'] = 'receiving';
echo view('reports/date_input', $data);
return view('reports/date_input', $data);
}
/**
@@ -715,10 +720,10 @@ class Reports extends Secure_Controller
* @param string $start_date
* @param string $end_date
* @param string $sale_type
* @return void
* @return string
* @noinspection PhpUnused
*/
public function graphical_summary_expenses_categories(string $start_date, string $end_date, string $sale_type): void
public function graphical_summary_expenses_categories(string $start_date, string $end_date, string $sale_type): string
{
$this->clearCache();
@@ -751,7 +756,7 @@ class Reports extends Secure_Controller
'show_currency' => true
];
echo view('reports/graphical', $data);
return view('reports/graphical', $data);
}
/**
@@ -761,9 +766,9 @@ class Reports extends Secure_Controller
* @param string $end_date
* @param string $sale_type
* @param string $location_id
* @return void
* @return string
*/
public function graphical_summary_sales(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void
public function graphical_summary_sales(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{
$this->clearCache();
@@ -797,7 +802,7 @@ class Reports extends Secure_Controller
'show_currency' => true
];
echo view('reports/graphical', $data);
return view('reports/graphical', $data);
}
/**
@@ -807,9 +812,9 @@ class Reports extends Secure_Controller
* @param string $end_date
* @param string $sale_type
* @param string $location_id
* @return void
* @return string
*/
public function graphical_summary_items(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void
public function graphical_summary_items(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{
$this->clearCache();
@@ -844,7 +849,7 @@ class Reports extends Secure_Controller
'show_currency' => true
];
echo view('reports/graphical', $data);
return view('reports/graphical', $data);
}
/**
@@ -854,9 +859,9 @@ class Reports extends Secure_Controller
* @param string $end_date
* @param string $sale_type
* @param string $location_id
* @return void
* @return string
*/
public function graphical_summary_categories(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void
public function graphical_summary_categories(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{ // TODO: Duplicated Code
$this->clearCache();
@@ -887,7 +892,7 @@ class Reports extends Secure_Controller
'show_currency' => true
];
echo view('reports/graphical', $data);
return view('reports/graphical', $data);
}
/**
@@ -897,9 +902,9 @@ class Reports extends Secure_Controller
* @param string $end_date
* @param string $sale_type
* @param string $location_id
* @return void
* @return string
*/
public function graphical_summary_suppliers(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void
public function graphical_summary_suppliers(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{ // TODO: Duplicated Code
$this->clearCache();
@@ -932,7 +937,7 @@ class Reports extends Secure_Controller
'show_currency' => true
];
echo view('reports/graphical', $data);
return view('reports/graphical', $data);
}
/**
@@ -942,9 +947,9 @@ class Reports extends Secure_Controller
* @param string $end_date
* @param string $sale_type
* @param string $location_id
* @return void
* @return string
*/
public function graphical_summary_employees(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void
public function graphical_summary_employees(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{
$this->clearCache();
@@ -976,7 +981,7 @@ class Reports extends Secure_Controller
'show_currency' => true
];
echo view('reports/graphical', $data);
return view('reports/graphical', $data);
}
/**
@@ -986,9 +991,9 @@ class Reports extends Secure_Controller
* @param string $end_date
* @param string $sale_type
* @param string $location_id
* @return void
* @return string
*/
public function graphical_summary_taxes(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void
public function graphical_summary_taxes(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{ // TODO: Duplicated Code
$this->clearCache();
@@ -1020,7 +1025,7 @@ class Reports extends Secure_Controller
'show_currency' => true
];
echo view('reports/graphical', $data);
return view('reports/graphical', $data);
}
/**
@@ -1030,9 +1035,9 @@ class Reports extends Secure_Controller
* @param string $end_date
* @param string $sale_type
* @param string $location_id
* @return void
* @return string
*/
public function graphical_summary_sales_taxes(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void
public function graphical_summary_sales_taxes(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{ // TODO: Duplicated Code
$this->clearCache();
@@ -1064,7 +1069,7 @@ class Reports extends Secure_Controller
'show_currency' => true
];
echo view('reports/graphical', $data);
return view('reports/graphical', $data);
}
/**
@@ -1074,9 +1079,9 @@ class Reports extends Secure_Controller
* @param string $end_date
* @param string $sale_type
* @param string $location_id
* @return void
* @return string
*/
public function graphical_summary_customers(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void
public function graphical_summary_customers(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{ // TODO: Duplicated Code
$this->clearCache();
@@ -1110,7 +1115,7 @@ class Reports extends Secure_Controller
'show_currency' => true
];
echo view('reports/graphical', $data);
return view('reports/graphical', $data);
}
/**
@@ -1121,9 +1126,10 @@ class Reports extends Secure_Controller
* @param string $sale_type
* @param string $location_id ID of the location to be reported or 'all' if none is specified
* @param int $discount_type
* @return string
* @noinspection PhpUnused
*/
public function graphical_summary_discounts(string $start_date, string $end_date, string $sale_type, string $location_id = 'all', int $discount_type = 0): void
public function graphical_summary_discounts(string $start_date, string $end_date, string $sale_type, string $location_id = 'all', int $discount_type = 0): string
{ // TODO: Duplicated Code
$this->clearCache();
@@ -1158,7 +1164,7 @@ class Reports extends Secure_Controller
'show_currency' => false
];
echo view('reports/graphical', $data);
return view('reports/graphical', $data);
}
/**
@@ -1168,9 +1174,9 @@ class Reports extends Secure_Controller
* @param string $end_date
* @param string $sale_type
* @param string $location_id
* @return void
* @return string
*/
public function graphical_summary_payments(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void
public function graphical_summary_payments(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{
$this->clearCache();
@@ -1204,16 +1210,16 @@ class Reports extends Secure_Controller
'show_currency' => true
];
echo view('reports/graphical', $data);
return view('reports/graphical', $data);
}
/**
* Gets the specific customer input view. Used in app/Config/Routes.php
*
* @return void
* @return string
* @noinspection PhpUnused
*/
public function specific_customer_input(): void
public function specific_customer_input(): string
{
$this->clearCache();
@@ -1231,7 +1237,7 @@ class Reports extends Secure_Controller
$data['sale_type_options'] = $this->get_sale_type_options();
$data['payment_type'] = $this->get_payment_type();
echo view('reports/specific_customer_input', $data);
return view('reports/specific_customer_input', $data);
}
/**
@@ -1258,10 +1264,10 @@ class Reports extends Secure_Controller
* @param string $customer_id
* @param string $sale_type
* @param string $payment_type
* @return void
* @return string
* @noinspection PhpUnused
*/
public function specific_customers(string $start_date, string $end_date, string $customer_id, string $sale_type, string $payment_type): void
public function specific_customers(string $start_date, string $end_date, string $customer_id, string $sale_type, string $payment_type): string
{
$this->clearCache();
@@ -1352,16 +1358,16 @@ class Reports extends Secure_Controller
'overall_summary_data' => $specific_customer->getSummaryData($inputs)
];
echo view('reports/tabular_details', $data);
return view('reports/tabular_details', $data);
}
/**
* Detailed employee report input form. Used in app/Config/Routes.php
*
* @return void
* @return string
* @noinspection PhpUnused
*/
public function specific_employee_input(): void
public function specific_employee_input(): string
{
$this->clearCache();
@@ -1375,7 +1381,7 @@ class Reports extends Secure_Controller
$data['specific_input_data'] = $employees;
$data['sale_type_options'] = $this->get_sale_type_options();
echo view('reports/specific_input', $data);
return view('reports/specific_input', $data);
}
/**
@@ -1385,10 +1391,10 @@ class Reports extends Secure_Controller
* @param string $end_date
* @param string $employee_id
* @param string $sale_type
* @return void
* @return string
* @noinspection PhpUnused
*/
public function specific_employees(string $start_date, string $end_date, string $employee_id, string $sale_type): void
public function specific_employees(string $start_date, string $end_date, string $employee_id, string $sale_type): string
{
$this->clearCache();
@@ -1475,16 +1481,16 @@ class Reports extends Secure_Controller
'overall_summary_data' => $specific_employee->getSummaryData($inputs)
];
echo view('reports/tabular_details', $data);
return view('reports/tabular_details', $data);
}
/**
* Detailed discount report. Used in app/Config/Routes.php
*
* @return void
* @return string
* @noinspection PhpUnused
*/
public function specific_discount_input(): void
public function specific_discount_input(): string
{
$this->clearCache();
@@ -1499,7 +1505,7 @@ class Reports extends Secure_Controller
$data['discount_type_options'] = ['0' => lang('Reports.discount_percent'), '1' => lang('Reports.discount_fixed')];
$data['sale_type_options'] = $this->get_sale_type_options();
echo view('reports/specific_input', $data);
return view('reports/specific_input', $data);
}
/**
@@ -1510,10 +1516,10 @@ class Reports extends Secure_Controller
* @param string $discount
* @param string $sale_type
* @param string $discount_type
* @return void
* @return string
* @noinspection PhpUnused
*/
public function specific_discounts(string $start_date, string $end_date, string $discount, string $sale_type, string $discount_type): void
public function specific_discounts(string $start_date, string $end_date, string $discount, string $sale_type, string $discount_type): string
{
$this->clearCache();
@@ -1606,17 +1612,17 @@ class Reports extends Secure_Controller
'overall_summary_data' => $specific_discount->getSummaryData($inputs)
];
echo view('reports/tabular_details', $data);
return view('reports/tabular_details', $data);
}
/**
* Gets the detailed sales data row for given sale_id. Used in app/Views/reports/tabular_details.php
*
* @param string $sale_id
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function getGet_detailed_sales_row(string $sale_id): void
public function getGet_detailed_sales_row(string $sale_id): ResponseInterface
{
$this->clearCache();
@@ -1659,16 +1665,16 @@ class Reports extends Secure_Controller
)
];
echo json_encode([$sale_id => $summary_data]);
return $this->response->setJSON([$sale_id => $summary_data]);
}
/**
* Detailed Supplier report input form. Used in app/Config/Routes.php
*
* @return void
* @return string
* @noinspection PhpUnused
*/
public function specific_supplier_input(): void
public function specific_supplier_input(): string
{
$this->clearCache();
@@ -1682,7 +1688,7 @@ class Reports extends Secure_Controller
$data['specific_input_data'] = $suppliers;
$data['sale_type_options'] = $this->get_sale_type_options();
echo view('reports/specific_input', $data);
return view('reports/specific_input', $data);
}
/**
@@ -1692,9 +1698,9 @@ class Reports extends Secure_Controller
* @param string $end_date
* @param string $supplier_id
* @param string $sale_type
* @return void
* @return string
*/
public function specific_suppliers(string $start_date, string $end_date, string $supplier_id, string $sale_type): void
public function specific_suppliers(string $start_date, string $end_date, string $supplier_id, string $sale_type): string
{
$inputs = [
'start_date' => $start_date,
@@ -1737,7 +1743,7 @@ class Reports extends Secure_Controller
'summary_data' => $specific_supplier->getSummaryData($inputs)
];
echo view('reports/tabular', $data);
return view('reports/tabular', $data);
}
/**
@@ -1764,9 +1770,9 @@ class Reports extends Secure_Controller
* @param string $end_date
* @param string $sale_type
* @param string $location_id
* @return void
* @return string
*/
public function detailed_sales(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void
public function detailed_sales(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{
$this->clearCache();
@@ -1870,17 +1876,17 @@ class Reports extends Secure_Controller
'details_data_rewards' => $details_data_rewards,
'overall_summary_data' => $this->detailed_sales->getSummaryData($inputs)
];
echo view('reports/tabular_details', $data);
return view('reports/tabular_details', $data);
}
/**
* Returns detailed receivings row for given receiving_id. Used in app/Views/reports/tabular_details.php
*
* @param string $receiving_id
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function getGet_detailed_receivings_row(string $receiving_id): void
public function getGet_detailed_receivings_row(string $receiving_id): ResponseInterface
{
$inputs = ['receiving_id' => $receiving_id];
@@ -1910,7 +1916,7 @@ class Reports extends Secure_Controller
)
];
echo json_encode([$receiving_id => $summary_data]);
return $this->response->setJSON([$receiving_id => $summary_data]);
}
/**
@@ -1918,9 +1924,9 @@ class Reports extends Secure_Controller
* @param string $end_date
* @param string $receiving_type
* @param string $location_id
* @return void
* @return string
*/
public function detailed_receivings(string $start_date, string $end_date, string $receiving_type, string $location_id = 'all'): void
public function detailed_receivings(string $start_date, string $end_date, string $receiving_type, string $location_id = 'all'): string
{
$this->clearCache();
@@ -1994,13 +2000,13 @@ class Reports extends Secure_Controller
'overall_summary_data' => $this->detailed_receivings->getSummaryData($inputs)
];
echo view('reports/tabular_details', $data);
return view('reports/tabular_details', $data);
}
/**
* @return void
* @return string
*/
public function inventory_low(): void
public function inventory_low(): string
{
$this->clearCache();
@@ -2029,16 +2035,16 @@ class Reports extends Secure_Controller
'summary_data' => $inventory_low->getSummaryData($inputs)
];
echo view('reports/tabular', $data);
return view('reports/tabular', $data);
}
/**
* Gets the inventory summary input view. Used in app/Config/Routes.php
*
* @return void
* @return string
* @noinspection PhpUnused
*/
public function inventory_summary_input(): void
public function inventory_summary_input(): string
{
$this->clearCache();
@@ -2049,15 +2055,15 @@ class Reports extends Secure_Controller
$stock_locations['all'] = lang('Reports.all');
$data['stock_locations'] = array_reverse($stock_locations, true);
echo view('reports/inventory_summary_input', $data);
return view('reports/inventory_summary_input', $data);
}
/**
* @param string $location_id
* @param string $item_count
* @return void
* @return string
*/
public function inventory_summary(string $location_id = 'all', string $item_count = 'all'): void
public function inventory_summary(string $location_id = 'all', string $item_count = 'all'): string
{
$this->clearCache();
@@ -2089,7 +2095,7 @@ class Reports extends Secure_Controller
'summary_data' => $this->inventory_summary->getSummaryData($report_data)
];
echo view('reports/tabular', $data);
return view('reports/tabular', $data);
}
/**

View File

@@ -20,6 +20,7 @@ use App\Models\Stock_location;
use App\Models\Tokens\Token_invoice_count;
use App\Models\Tokens\Token_customer;
use App\Models\Tokens\Token_invoice_sequence;
use CodeIgniter\HTTP\ResponseInterface;
use Config\Services;
use Config\OSPOS;
use ReflectionException;
@@ -65,22 +66,19 @@ class Sales extends Secure_Controller
$this->employee = model(Employee::class);
}
/**
* @return void
*/
public function getIndex(): void
public function getIndex(): ResponseInterface|string
{
$this->session->set('allow_temp_items', 1);
$this->_reload(); // TODO: Hungarian Notation
return $this->_reload(); // TODO: Hungarian Notation
}
/**
* Load the sale edit modal. Used in app/Views/sales/register.php.
*
* @return void
* @return string
* @noinspection PhpUnused
*/
public function getManage(): void
public function getManage(): string
{
$person_id = $this->session->get('person_id');
@@ -107,26 +105,26 @@ class Sales extends Secure_Controller
}
$data['selected_filters'] = $selected_filters;
echo view('sales/manage', $data);
return view('sales/manage', $data);
}
}
/**
* @param int $row_id
* @return void
* @return ResponseInterface
*/
public function getRow(int $row_id): void
public function getRow(int $row_id): ResponseInterface
{
$sale_info = $this->sale->get_info($row_id)->getRow();
$data_row = get_sale_data_row($sale_info);
echo json_encode($data_row);
return $this->response->setJSON($data_row);
}
/**
* @return void
*/
public function getSearch(): void
public function getSearch(): ResponseInterface
{
$search = $this->request->getGet('search', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$limit = $this->request->getGet('limit', FILTER_SANITIZE_NUMBER_INT);
@@ -166,16 +164,16 @@ class Sales extends Secure_Controller
$data_rows[] = get_sale_data_last_row($sales);
}
echo json_encode(['total' => $total_rows, 'rows' => $data_rows, 'payment_summary' => $payment_summary]);
return $this->response->setJSON(['total' => $total_rows, 'rows' => $data_rows, 'payment_summary' => $payment_summary]);
}
/**
* Gets search suggestions for an item or item kit. Used in app/Views/sales/register.php.
*
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function getItemSearch(): void
public function getItemSearch(): ResponseInterface
{
$suggestions = [];
$receipt = $search = $this->request->getGet('term') != ''
@@ -189,13 +187,13 @@ class Sales extends Secure_Controller
$suggestions = array_merge($suggestions, $this->item->get_search_suggestions($search, ['search_custom' => false, 'is_deleted' => false], true));
$suggestions = array_merge($suggestions, $this->item_kit->get_search_suggestions($search));
echo json_encode($suggestions);
return $this->response->setJSON($suggestions);
}
/**
* @return void
* @return ResponseInterface
*/
public function suggest_search(): void
public function suggest_search(): ResponseInterface
{
$search = $this->request->getPost('term') != ''
? $this->request->getPost('term')
@@ -203,16 +201,16 @@ class Sales extends Secure_Controller
$suggestions = $this->sale->get_search_suggestions($search);
echo json_encode($suggestions);
return $this->response->setJSON($suggestions);
}
/**
* Set a given customer. Used in app/Views/sales/register.php.
*
* @return void
* @return ResponseInterface|string
* @noinspection PhpUnused
*/
public function postSelectCustomer(): void
public function postSelectCustomer(): ResponseInterface|string
{
$customer_id = (int)$this->request->getPost('customer', FILTER_SANITIZE_NUMBER_INT);
if ($this->customer->exists($customer_id)) {
@@ -226,16 +224,16 @@ class Sales extends Secure_Controller
}
}
$this->_reload();
return $this->_reload();
}
/**
* Changes the sale mode in the register to carry out different types of sales
*
* @return void
* @return ResponseInterface|string
* @noinspection PhpUnused
*/
public function postChangeMode(): void
public function postChangeMode(): ResponseInterface|string
{
$mode = $this->request->getPost('mode', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$this->sale_lib->set_mode($mode);
@@ -276,14 +274,14 @@ class Sales extends Secure_Controller
$this->sale_lib->empty_payments();
$this->_reload();
return $this->_reload();
}
/**
* @param int $sale_type
* @return void
* @return ResponseInterface|string
*/
public function change_register_mode(int $sale_type): void
public function change_register_mode(int $sale_type): ResponseInterface|string
{
$mode = match ($sale_type) {
SALE_TYPE_QUOTE => 'sale_quote',
@@ -294,81 +292,87 @@ class Sales extends Secure_Controller
};
$this->sale_lib->set_mode($mode);
return $this->_reload();
}
/**
* Sets the sales comment. Used in app/Views/sales/register.php
*
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postSetComment(): void
public function postSetComment(): ResponseInterface
{
$this->sale_lib->set_comment($this->request->getPost('comment', FILTER_SANITIZE_FULL_SPECIAL_CHARS));
return $this->response->setJSON(['success' => true]);
}
/**
* Sets the invoice number. Used in app/Views/sales/register.php
*
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postSetInvoiceNumber(): void
public function postSetInvoiceNumber(): ResponseInterface|string
{
$this->sale_lib->set_invoice_number($this->request->getPost('sales_invoice_number', FILTER_SANITIZE_NUMBER_INT));
return $this->response->setJSON(['success' => true]);
}
/**
* @return void
* @return ResponseInterface
*/
public function postSetPaymentType(): void // TODO: This function does not appear to be called anywhere in the code.
public function postSetPaymentType(): ResponseInterface|string // TODO: This function does not appear to be called anywhere in the code.
{
$this->sale_lib->set_payment_type($this->request->getPost('selected_payment_type', FILTER_SANITIZE_FULL_SPECIAL_CHARS));
$this->_reload(); // TODO: Hungarian notation.
return $this->_reload(); // TODO: Hungarian notation.
}
/**
* Sets PrintAfterSale flag. Used in app/Views/sales/register.php
*
* @return void
* @return ResponseInterface|string
* @noinspection PhpUnused
*/
public function postSetPrintAfterSale(): void
public function postSetPrintAfterSale(): ResponseInterface
{
$this->sale_lib->set_print_after_sale($this->request->getPost('sales_print_after_sale') != 'false');
return $this->response->setJSON(['success' => true]);
}
/**
* Sets the flag to include prices in the work order. Used in app/Views/sales/register.php
*
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postSetPriceWorkOrders(): void
public function postSetPriceWorkOrders(): ResponseInterface
{
$price_work_orders = parse_decimals($this->request->getPost('price_work_orders'));
$this->sale_lib->set_price_work_orders($price_work_orders);
return $this->response->setJSON(['success' => true]);
}
/**
* Sets the flag to email receipt to the customer. Used in app/Views/sales/register.php
*
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postSetEmailReceipt(): void
public function postSetEmailReceipt(): ResponseInterface
{
$this->sale_lib->set_email_receipt($this->request->getPost('email_receipt', FILTER_SANITIZE_FULL_SPECIAL_CHARS));
return $this->response->setJSON(['success' => true]);
}
/**
* Add a payment to the sale. Used in app/Views/sales/register.php
*
* @return void
* @return ResponseInterface|string
* @noinspection PhpUnused
*/
public function postAddPayment(): void
public function postAddPayment(): ResponseInterface|string
{
$data = [];
$giftcard = model(Giftcard::class);
@@ -453,32 +457,32 @@ class Sales extends Secure_Controller
}
}
$this->_reload($data);
return $this->_reload($data);
}
/**
* Multiple Payments. Used in app/Views/sales/register.php
*
* @param string $payment_id
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function getDeletePayment(string $payment_id): void
public function getDeletePayment(string $payment_id): ResponseInterface|string
{
helper('url');
$this->sale_lib->delete_payment(base64url_decode($payment_id));
$this->_reload(); // TODO: Hungarian notation
return $this->_reload();
}
/**
* Add an item to the sale. Used in app/Views/sales/register.php
*
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postAdd(): void
public function postAdd(): ResponseInterface|string
{
$data = [];
@@ -549,17 +553,17 @@ class Sales extends Secure_Controller
}
}
$this->_reload($data);
return $this->_reload($data);
}
/**
* Edit an item in the sale. Used in app/Views/sales/register.php
*
* @param string $line
* @return void
* @return ResponseInterface|string
* @noinspection PhpUnused
*/
public function postEditItem(string $line): void
public function postEditItem(string $line): ResponseInterface|string
{
$data = [];
@@ -594,33 +598,33 @@ class Sales extends Secure_Controller
$data['error'] = lang('Sales.error_editing_item');
}
$this->_reload($data);
return $this->_reload($data);
}
/**
* Deletes an item specified in the parameter from the shopping cart. Used in app/Views/sales/register.php
*
* @param int $item_id
* @return void
* @return ResponseInterface
* @throws ReflectionException
* @noinspection PhpUnused
*/
public function getDeleteItem(int $item_id): void
public function getDeleteItem(int $item_id): ResponseInterface|string
{
$this->sale_lib->delete_item($item_id);
$this->sale_lib->empty_payments();
$this->_reload(); // TODO: Hungarian notation
return $this->_reload();
}
/**
* Remove the current customer from the sale. Used in app/Views/sales/register.php
*
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function getRemoveCustomer(): void
public function getRemoveCustomer(): ResponseInterface|string
{
$this->sale_lib->clear_giftcard_remainder();
$this->sale_lib->clear_rewards_remainder();
@@ -629,17 +633,17 @@ class Sales extends Secure_Controller
$this->sale_lib->clear_quote_number();
$this->sale_lib->remove_customer();
$this->_reload(); // TODO: Hungarian notation
return $this->_reload();
}
/**
* Complete and finalize a sale. Used in app/Views/sales/register.php
*
* @return void
* @return string
* @throws ReflectionException
* @noinspection PhpUnused
*/
public function postComplete(): void // TODO: this function is huge. Probably should be refactored.
public function postComplete(): string // TODO: this function is huge. Probably should be refactored.
{
$sale_id = $this->sale_lib->get_sale_id();
$data = [];
@@ -765,7 +769,7 @@ class Sales extends Secure_Controller
$data['error_message'] = lang('Sales.transaction_failed');
} else {
$data['barcode'] = $this->barcode_lib->generate_receipt_barcode($data['sale_id']);
echo view('sales/' . $invoice_view, $data);
return view('sales/' . $invoice_view, $data);
$this->sale_lib->clear_all();
}
}
@@ -799,7 +803,7 @@ class Sales extends Secure_Controller
$data['barcode'] = null;
echo view('sales/work_order', $data);
return view('sales/work_order', $data);
$this->sale_lib->clear_mode();
$this->sale_lib->clear_all();
}
@@ -827,7 +831,7 @@ class Sales extends Secure_Controller
$data['cart'] = $this->sale_lib->sort_and_filter_cart($data['cart']);
$data['barcode'] = null;
echo view('sales/quote', $data);
return view('sales/quote', $data);
$this->sale_lib->clear_mode();
$this->sale_lib->clear_all();
}
@@ -850,7 +854,7 @@ class Sales extends Secure_Controller
$data['error_message'] = lang('Sales.transaction_failed');
} else {
$data['barcode'] = $this->barcode_lib->generate_receipt_barcode($data['sale_id']);
echo view('sales/receipt', $data);
return view('sales/receipt', $data);
$this->sale_lib->clear_all();
}
}
@@ -861,10 +865,10 @@ class Sales extends Secure_Controller
*
* @param int $sale_id
* @param string $type
* @return bool
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function getSendPdf(int $sale_id, string $type = 'invoice'): bool
public function getSendPdf(int $sale_id, string $type = 'invoice'): ResponseInterface
{
$sale_data = $this->_load_sale_data($sale_id);
@@ -899,21 +903,19 @@ class Sales extends Secure_Controller
$message = lang($result ? "Sales." . $type . "_sent" : "Sales." . $type . "_unsent") . ' ' . $to;
}
echo json_encode(['success' => $result, 'message' => $message, 'id' => $sale_id]);
$this->sale_lib->clear_all();
return $result;
return $this->response->setJSON(['success' => $result, 'message' => $message, 'id' => $sale_id]);
}
/**
* Emails sales receipt to customer. Used in app/Views/sales/receipt.php
*
* @param int $sale_id
* @return bool
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function getSendReceipt(int $sale_id): bool
public function getSendReceipt(int $sale_id): ResponseInterface
{
$sale_data = $this->_load_sale_data($sale_id);
@@ -922,6 +924,13 @@ class Sales extends Secure_Controller
if (!empty($sale_data['customer_email'])) {
$sale_data['barcode'] = $this->barcode_lib->generate_receipt_barcode($sale_data['sale_id']);
$sale_data['img_tag'] = '';
$logo_path = FCPATH . 'uploads/' . $this->config['company_logo'];
if (!empty($this->config['company_logo']) && file_exists($logo_path)) {
$logo_data = base64_encode(file_get_contents($logo_path));
$sale_data['img_tag'] = '<img id="image" src="data:image/png;base64,' . $logo_data . '" alt="company_logo">';
}
$to = $sale_data['customer_email'];
$subject = lang('Sales.receipt');
@@ -934,11 +943,9 @@ class Sales extends Secure_Controller
$message = lang($result ? 'Sales.receipt_sent' : 'Sales.receipt_unsent') . ' ' . $to;
}
echo json_encode(['success' => $result, 'message' => $message, 'id' => $sale_id]);
$this->sale_lib->clear_all();
return $result;
return $this->response->setJSON(['success' => $result, 'message' => $message, 'id' => $sale_id]);
}
/**
@@ -1109,7 +1116,7 @@ class Sales extends Secure_Controller
* @param array $data
* @return void
*/
private function _reload(array $data = []): void // TODO: Hungarian notation
private function _reload(array $data = []): ResponseInterface|string // TODO: Hungarian notation
{
$sale_id = $this->session->get('sale_id'); // TODO: This variable is never used
@@ -1215,40 +1222,47 @@ class Sales extends Secure_Controller
$data['customer_required'] = lang('Sales.customer_optional');
}
echo view("sales/register", $data);
return view("sales/register", $data);
}
/**
* Load the sales receipt for a sale. Used in app/Views/sales/form.php
*
* @param int $sale_id
* @return void
* @return string
* @noinspection PhpUnused
*/
public function getReceipt(int $sale_id): void
public function getReceipt(int $sale_id): string
{
$data = $this->_load_sale_data($sale_id);
echo view('sales/receipt', $data);
$this->sale_lib->clear_all();
return view('sales/receipt', $data);
}
/**
* Loads the sales invoice for a sale. Used in app/Views/sales/form.php
*
* @param int $sale_id
* @return void
* @return string
* @noinspection PhpUnused
*/
public function getInvoice(int $sale_id): void
public function getInvoice(int $sale_id): string
{
$data = $this->_load_sale_data($sale_id);
echo view('sales/' . $data['invoice_view'], $data);
$this->sale_lib->clear_all();
return view('sales/' . $data['invoice_view'], $data);
}
/**
* Edits an existing sale or work order. Used in app/Views/sales/form.php
*
* @param int $sale_id
* @return void
* @return string
* @throws ReflectionException
*/
public function getEdit(int $sale_id): void
public function getEdit(int $sale_id): string
{
$data = [];
@@ -1293,30 +1307,32 @@ class Sales extends Secure_Controller
$data['new_payment_options'] = $payment_options;
echo view('sales/form', $data);
return view('sales/form', $data);
}
/**
* @param int $sale_id
* @return ResponseInterface
* @throws ReflectionException
*/
public function postDelete(int $sale_id = NEW_ENTRY, bool $update_inventory = true): void
public function postDelete(int $sale_id = NEW_ENTRY, bool $update_inventory = true): ResponseInterface
{
$employee_id = $this->employee->get_logged_in_employee_info()->person_id;
$has_grant = $this->employee->has_grant('sales_delete', $employee_id);
if (!$has_grant) {
echo json_encode(['success' => false, 'message' => lang('Sales.not_authorized')]);
return $this->response->setJSON(['success' => false, 'message' => lang('Sales.not_authorized')]);
} else {
$sale_ids = $sale_id == NEW_ENTRY ? $this->request->getPost('ids', FILTER_SANITIZE_NUMBER_INT) : [$sale_id];
if ($this->sale->delete_list($sale_ids, $employee_id, $update_inventory)) {
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Sales.successfully_deleted') . ' ' . count($sale_ids) . ' ' . lang('Sales.one_or_multiple'),
'ids' => $sale_ids
]);
} else {
echo json_encode(['success' => false, 'message' => lang('Sales.unsuccessfully_deleted')]);
return $this->response->setJSON(['success' => false, 'message' => lang('Sales.unsuccessfully_deleted')]);
}
}
}
@@ -1324,26 +1340,26 @@ class Sales extends Secure_Controller
/**
* @param int $sale_id
* @param bool $update_inventory
* @return void
* @return ResponseInterface
*/
public function restore(int $sale_id = NEW_ENTRY, bool $update_inventory = true): void
public function restore(int $sale_id = NEW_ENTRY, bool $update_inventory = true): ResponseInterface
{
$employee_id = $this->employee->get_logged_in_employee_info()->person_id;
$has_grant = $this->employee->has_grant('sales_delete', $employee_id);
if (!$has_grant) {
echo json_encode(['success' => false, 'message' => lang('Sales.not_authorized')]);
return $this->response->setJSON(['success' => false, 'message' => lang('Sales.not_authorized')]);
} else {
$sale_ids = $sale_id == NEW_ENTRY ? $this->request->getPost('ids', FILTER_SANITIZE_NUMBER_INT) : [$sale_id];
if ($this->sale->restore_list($sale_ids, $employee_id, $update_inventory)) {
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Sales.successfully_restored') . ' ' . count($sale_ids) . ' ' . lang('Sales.one_or_multiple'),
'ids' => $sale_ids
]);
} else {
echo json_encode(['success' => false, 'message' => lang('Sales.unsuccessfully_restored')]);
return $this->response->setJSON(['success' => false, 'message' => lang('Sales.unsuccessfully_restored')]);
}
}
}
@@ -1352,9 +1368,10 @@ class Sales extends Secure_Controller
* This saves the sale from the update sale view (sales/form).
* It only updates the sales table and payments.
* @param int $sale_id
* @return ResponseInterface
* @throws ReflectionException
*/
public function postSave(int $sale_id = NEW_ENTRY): void
public function postSave(int $sale_id = NEW_ENTRY): ResponseInterface
{
$newdate = $this->request->getPost('date', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$employee_id = $this->employee->get_logged_in_employee_info()->person_id;
@@ -1435,9 +1452,9 @@ class Sales extends Secure_Controller
$inventory->update('POS ' . $sale_id, ['trans_date' => $sale_time]); // TODO: Reflection Exception
if ($this->sale->update($sale_id, $sale_data)) {
echo json_encode(['success' => true, 'message' => lang('Sales.successfully_updated'), 'id' => $sale_id]);
return $this->response->setJSON(['success' => true, 'message' => lang('Sales.successfully_updated'), 'id' => $sale_id]);
} else {
echo json_encode(['success' => false, 'message' => lang('Sales.unsuccessfully_updated'), 'id' => $sale_id]);
return $this->response->setJSON(['success' => false, 'message' => lang('Sales.unsuccessfully_updated'), 'id' => $sale_id]);
}
}
@@ -1447,10 +1464,11 @@ class Sales extends Secure_Controller
* Work orders can be canceled but are not physically removed from the sales history.
* Used in app/Views/sales/register.php
*
* @return ResponseInterface
* @throws ReflectionException
* @noinspection PhpUnused
*/
public function postCancel(): void
public function postCancel(): ResponseInterface|string
{
$sale_id = $this->sale_lib->get_sale_id();
if ($sale_id != NEW_ENTRY && $sale_id != '') {
@@ -1472,32 +1490,32 @@ class Sales extends Secure_Controller
}
$this->sale_lib->clear_all();
$this->_reload(); // TODO: Hungarian notation
return $this->_reload();
}
/**
* Discards the suspended sale. Used in app/Views/sales/quote.php
*
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function getDiscardSuspendedSale(): void
public function getDiscardSuspendedSale(): ResponseInterface|string
{
$suspended_id = $this->sale_lib->get_suspended_id();
$this->sale_lib->clear_all();
$this->sale->delete_suspended_sale($suspended_id);
$this->_reload(); // TODO: Hungarian notation
return $this->_reload();
}
/**
* Suspend the current sale.
* If the current sale is already suspended then update the existing suspended sale otherwise create
* it as a new suspended sale. Used in app/Views/sales/register.php.
* it as a new suspended sale. Used in app/Views/sales/register.php
*
* @throws ReflectionException
* @return ResponseInterface|string
* @noinspection PhpUnused
*/
public function postSuspend(): void
public function postSuspend(): ResponseInterface|string
{
$sale_id = $this->sale_lib->get_sale_id();
$dinner_table = $this->sale_lib->get_dinner_table();
@@ -1528,28 +1546,29 @@ class Sales extends Secure_Controller
$this->sale_lib->clear_all();
$this->_reload($data); // TODO: Hungarian notation
return $this->_reload($data);
}
/**
* List suspended sales
* @return string
*/
public function getSuspended(): void
public function getSuspended(): string
{
$data = [];
$customer_id = $this->sale_lib->get_customer();
$data['suspended_sales'] = $this->sale->get_all_suspended($customer_id);
echo view('sales/suspended', $data);
return view('sales/suspended', $data);
}
/**
* Unsuspended sales are now left in the tables and are only removed
* when they are intentionally cancelled. Used in app/Views/sales/suspended.php.
*
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postUnsuspend(): void
public function postUnsuspend(): ResponseInterface|string
{
$sale_id = $this->request->getPost('suspended_sale_id', FILTER_SANITIZE_NUMBER_INT);
$this->sale_lib->clear_all();
@@ -1561,32 +1580,32 @@ class Sales extends Secure_Controller
// Set current register mode to reflect that of unsuspended order type
$this->change_register_mode($this->sale_lib->get_sale_type());
$this->_reload(); // TODO: Hungarian notation
return $this->_reload();
}
/**
* Show Keyboard shortcut modal. Used in app/Views/sales/register.php
*
* @return void
* @return string
* @noinspection PhpUnused
*/
public function getSalesKeyboardHelp(): void
public function getSalesKeyboardHelp(): string
{
echo view('sales/help');
return view('sales/help');
}
/**
* Check the validity of an invoice number. Used in app/Views/sales/form.php.
*
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postCheckInvoiceNumber(): void
public function postCheckInvoiceNumber(): ResponseInterface
{
$sale_id = $this->request->getPost('sale_id', FILTER_SANITIZE_NUMBER_INT);
$invoice_number = $this->request->getPost('invoice_number', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$exists = !empty($invoice_number) && $this->sale->check_invoice_number_exists($invoice_number, $sale_id);
echo !$exists ? 'true' : 'false';
return $this->response->setJSON(!$exists ? 'true' : 'false');
}
/**
@@ -1613,10 +1632,10 @@ class Sales extends Secure_Controller
/**
* Update the item number in the register. Used in app/Views/sales/register.php
*
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postChangeItemNumber(): void
public function postChangeItemNumber(): ResponseInterface
{
$item_id = $this->request->getPost('item_id', FILTER_SANITIZE_NUMBER_INT);
$item_number = $this->request->getPost('item_number', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
@@ -1632,10 +1651,10 @@ class Sales extends Secure_Controller
/**
* Change a given item name. Used in app/Views/sales/register.php.
*
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postChangeItemName(): void
public function postChangeItemName(): ResponseInterface
{
$item_id = $this->request->getPost('item_id', FILTER_SANITIZE_NUMBER_INT);
$name = $this->request->getPost('item_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
@@ -1655,10 +1674,10 @@ class Sales extends Secure_Controller
/**
* Update the given item description. Used in app/Views/sales/register.php
*
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postChangeItemDescription(): void
public function postChangeItemDescription(): ResponseInterface
{
$item_id = $this->request->getPost('item_id', FILTER_SANITIZE_NUMBER_INT);
$description = $this->request->getPost('item_description', FILTER_SANITIZE_FULL_SPECIAL_CHARS);

View File

@@ -4,7 +4,7 @@ namespace App\Controllers;
use App\Models\Employee;
use App\Models\Module;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Model;
use CodeIgniter\Session\Session;
use Config\OSPOS;
@@ -85,18 +85,17 @@ class Secure_Controller extends BaseController
/**
* AJAX function used to confirm whether values sent in the request are numeric
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function getCheckNumeric(): void
public function getCheckNumeric(): ResponseInterface
{
foreach ($this->request->getGet() as $value) {
if (parse_decimals($value) === false) {
echo 'false';
return;
return $this->response->setJSON('false');
}
}
echo 'true';
return $this->response->setJSON('true');
}
/**

View File

@@ -3,6 +3,7 @@
namespace App\Controllers;
use App\Models\Supplier;
use CodeIgniter\HTTP\ResponseInterface;
use Config\Services;
class Suppliers extends Persons
@@ -17,33 +18,33 @@ class Suppliers extends Persons
}
/**
* @return void
* @return string
*/
public function getIndex(): void
public function getIndex(): string
{
$data['table_headers'] = get_suppliers_manage_table_headers();
echo view('people/manage', $data);
return view('people/manage', $data);
}
/**
* Gets one row for a supplier manage table. This is called using AJAX to update one row.
* @param $row_id
* @return void
* @return ResponseInterface
*/
public function getRow($row_id): void
public function getRow($row_id): ResponseInterface
{
$data_row = get_supplier_data_row($this->supplier->get_info($row_id));
$data_row['category'] = $this->supplier->get_category_name($data_row['category']);
echo json_encode($data_row);
return $this->response->setJSON($data_row);
}
/**
* Returns Supplier table data rows. This will be called with AJAX.
* @return void
**/
public function getSearch(): void
public function getSearch(): ResponseInterface
{
$search = $this->request->getGet('search');
$limit = $this->request->getGet('limit', FILTER_SANITIZE_NUMBER_INT);
@@ -62,38 +63,39 @@ class Suppliers extends Persons
$data_rows[] = $row;
}
echo json_encode(['total' => $total_rows, 'rows' => $data_rows]);
return $this->response->setJSON(['total' => $total_rows, 'rows' => $data_rows]);
}
/**
* Gives search suggestions based on what is being searched for
* @return ResponseInterface
**/
public function getSuggest(): void
public function getSuggest(): ResponseInterface
{
$search = $this->request->getGet('term');
$suggestions = $this->supplier->get_search_suggestions($search, true);
echo json_encode($suggestions);
return $this->response->setJSON($suggestions);
}
/**
* @return void
* @return ResponseInterface
*/
public function suggest_search(): void
public function suggest_search(): ResponseInterface
{
$search = $this->request->getPost('term');
$suggestions = $this->supplier->get_search_suggestions($search, false);
echo json_encode($suggestions);
return $this->response->setJSON($suggestions);
}
/**
* Loads the supplier edit form
*
* @param int $supplier_id
* @return void
* @return string
*/
public function getView(int $supplier_id = NEW_ENTRY): void
public function getView(int $supplier_id = NEW_ENTRY): string
{
$info = $this->supplier->get_info($supplier_id);
foreach (get_object_vars($info) as $property => $value) {
@@ -102,16 +104,16 @@ class Suppliers extends Persons
$data['person_info'] = $info;
$data['categories'] = $this->supplier->get_categories();
echo view("suppliers/form", $data);
return view("suppliers/form", $data);
}
/**
* Inserts/updates a supplier
*
* @param int $supplier_id
* @return void
* @return ResponseInterface
*/
public function postSave(int $supplier_id = NEW_ENTRY): void
public function postSave(int $supplier_id = NEW_ENTRY): ResponseInterface
{
$first_name = $this->request->getPost('first_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS); // TODO: Duplicate code
$last_name = $this->request->getPost('last_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
@@ -147,21 +149,21 @@ class Suppliers extends Persons
if ($this->supplier->save_supplier($person_data, $supplier_data, $supplier_id)) {
// New supplier
if ($supplier_id == NEW_ENTRY) {
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Suppliers.successful_adding') . ' ' . $supplier_data['company_name'],
'id' => $supplier_data['person_id']
]);
} else { // Existing supplier
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Suppliers.successful_updating') . ' ' . $supplier_data['company_name'],
'id' => $supplier_id
]);
}
} else { // Failure
echo json_encode([
return $this->response->setJSON([
'success' => false,
'message' => lang('Suppliers.error_adding_updating') . ' ' . $supplier_data['company_name'],
'id' => NEW_ENTRY
@@ -172,19 +174,19 @@ class Suppliers extends Persons
/**
* This deletes suppliers from the suppliers table
*
* @return void
* @return ResponseInterface
*/
public function postDelete(): void
public function postDelete(): ResponseInterface
{
$suppliers_to_delete = $this->request->getPost('ids', FILTER_SANITIZE_NUMBER_INT);
if ($this->supplier->delete_list($suppliers_to_delete)) {
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Suppliers.successful_deleted') . ' ' . count($suppliers_to_delete) . ' ' . lang('Suppliers.one_or_multiple')
]);
} else {
echo json_encode(['success' => false, 'message' => lang('Suppliers.cannot_be_deleted')]);
return $this->response->setJSON(['success' => false, 'message' => lang('Suppliers.cannot_be_deleted')]);
}
}
}

View File

@@ -3,6 +3,7 @@
namespace App\Controllers;
use App\Models\Tax_category;
use CodeIgniter\HTTP\ResponseInterface;
use Config\Services;
/**
@@ -20,13 +21,13 @@ class Tax_categories extends Secure_Controller
}
/**
* @return void
* @return string
*/
public function getIndex(): void
public function getIndex(): string
{
$data['tax_categories_table_headers'] = get_tax_categories_table_headers();
echo view('taxes/tax_categories', $data);
return view('taxes/tax_categories', $data);
}
/**
@@ -34,7 +35,7 @@ class Tax_categories extends Secure_Controller
*
* @return void
*/
public function getSearch(): void
public function getSearch(): ResponseInterface
{
$search = $this->request->getGet('search');
$limit = $this->request->getGet('limit', FILTER_SANITIZE_NUMBER_INT);
@@ -50,37 +51,37 @@ class Tax_categories extends Secure_Controller
$data_rows[] = get_tax_categories_data_row($tax_category);
}
echo json_encode(['total' => $total_rows, 'rows' => $data_rows]);
return $this->response->setJSON(['total' => $total_rows, 'rows' => $data_rows]);
}
/**
* @param $row_id
* @return void
* @return ResponseInterface
*/
public function getRow($row_id): void
public function getRow($row_id): ResponseInterface
{
$data_row = get_tax_categories_data_row($this->tax_category->get_info($row_id));
echo json_encode($data_row);
return $this->response->setJSON($data_row);
}
/**
* @param int $tax_category_id
* @return void
* @return string
*/
public function getView(int $tax_category_id = NEW_ENTRY): void
public function getView(int $tax_category_id = NEW_ENTRY): string
{
$data['tax_category_info'] = $this->tax_category->get_info($tax_category_id);
echo view("taxes/tax_category_form", $data);
return view("taxes/tax_category_form", $data);
}
/**
* @param int $tax_category_id
* @return void
* @return ResponseInterface
*/
public function postSave(int $tax_category_id = NEW_ENTRY): void
public function postSave(int $tax_category_id = NEW_ENTRY): ResponseInterface
{
$tax_category_data = [
'tax_category' => $this->request->getPost('tax_category', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
@@ -91,20 +92,20 @@ class Tax_categories extends Secure_Controller
if ($this->tax_category->save_value($tax_category_data, $tax_category_id)) {
// New tax_category_id
if ($tax_category_id == NEW_ENTRY) {
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Tax_categories.successful_adding'),
'id' => $tax_category_data['tax_category_id']
]);
} else {
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Tax_categories.successful_updating'),
'id' => $tax_category_id
]);
}
} else {
echo json_encode([
return $this->response->setJSON([
'success' => false,
'message' => lang('Tax_categories.error_adding_updating') . ' ' . $tax_category_data['tax_category'],
'id' => NEW_ENTRY
@@ -113,19 +114,19 @@ class Tax_categories extends Secure_Controller
}
/**
* @return void
* @return ResponseInterface
*/
public function postDelete(): void
public function postDelete(): ResponseInterface
{
$tax_categories_to_delete = $this->request->getPost('ids', FILTER_SANITIZE_NUMBER_INT);
if ($this->tax_category->delete_list($tax_categories_to_delete)) {
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Tax_categories.successful_deleted') . ' ' . count($tax_categories_to_delete) . ' ' . lang('Tax_categories.one_or_multiple')
]);
} else {
echo json_encode(['success' => false, 'message' => lang('Tax_categories.cannot_be_deleted')]);
return $this->response->setJSON(['success' => false, 'message' => lang('Tax_categories.cannot_be_deleted')]);
}
}
}

View File

@@ -3,6 +3,7 @@
namespace App\Controllers;
use App\Models\Tax_code;
use CodeIgniter\HTTP\ResponseInterface;
use Config\Services;
/**
@@ -22,11 +23,11 @@ class Tax_codes extends Secure_Controller
/**
* @return void
* @return string
*/
public function getIndex(): void
public function getIndex(): string
{
echo view('taxes/tax_codes', $this->get_data());
return view('taxes/tax_codes', $this->get_data());
}
/**
@@ -44,7 +45,7 @@ class Tax_codes extends Secure_Controller
*
* @return void
*/
public function getSearch(): void
public function getSearch(): ResponseInterface
{
$search = $this->request->getGet('search');
$limit = $this->request->getGet('limit', FILTER_SANITIZE_NUMBER_INT);
@@ -61,37 +62,37 @@ class Tax_codes extends Secure_Controller
$data_rows[] = get_tax_code_data_row($tax_code);
}
echo json_encode(['total' => $total_rows, 'rows' => $data_rows]);
return $this->response->setJSON(['total' => $total_rows, 'rows' => $data_rows]);
}
/**
* @param int $row_id
* @return void
* @return ResponseInterface
*/
public function getRow(int $row_id): void
public function getRow(int $row_id): ResponseInterface
{
$data_row = get_tax_code_data_row($this->tax_code->get_info($row_id));
echo json_encode($data_row);
return $this->response->setJSON($data_row);
}
/**
* @param int $tax_code_id
* @return void
* @return string
*/
public function getView(int $tax_code_id = NEW_ENTRY): void
public function getView(int $tax_code_id = NEW_ENTRY): string
{
$data['tax_code_info'] = $this->tax_code->get_info($tax_code_id);
echo view("taxes/tax_code_form", $data);
return view("taxes/tax_code_form", $data);
}
/**
* @param int $tax_code_id
* @return void
* @return ResponseInterface
*/
public function postSave(int $tax_code_id = NEW_ENTRY): void
public function postSave(int $tax_code_id = NEW_ENTRY): ResponseInterface
{
$tax_code_data = [
'tax_code' => $this->request->getPost('tax_code', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
@@ -102,20 +103,20 @@ class Tax_codes extends Secure_Controller
if ($this->tax_code->save($tax_code_data)) {
if ($tax_code_id == NEW_ENTRY) {
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Tax_codes.successful_adding'),
'id' => $tax_code_data['tax_code_id']
]);
} else {
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Tax_codes.successful_updating'),
'id' => $tax_code_id
]);
}
} else {
echo json_encode([
return $this->response->setJSON([
'success' => false,
'message' => lang('Tax_codes.error_adding_updating') . ' ' . $tax_code_data['tax_code_id'],
'id' => NEW_ENTRY
@@ -124,19 +125,19 @@ class Tax_codes extends Secure_Controller
}
/**
* @return void
* @return ResponseInterface
*/
public function postDelete(): void
public function postDelete(): ResponseInterface
{
$tax_codes_to_delete = $this->request->getPost('ids', FILTER_SANITIZE_NUMBER_INT);
if ($this->tax_code->delete_list($tax_codes_to_delete)) {
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Tax_codes.successful_deleted') . ' ' . count($tax_codes_to_delete) . ' ' . lang('Tax_codes.one_or_multiple')
]);
} else {
echo json_encode(['success' => false, 'message' => lang('Tax_codes.cannot_be_deleted')]);
return $this->response->setJSON(['success' => false, 'message' => lang('Tax_codes.cannot_be_deleted')]);
}
}
}

View File

@@ -3,6 +3,7 @@
namespace App\Controllers;
use App\Models\Tax_jurisdiction;
use CodeIgniter\HTTP\ResponseInterface;
use Config\Services;
/**
@@ -23,13 +24,13 @@ class Tax_jurisdictions extends Secure_Controller
/**
* @return void
* @return string
*/
public function getIndex(): void
public function getIndex(): string
{
$data['table_headers'] = get_tax_jurisdictions_table_headers();
echo view('taxes/tax_jurisdictions', $data);
return view('taxes/tax_jurisdictions', $data);
}
/**
@@ -37,7 +38,7 @@ class Tax_jurisdictions extends Secure_Controller
*
* @return void
*/
public function getSearch(): void
public function getSearch(): ResponseInterface
{
$search = $this->request->getGet('search');
$limit = $this->request->getGet('limit', FILTER_SANITIZE_NUMBER_INT);
@@ -53,37 +54,37 @@ class Tax_jurisdictions extends Secure_Controller
$data_rows[] = get_tax_jurisdictions_data_row($tax_jurisdiction);
}
echo json_encode(['total' => $total_rows, 'rows' => $data_rows]);
return $this->response->setJSON(['total' => $total_rows, 'rows' => $data_rows]);
}
/**
* @param int $row_id
* @return void
* @return ResponseInterface
*/
public function getRow(int $row_id): void
public function getRow(int $row_id): ResponseInterface
{
$data_row = get_tax_jurisdictions_data_row($this->tax_jurisdiction->get_info($row_id));
echo json_encode($data_row);
return $this->response->setJSON($data_row);
}
/**
* @param int $tax_jurisdiction_id
* @return void
* @return string
*/
public function getView(int $tax_jurisdiction_id = NEW_ENTRY): void
public function getView(int $tax_jurisdiction_id = NEW_ENTRY): string
{
$data['tax_jurisdiction_info'] = $this->tax_jurisdiction->get_info($tax_jurisdiction_id);
echo view("taxes/tax_jurisdiction_form", $data);
return view("taxes/tax_jurisdiction_form", $data);
}
/**
* @param int $jurisdiction_id
* @return void
* @return ResponseInterface
*/
public function postSave(int $jurisdiction_id = NEW_ENTRY): void
public function postSave(int $jurisdiction_id = NEW_ENTRY): ResponseInterface
{
$tax_jurisdiction_data = [
'jurisdiction_name' => $this->request->getPost('jurisdiction_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
@@ -92,20 +93,20 @@ class Tax_jurisdictions extends Secure_Controller
if ($this->tax_jurisdiction->save_value($tax_jurisdiction_data)) {
if ($jurisdiction_id == NEW_ENTRY) {
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Tax_jurisdictions.successful_adding'),
'id' => $tax_jurisdiction_data['jurisdiction_id']
]);
} else {
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Tax_jurisdictions.successful_updating'),
'id' => $jurisdiction_id
]);
}
} else {
echo json_encode([
return $this->response->setJSON([
'success' => false,
'message' => lang('Tax_jurisdictions.error_adding_updating') . ' ' . $tax_jurisdiction_data['jurisdiction_name'],
'id' => NEW_ENTRY
@@ -114,19 +115,19 @@ class Tax_jurisdictions extends Secure_Controller
}
/**
* @return void
* @return ResponseInterface
*/
public function postDelete(): void
public function postDelete(): ResponseInterface
{
$tax_jurisdictions_to_delete = $this->request->getPost('ids', FILTER_SANITIZE_NUMBER_INT);
if ($this->tax_jurisdiction->delete_list($tax_jurisdictions_to_delete)) {
echo json_encode([
return $this->response->setJSON([
'success' => true,
'message' => lang('Tax_jurisdictions.successful_deleted') . ' ' . count($tax_jurisdictions_to_delete) . ' ' . lang('Tax_jurisdictions.one_or_multiple')
]);
} else {
echo json_encode(['success' => false, 'message' => lang('Tax_jurisdictions.cannot_be_deleted')]);
return $this->response->setJSON(['success' => false, 'message' => lang('Tax_jurisdictions.cannot_be_deleted')]);
}
}
}

View File

@@ -8,6 +8,7 @@ use App\Models\Tax;
use App\Models\Tax_category;
use App\Models\Tax_code;
use App\Models\Tax_jurisdiction;
use CodeIgniter\HTTP\ResponseInterface;
use Config\OSPOS;
use Config\Services;
@@ -36,9 +37,9 @@ class Taxes extends Secure_Controller
}
/**
* @return void
* @return string
*/
public function getIndex(): void
public function getIndex(): string
{
$data['tax_codes'] = $this->tax_code->get_all()->getResultArray();
if (count($data['tax_codes']) == 0) {
@@ -67,7 +68,7 @@ class Taxes extends Secure_Controller
$data['tax_type_options'] = $this->tax_lib->get_tax_type_options($data['default_tax_type']);
echo view('taxes/manage', $data);
return view('taxes/manage', $data);
}
/**
@@ -75,7 +76,7 @@ class Taxes extends Secure_Controller
*
* @return void
*/
public function getSearch(): void
public function getSearch(): ResponseInterface
{
$search = $this->request->getGet('search');
$limit = $this->request->getGet('limit', FILTER_SANITIZE_NUMBER_INT);
@@ -92,50 +93,50 @@ class Taxes extends Secure_Controller
$data_rows[] = get_tax_rates_data_row($tax_rate_row);
}
echo json_encode(['total' => $total_rows, 'rows' => $data_rows]);
return $this->response->setJSON(['total' => $total_rows, 'rows' => $data_rows]);
}
/**
* Gives search suggestions based on what is being searched for
* @return ResponseInterface
*/
public function suggest_search(): void
public function suggest_search(): ResponseInterface
{
$search = $this->request->getPost('term');
$suggestions = $this->tax->get_search_suggestions($search); // TODO: There is no get_search_suggestions function in the tax model
echo json_encode($suggestions);
return $this->response->setJSON($suggestions);
}
/**
* Provides list of tax categories to select from
*
* @return void
* @return ResponseInterface
*/
public function suggest_tax_categories(): void
public function suggest_tax_categories(): ResponseInterface
{
$search = $this->request->getPost('term');
$suggestions = $this->tax_category->get_tax_category_suggestions($search);
echo json_encode($suggestions);
return $this->response->setJSON($suggestions);
}
/**
* @param int $row_id
* @return void
* @return ResponseInterface
*/
public function getRow(int $row_id): void
public function getRow(int $row_id): ResponseInterface
{
$data_row = get_tax_rates_data_row($this->tax->get_info($row_id));
echo json_encode($data_row);
return $this->response->setJSON($data_row);
}
/**
* @param int $tax_code
* @return void
* @return string
*/
public function getView_tax_codes(int $tax_code = NEW_ENTRY): void
public function getView_tax_codes(int $tax_code = NEW_ENTRY): string
{
$tax_code_info = $this->tax->get_info($tax_code);
@@ -192,15 +193,15 @@ class Taxes extends Secure_Controller
$data['tax_rates'] = $tax_rates;
echo view('taxes/tax_code_form', $data);
return view('taxes/tax_code_form', $data);
}
/**
* @param int $tax_rate_id
* @return void
* @return string
*/
public function getView(int $tax_rate_id = NEW_ENTRY): void
public function getView(int $tax_rate_id = NEW_ENTRY): string
{
$tax_rate_info = $this->tax->get_info($tax_rate_id);
@@ -226,14 +227,14 @@ class Taxes extends Secure_Controller
$data['tax_rate'] = $tax_rate_info->tax_rate;
}
echo view('taxes/tax_rates_form', $data);
return view('taxes/tax_rates_form', $data);
}
/**
* @param int $tax_code
* @return void
* @return string
*/
public function getView_tax_categories(int $tax_code = NEW_ENTRY): void // TODO: This appears to be called no where in the code.
public function getView_tax_categories(int $tax_code = NEW_ENTRY): string // TODO: This appears to be called no where in the code.
{
$tax_code_info = $this->tax->get_info($tax_code); // TODO: Duplicated Code
@@ -290,14 +291,14 @@ class Taxes extends Secure_Controller
$data['tax_rates'] = $tax_rates;
echo view('taxes/tax_category_form', $data);
return view('taxes/tax_category_form', $data);
}
/**
* @param int $tax_code
* @return void
* @return string
*/
public function getView_tax_jurisdictions(int $tax_code = NEW_ENTRY): void // TODO: This appears to be called no where in the code.
public function getView_tax_jurisdictions(int $tax_code = NEW_ENTRY): string // TODO: This appears to be called no where in the code.
{
$tax_code_info = $this->tax->get_info($tax_code); // TODO: Duplicated code
@@ -354,7 +355,7 @@ class Taxes extends Secure_Controller
$data['tax_rates'] = $tax_rates;
echo view('taxes/tax_jurisdiction_form', $data);
return view('taxes/tax_jurisdiction_form', $data);
}
/**
@@ -367,9 +368,9 @@ class Taxes extends Secure_Controller
/**
* @param int $tax_rate_id
* @return void
* @return ResponseInterface
*/
public function postSave(int $tax_rate_id = NEW_ENTRY): void
public function postSave(int $tax_rate_id = NEW_ENTRY): ResponseInterface
{
$tax_category_id = $this->request->getPost('rate_tax_category_id', FILTER_SANITIZE_NUMBER_INT);
$tax_rate = parse_tax($this->request->getPost('tax_rate'));
@@ -388,50 +389,50 @@ class Taxes extends Secure_Controller
if ($this->tax->save_value($tax_rate_data, $tax_rate_id)) {
if ($tax_rate_id == NEW_ENTRY) { // TODO: this needs to be replaced with ternary notation
echo json_encode(['success' => true, 'message' => lang('Taxes.tax_rate_successfully_added')]);
return $this->response->setJSON(['success' => true, 'message' => lang('Taxes.tax_rate_successfully_added')]);
} else { // Existing tax_code
echo json_encode(['success' => true, 'message' => lang('Taxes.tax_rate_successful_updated')]);
return $this->response->setJSON(['success' => true, 'message' => lang('Taxes.tax_rate_successful_updated')]);
}
} else {
echo json_encode(['success' => false, 'message' => lang('Taxes.tax_rate_error_adding_updating')]);
return $this->response->setJSON(['success' => false, 'message' => lang('Taxes.tax_rate_error_adding_updating')]);
}
}
/**
* @return void
* @return ResponseInterface
*/
public function postDelete(): void
public function postDelete(): ResponseInterface
{
$tax_codes_to_delete = $this->request->getPost('ids', FILTER_SANITIZE_NUMBER_INT);
if ($this->tax->delete_list($tax_codes_to_delete)) { // TODO: this needs to be replaced with ternary notation
echo json_encode(['success' => true, 'message' => lang('Taxes.tax_code_successful_deleted')]);
return $this->response->setJSON(['success' => true, 'message' => lang('Taxes.tax_code_successful_deleted')]);
} else {
echo json_encode(['success' => false, 'message' => lang('Taxes.tax_code_cannot_be_deleted')]);
return $this->response->setJSON(['success' => false, 'message' => lang('Taxes.tax_code_cannot_be_deleted')]);
}
}
/**
* Get search suggestions for tax codes. Used in app/Views/customers/form.php
*
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function getSuggestTaxCodes(): void
public function getSuggestTaxCodes(): ResponseInterface
{
$search = $this->request->getPostGet('term');
$suggestions = $this->tax_code->get_tax_codes_search_suggestions($search);
echo json_encode($suggestions);
return $this->response->setJSON($suggestions);
}
/**
* Saves Tax Codes. Used in app/Views/taxes/tax_codes.php
*
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postSave_tax_codes(): void
public function postSave_tax_codes(): ResponseInterface
{
$tax_code_id = $this->request->getPost('tax_code_id', FILTER_SANITIZE_NUMBER_INT);
$tax_code = $this->request->getPost('tax_code', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
@@ -452,7 +453,7 @@ class Taxes extends Secure_Controller
$success = $this->tax_code->save_tax_codes($array_save);
echo json_encode([
return $this->response->setJSON([
'success' => $success,
'message' => lang('Taxes.tax_codes_saved_' . ($success ? '' : 'un') . 'successfully')
]);
@@ -461,10 +462,10 @@ class Taxes extends Secure_Controller
/**
* Saves given tax jurisdiction. Used in app/Views/taxes/tax_jurisdictions.php.
*
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postSave_tax_jurisdictions(): void
public function postSave_tax_jurisdictions(): ResponseInterface
{
$jurisdiction_id = $this->request->getPost('jurisdiction_id', FILTER_SANITIZE_NUMBER_INT);
$jurisdiction_name = $this->request->getPost('jurisdiction_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
@@ -489,11 +490,10 @@ class Taxes extends Secure_Controller
];
if (in_array($tax_group[$key], $unique_tax_groups)) { // TODO: This can be replaced with `in_array($tax_group[$key], $unique_tax_groups)`
echo json_encode([
return $this->response->setJSON([
'success' => false,
'message' => lang('Taxes.tax_group_not_unique', [$tax_group[$key]])
]);
return;
} else {
$unique_tax_groups[] = $tax_group[$key];
}
@@ -501,7 +501,7 @@ class Taxes extends Secure_Controller
$success = $this->tax_jurisdiction->save_jurisdictions($array_save);
echo json_encode([
return $this->response->setJSON([
'success' => $success,
'message' => lang('Taxes.tax_jurisdictions_saved_' . ($success ? '' : 'un') . 'successfully')
]);
@@ -510,10 +510,10 @@ class Taxes extends Secure_Controller
/**
* Saves tax categories. Used in app/Views/taxes/tax_categories.php
*
* @return void
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postSave_tax_categories(): void
public function postSave_tax_categories(): ResponseInterface
{
$tax_category_id = $this->request->getPost('tax_category_id', FILTER_SANITIZE_NUMBER_INT);
$tax_category = $this->request->getPost('tax_category', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
@@ -531,7 +531,7 @@ class Taxes extends Secure_Controller
$success = $this->tax_category->save_categories($array_save);
echo json_encode([
return $this->response->setJSON([
'success' => $success,
'message' => lang('Taxes.tax_categories_saved_' . ($success ? '' : 'un') . 'successfully')
]);
@@ -540,36 +540,36 @@ class Taxes extends Secure_Controller
/**
* Gets tax codes partial view. Used in app/Views/taxes/tax_codes.php.
*
* @return void
* @return string
* @noinspection PhpUnused
*/
public function getAjax_tax_codes(): void
public function getAjax_tax_codes(): string
{
$tax_codes = $this->tax_code->get_all()->getResultArray();
echo view('partial/tax_codes', ['tax_codes' => $tax_codes]);
return view('partial/tax_codes', ['tax_codes' => $tax_codes]);
}
/**
* Gets current tax categories. Used in app/Views/taxes/tax_categories.php
*
* @return void
* @return string
* @noinspection PhpUnused
*/
public function getAjax_tax_categories(): void
public function getAjax_tax_categories(): string
{
$tax_categories = $this->tax_category->get_all()->getResultArray();
echo view('partial/tax_categories', ['tax_categories' => $tax_categories]);
return view('partial/tax_categories', ['tax_categories' => $tax_categories]);
}
/**
* Gets the tax jurisdiction partial view. Used in app/Views/taxes/tax_jurisdictions.php.
*
* @return void
* @return string
* @noinspection PhpUnused
*/
public function getAjax_tax_jurisdictions(): void
public function getAjax_tax_jurisdictions(): string
{
$tax_jurisdictions = $this->tax_jurisdiction->get_all()->getResultArray();
@@ -581,7 +581,7 @@ class Taxes extends Secure_Controller
$tax_types = $this->tax_lib->get_tax_types();
echo view('partial/tax_jurisdictions', [
return view('partial/tax_jurisdictions', [
'tax_jurisdictions' => $tax_jurisdictions,
'tax_types' => $tax_types,
'default_tax_type' => $default_tax_type

View File

@@ -21,6 +21,6 @@ class Migration_receipttaxindicator extends Migration
*/
public function down(): void
{
$this->db->query('DELETE FROM ' . $this->db->prefixTable('app_config') . ' WHERE key = \'receipt_show_tax_ind\'');
$this->db->query('DELETE FROM ' . $this->db->prefixTable('app_config') . ' WHERE `key` = \'receipt_show_tax_ind\'');
}
}

View File

@@ -1,5 +1,5 @@
[mysqld]
sql_mode = "STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
sql_mode = "STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"
key_buffer = 16M
max_allowed_packet = 1M

View File

@@ -172,7 +172,7 @@ class Barcode_lib
if ($layout_type == 'name') {
$result = $item['name'];
} elseif ($layout_type == 'category' && isset($item['category'])) {
$result = lang('Items.category') . " " . $item['category'];
$result = lang('Items.category') . " " . esc($item['category']);
} elseif ($layout_type == 'cost_price' && isset($item['cost_price'])) {
$result = lang('Items.cost_price') . " " . to_currency($item['cost_price']);
} elseif ($layout_type == 'unit_price' && isset($item['unit_price'])) {

View File

@@ -36,7 +36,7 @@
<div class="fileinput <?= $logo_exists ? 'fileinput-exists' : 'fileinput-new' ?>" data-provides="fileinput">
<div class="fileinput-new thumbnail" style="width: 200px; height: 200px;"></div>
<div class="fileinput-preview fileinput-exists thumbnail" style="max-width: 200px; max-height: 200px;">
<img data-src="holder.js/100%x100%" alt="<?= lang('Config.company_logo') ?>" src="<?php if ($logo_exists) echo base_url('uploads/' . $config['company_logo']); else echo '' ?>" style="max-height: 100%; max-width: 100%;">
<img data-src="holder.js/100%x100%" alt="<?= esc(lang('Config.company_logo')) ?>" src="<?= $logo_src ?>" style="max-height: 100%; max-width: 100%;">
</div>
<div>
<span class="btn btn-default btn-sm btn-file">

View File

@@ -15,7 +15,7 @@
<head>
<meta charset="utf-8">
<base href="<?= base_url() ?>">
<title><?= $config['company'] . '&nbsp;|&nbsp;' . lang('Common.software_short') . '&nbsp;|&nbsp;' . lang('Login.login') ?></title>
<title><?= esc($config['company']) . '&nbsp;|&nbsp;' . esc(lang('Common.software_short')) . '&nbsp;|&nbsp;' . esc(lang('Login.login')) ?></title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="noindex, nofollow">
<link rel="shortcut icon" type="image/x-icon" href="images/favicon.ico">
@@ -36,7 +36,7 @@
<div class="container-login container-fluid d-flex flex-column flex-md-row bg-body shadow rounded m-3 p-4 p-md-0">
<div class="box-logo d-flex flex-column justify-content-center align-items-center border-end border-secondary-subtle px-4 pb-3 p-md-4">
<?php if (isset($config['company_logo']) && !empty($config['company_logo'])): ?>
<img class="logo w-100" src="<?= base_url('uploads/' . $config['company_logo']) ?>" alt="<?= lang('Common.logo') . '&nbsp;' . $config['company'] ?>">
<img class="logo w-100" src="<?= base_url('uploads/' . esc($config['company_logo'], 'url')) ?>" alt="<?= esc(lang('Common.logo') . '&nbsp;' . $config['company']) ?>">
<?php else: ?>
<svg class="logo text-primary" role="img" viewBox="0 0 308.57998 308.57997" xmlns="http://www.w3.org/2000/svg">
<title><?= lang('Common.software_title') . '&nbsp;' . lang('Common.logo') ?></title>

View File

@@ -32,7 +32,7 @@
<div id="chart_report_summary">
<?php foreach ($summary_data_1 as $name => $value) { ?>
<div class="summary_row"><?= lang("Reports.$name") . ': ' . to_currency($value) ?></div>
<div class="summary_row"><?= lang("Reports.$name") . ': ' . esc(to_currency($value)) ?></div>
<?php } ?>
</div>

View File

@@ -38,7 +38,7 @@ if (isset($error)) {
if (can_show_report($permission_id, ['inventory', 'receiving'])) {
$link = get_report_link($permission_id, 'graphical_summary');
?>
<a class="list-group-item" href="<?= $link['path'] ?>"><?= $link['label'] ?></a>
<a class="list-group-item" href="<?= $link['path'] ?>"><?= esc($link['label']) ?></a>
<?php
}
}
@@ -57,7 +57,7 @@ if (isset($error)) {
if (can_show_report($permission_id, ['inventory', 'receiving'])) {
$link = get_report_link($permission_id, 'summary');
?>
<a class="list-group-item" href="<?= $link['path'] ?>"><?= $link['label'] ?></a>
<a class="list-group-item" href="<?= $link['path'] ?>"><?= esc($link['label']) ?></a>
<?php
}
}
@@ -76,7 +76,7 @@ if (isset($error)) {
if (in_array($report_name, $permission_ids, true)) {
$link = get_report_link($report_name, $prefix);
?>
<a class="list-group-item" href="<?= $link['path'] ?>"><?= $link['label'] ?></a>
<a class="list-group-item" href="<?= $link['path'] ?>"><?= esc($link['label']) ?></a>
<?php
}
}
@@ -94,8 +94,8 @@ if (isset($error)) {
$inventory_low_report = get_report_link('reports_inventory_low');
$inventory_summary_report = get_report_link('reports_inventory_summary');
?>
<a class="list-group-item" href="<?= $inventory_low_report['path'] ?>"><?= $inventory_low_report['label'] ?></a>
<a class="list-group-item" href="<?= $inventory_summary_report['path'] ?>"><?= $inventory_summary_report['label'] ?></a>
<a class="list-group-item" href="<?= $inventory_low_report['path'] ?>"><?= esc($inventory_low_report['label']) ?></a>
<a class="list-group-item" href="<?= $inventory_summary_report['path'] ?>"><?= esc($inventory_summary_report['label']) ?></a>
</div>
</div>
<?php } ?>

View File

@@ -36,7 +36,7 @@
foreach ($summary_data as $name => $value) {
if ($name == "total_quantity") {
?>
<div class="summary_row"><?= lang("Reports.$name") . ": $value" ?></div>
<div class="summary_row"><?= lang("Reports.$name") . ": " . esc($value) ?></div>
<?php } else { ?>
<div class="summary_row"><?= lang("Reports.$name") . ': ' . to_currency($value) ?></div>
<?php

View File

@@ -31,7 +31,7 @@
<div id="report_summary">
<?php foreach ($overall_summary_data as $name => $value) { ?>
<div class="summary_row"><?= lang("Reports.$name") . ': ' . to_currency($value) ?></div>
<div class="summary_row"><?= lang("Reports.$name") . ': ' . esc(to_currency($value)) ?></div>
<?php } ?>
</div>

View File

@@ -84,11 +84,11 @@ if (isset($error_message)) {
<div id="logo">
<?php if ($config['company_logo'] != '') { ?>
<img id="image" src="<?= base_url('uploads/' . $config['company_logo']) ?>" alt="company_logo">
<img id="image" src="<?= base_url('uploads/' . esc($config['company_logo'], 'url')) ?>" alt="company_logo">
<?php } ?>
<div>&nbsp;</div>
<?php if ($config['receipt_show_company_name']) { ?>
<div id="company_name"><?= $config['company'] ?></div>
<div id="company_name"><?= esc($config['company']) ?></div>
<?php } ?>
</div>
</div>

View File

@@ -19,7 +19,7 @@
<div id="receipt_header" style="text-align: center;">
<?php if ($config['company_logo'] != '') { ?>
<div id="company_name">
<img id="image" src="data:image/png;base64,<?= base64_encode(file_get_contents('uploads/' . $config['company_logo'])) ?>" alt="company_logo">
<?= $img_tag ?>
</div>
<?php } ?>

View File

@@ -480,7 +480,7 @@ helper('url');
<tbody id="payment_contents">
<?php foreach ($payments as $payment_id => $payment) { ?>
<tr>
<td><?= anchor("$controller_name/deletePayment/". base64url_encode($payment_id), '<span class="glyphicon glyphicon-trash"></span>') ?></td>
<td><?= anchor("$controller_name/deletePayment/". esc(base64url_encode($payment_id), 'url'), '<span class="glyphicon glyphicon-trash"></span>') ?></td>
<td><?= $payment['payment_type'] ?></td>
<td style="text-align: right;"><?= to_currency($payment['payment_amount']) ?></td>
</tr>

View File

@@ -82,7 +82,7 @@ if (isset($error_message)) {
<div id="logo">
<?php if ($config['company_logo'] != '') { ?>
<img id="image" src="<?= base_url('uploads/' . $config['company_logo']) ?>" alt="company_logo">
<img id="image" src="<?= base_url('uploads/' . esc($config['company_logo'], 'url')) ?>" alt="company_logo">
<?php } ?>
<div>&nbsp;</div>
<?php if ($config['receipt_show_company_name']) { ?>

View File

@@ -2,7 +2,7 @@
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd"
bootstrap="system/Test/bootstrap.php"
bootstrap="vendor/codeigniter4/framework/system/Test/bootstrap.php"
backupGlobals="false"
beStrictAboutOutputDuringTests="true"
colors="true"

View File

@@ -0,0 +1,231 @@
<?php
namespace Tests\Controllers;
use CodeIgniter\Test\CIUnitTestCase;
use CodeIgniter\Test\DatabaseTestTrait;
use CodeIgniter\Test\FeatureTestTrait;
use CodeIgniter\Config\Services;
use App\Models\Employee;
/**
* Test suite for Home controller password validation
*
* Tests the critical fix for password minimum length validation bypass
* Issue: Code was checking hashed password length (always 60 chars) instead of actual password
* Fix: Validate raw password length BEFORE hashing
*/
class HomeTest extends CIUnitTestCase
{
use DatabaseTestTrait;
use FeatureTestTrait;
protected $migrate = true;
protected $migrateOnce = true;
protected $refresh = false;
protected $namespace = null;
/**
* Set up test environment
*/
protected function setUp(): void
{
parent::setUp();
}
/**
* Test password validation rejects passwords shorter than 8 characters
*
* @return void
*/
public function testPasswordMinLength_Rejects7Characters(): void
{
$this->resetSession();
// Attempt to change password to 7 characters
$response = $this->post('/home/save', [
'employee_id' => 1,
'username' => 'admin',
'current_password' => 'pointofsale',
'password' => '1234567' // 7 characters
]);
// Assert failure response
$response->assertStatus(200);
$result = json_decode($response->getJSON(), true);
$this->assertFalse($result['success'], 'Password with 7 chars should be rejected');
$this->assertEquals(-1, $result['id']);
// Verify password was not changed
$employee = model(Employee::class);
$admin = $employee->get_info(1);
$this->assertTrue(password_verify('pointofsale', $admin->password),
'Password should not have been changed');
}
/**
* Test password validation accepts passwords with exactly 8 characters
*
* @return void
*/
public function testPasswordMinLength_Accepts8Characters(): void
{
$this->resetSession();
// Change password to exactly 8 characters
$response = $this->post('/home/save', [
'employee_id' => 1,
'username' => 'admin',
'current_password' => 'pointofsale',
'password' => 'pa$$w0rd' // Exactly 8 characters including special chars
]);
// Assert success response
$response->assertStatus(200);
$result = json_decode($response->getJSON(), true);
$this->assertTrue($result['success'], 'Password with 8 chars should be accepted');
$this->assertEquals(1, $result['id']);
// Verify password was changed
$employee = model(Employee::class);
$admin = $employee->get_info(1);
$this->assertTrue(password_verify('pa$$w0rd', $admin->password),
'Password with 8 chars should be accepted');
// Restore original password
$employee->change_password([
'username' => 'admin',
'password' => password_hash('pointofsale', PASSWORD_DEFAULT),
'hash_version' => 2
], 1);
}
/**
* Test password validation rejects empty password
*
* @return void
*/
public function testPasswordMinLength_RejectsEmptyString(): void
{
$this->resetSession();
// Attempt to set empty password
$response = $this->post('/home/save', [
'employee_id' => 1,
'username' => 'admin',
'current_password' => 'pointofsale',
'password' => '' // Empty string
]);
$response->assertStatus(200);
$result = json_decode($response->getJSON(), true);
$this->assertFalse($result['success'], 'Empty password should be rejected');
$this->assertEquals(-1, $result['id']);
}
/**
* Test password validation rejects whitespace-only passwords
*
* @return void
*/
public function testPasswordMinLength_RejectsWhitespaceOnly(): void
{
$this->resetSession();
// Attempt to set password as only whitespace
$response = $this->post('/home/save', [
'employee_id' => 1,
'username' => 'admin',
'current_password' => 'pointofsale',
'password' => ' ' // 8 spaces but empty actual password
]);
$response->assertStatus(200);
$result = json_decode($response->getJSON(), true);
$this->assertFalse($result['success'], 'Whitespace only password should be rejected');
$this->assertEquals(-1, $result['id']);
}
/**
* Test password validation accepts passwords with special characters
* as long as they meet minimum length
*
* @return void
*/
public function testPasswordMinLength_AcceptsSpecialCharacters(): void
{
$this->resetSession();
$specialPassword = 'Str0ng!@#$'; // 11 characters with special chars
$response = $this->post('/home/save', [
'employee_id' => 1,
'username' => 'admin',
'current_password' => 'pointofsale',
'password' => $specialPassword
]);
$response->assertStatus(200);
$result = json_decode($response->getJSON(), true);
$this->assertTrue($result['success'], 'Password with special chars should be accepted');
$this->assertEquals(1, $result['id']);
// Verify password works
$employee = model(Employee::class);
$admin = $employee->get_info(1);
$this->assertTrue(password_verify($specialPassword, $admin->password));
// Restore original password
$employee->change_password([
'username' => 'admin',
'password' => password_hash('pointofsale', PASSWORD_DEFAULT),
'hash_version' => 2
], 1);
}
/**
* Regression test: Verify previous vulnerable behavior is fixed
*
* Before fix: 1-character passwords like "a" were accepted because
* code checked len(hashed_password) which is always 60 for bcrypt
* After fix: Raw password is validated before hashing
*
* @return void
*/
public function testPasswordMinLength_RejectsPreviousBehavior(): void
{
$this->resetSession();
// Attempt the previously vulnerable case: single character password
$response = $this->post('/home/save', [
'employee_id' => 1,
'username' => 'admin',
'current_password' => 'pointofsale',
'password' => 'a' // Previously allowed due to bug
]);
// This should now fail
$response->assertStatus(200);
$result = json_decode($response->getJSON(), true);
$this->assertFalse($result['success'], 'Single character password should be rejected (CVE fix)');
$this->assertEquals(-1, $result['id']);
// Verify password was NOT changed
$employee = model(Employee::class);
$admin = $employee->get_info(1);
$this->assertTrue(password_verify('pointofsale', $admin->password),
'Single character password should be rejected (CVE fix)');
}
/**
* Helper method to reset session
*
* @return void
*/
protected function resetSession(): void
{
$session = Services::session();
$session->destroy();
$session->set('person_id', 1); // Admin user
}
}