Compare commits

..

1 Commits

Author SHA1 Message Date
jekkos
f754b7b8ab Apply CI4 coding standards (#3708) 2025-07-11 23:57:46 +02:00
1317 changed files with 75939 additions and 77746 deletions

87
.env Normal file
View File

@@ -0,0 +1,87 @@
#--------------------------------------------------------------------
# ENVIRONMENT
#--------------------------------------------------------------------
CI_ENVIRONMENT = production
CI_DEBUG = false
#--------------------------------------------------------------------
# APP
#--------------------------------------------------------------------
app.appTimezone = 'UTC'
#--------------------------------------------------------------------
# DATABASE
#--------------------------------------------------------------------
database.default.hostname = 'localhost'
database.default.database = 'ospos'
database.default.username = 'admin'
database.default.password = 'pointofsale'
database.default.DBDriver = 'MySQLi'
database.default.DBPrefix = 'ospos_'
database.default.port = 3306
database.development.hostname = 'localhost'
database.development.database = 'ospos'
database.development.username = 'admin'
database.development.password = 'pointofsale'
database.development.DBDriver = 'MySQLi'
database.development.DBPrefix = 'ospos_'
database.development.port = 3306
database.tests.hostname = 'localhost'
database.tests.database = 'ospos'
database.tests.username = 'admin'
database.tests.password = 'pointofsale'
database.tests.DBDriver = 'MySQLi'
database.tests.DBPrefix = 'ospos_'
database.tests.charset = utf8mb4
database.tests.DBCollat = utf8mb4_general_ci
database.tests.port = 3306
#--------------------------------------------------------------------
# EMAIL
#--------------------------------------------------------------------
email.SMTPHost = ''
email.SMTPUser = ''
email.SMTPPass = ''
email.SMTPPort =
email.SMTPTimeout = 5
email.SMTPCrypto = 'tls'
#--------------------------------------------------------------------
# ENCRYPTION
#--------------------------------------------------------------------
encryption.key = ''
#--------------------------------------------------------------------
# HONEYPOT
#--------------------------------------------------------------------
honeypot.hidden = true
honeypot.label = 'Fill This Field'
honeypot.name = 'honeypot'
honeypot.template = '<label>{label}</label><input type="text" name="{name}" value="">'
honeypot.container = '<div style="display:none">{template}</div>'
#--------------------------------------------------------------------
# LOGGER
# - 0 = Disables logging, Error logging TURNED OFF
# - 1 = Emergency Messages - System is unusable
# - 2 = Alert Messages - Action Must Be Taken Immediately
# - 3 = Critical Messages - Application component unavailable, unexpected exception.
# - 4 = Runtime Errors - Don't need immediate action, but should be monitored.
# - 5 = Warnings - Exceptional occurrences that are not errors.
# - 6 = Notices - Normal but significant events.
# - 7 = Info - Interesting events, like user logging in, etc.
# - 8 = Debug - Detailed debug information.
# - 9 = All Messages
#--------------------------------------------------------------------
logger.threshold = 0
app.db_log_enabled = false
app.db_log_only_long = false

View File

View File

@@ -42,12 +42,10 @@ body:
label: OpensourcePOS Version
description: What version of our software are you running?
options:
- development (unreleased)
- opensourcepos 3.4.1
- opensourcepos 3.4.0
- opensourcepos 3.3.9
- opensourcepos 3.3.8
- opensourcepos 3.3.7
- development (unreleased)
default: 0
validations:
required: true

View File

@@ -1,116 +0,0 @@
name: Unit Tests
on:
push:
paths:
- 'app/**/*.php'
- 'tests/**/*.php'
- '.github/workflows/unit-tests.yml'
pull_request:
paths:
- 'app/**/*.php'
- 'tests/**/*.php'
- '.github/workflows/unit-tests.yml'
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
permissions:
contents: read
jobs:
test:
name: PHP ${{ matrix.php-version }} Unit Tests
runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
php-version:
- '8.1'
- '8.2'
- '8.3'
services:
mysql:
image: mysql:8.0
env:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: ospos_test
MYSQL_USER: ospos
MYSQL_PASSWORD: ospos
ports:
- 3306:3306
options: >-
--health-cmd="mysqladmin ping --silent"
--health-interval=10s
--health-timeout=5s
--health-retries=5
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
extensions: intl, mysqli, pdo_mysql, mbstring, json, dom, xml
coverage: xdebug
- 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 install --no-progress --ansi --no-interaction
- name: Wait for MySQL
run: |
while ! mysqladmin ping -h"127.0.0.1" --silent; do
echo "Waiting for MySQL..."
sleep 1
done
- name: Setup test database
run: |
mysql -h 127.0.0.1 -u root -proot -e "CREATE DATABASE IF NOT EXISTS ospos_test CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
mysql -h 127.0.0.1 -u root -proot -e "GRANT ALL PRIVILEGES ON ospos_test.* TO 'ospos'@'%' IDENTIFIED BY 'ospos';"
mysql -h 127.0.0.1 -u root -proot -e "FLUSH PRIVILEGES;"
- name: Copy test environment config
run: |
if [ -f ".env.testing" ]; then
cp .env.testing .env
else
cp .env.example .env
fi
- name: Run migrations
run: php spark migrate --all || true
- name: Run unit tests
run: vendor/bin/phpunit --configuration tests/phpunit.xml --testsuite Helpers,Models,Controllers --colors=always --verbose
- name: Generate test report
if: always()
run: |
vendor/bin/phpunit --configuration tests/phpunit.xml --testsuite Helpers,Models,Controllers --log-junit build/logs/junit.xml --coverage-clover build/logs/clover.xml || true
echo "Test run completed"
- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results-php-${{ matrix.php-version }}
path: build/logs/
retention-days: 30

1
.gitignore vendored
View File

@@ -8,7 +8,6 @@ public/license/*
!public/license/.gitkeep
app/Config/email.php
npm-debug.log*
.vscode
# Docker
!docker/.env

View File

@@ -15,7 +15,7 @@ script:
- echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
- docker run --rm -u $(id -u) -v $(pwd):/app opensourcepos/composer:ci4 composer install
- version=$(grep application_version app/Config/App.php | sed "s/.*=\s'\(.*\)';/\1/g")
- cp .env.example .env && sed -i 's/production/development/g' .env
- sed -i 's/production/development/g' .env
- sed -i "s/commit_sha1 = 'dev'/commit_sha1 = '$rev'/g" app/Config/OSPOS.php
- echo "$version-$branch-$rev"
- npm version "$version-$branch-$rev" --force || true

View File

@@ -1,5 +1,4 @@
[unreleased]: https://github.com/opensourcepos/opensourcepos/compare/3.4.0...HEAD
[3.4.2]: https://github.com/opensourcepos/opensourcepos/compare/3.4.1...3.4.2
[3.4.1]: https://github.com/opensourcepos/opensourcepos/compare/3.4.0...3.4.1
[3.4.0]: https://github.com/opensourcepos/opensourcepos/compare/3.3.9...3.4.0
[3.3.9]: https://github.com/opensourcepos/opensourcepos/compare/3.3.8...3.3.9

View File

@@ -14,7 +14,7 @@ First of all, if you're seeing the message `system folder missing` after launchi
2. Create/locate a new MySQL database to install Open Source Point of Sale into.
3. Execute the file `app/Database/database.sql` to create the tables needed.
4. Unzip and upload Open Source Point of Sale files to the web-server.
5. Open `.env` file and modify credentials to connect to your database if needed. (First copy .env.example to .env and update)
5. Open `.env` file and modify credentials to connect to your database if needed.
7. Go to your install `public` dir via the browser.
8. Log in using
- Username: admin
@@ -63,39 +63,3 @@ Do **not** use below command on live deployments unless you want to tear everyth
If you choose DigitalOcean:
[Through this link](https://m.do.co/c/ac38c262507b), you will get a [**free $100, 60-day credit**](https://m.do.co/c/ac38c262507b). [Check the wiki](https://github.com/opensourcepos/opensourcepos/wiki/Getting-Started-installations) for further instructions on how to install the necessary components.
## One-line Ubuntu Installation
For a fresh Ubuntu server (20.04 LTS or newer), you can install OSPOS directly with:
```bash
curl -sSL https://opensourcepos.org/install | sudo bash
```
> **Note:** This URL redirects to the latest installation script from the official repository. If the redirect is unavailable, use the direct GitHub URL:
> ```bash
> curl -sSL https://raw.githubusercontent.com/opensourcepos/opensourcepos/master/scripts/install-ubuntu.sh | sudo bash
> ```
This script will:
- Install Apache, MariaDB, PHP 8.2 and required extensions
- Create a MySQL database and user with a secure random password
- Download and configure OSPOS
- Set up Apache virtual host with proper permissions
- Display login credentials after completion
**Environment Variables (optional):**
- `DB_NAME` - Database name (default: ospos)
- `DB_USER` - Database user (default: ospos)
- `DB_PASS` - Database password (default: auto-generated)
- `OSPOS_DIR` - Installation directory (default: /var/www/ospos)
- `OSPOS_BRANCH` - Git branch to install (default: master)
- `PHP_VERSION` - PHP version (default: 8.2)
- `APACHE_SERVER_NAME` - Server hostname (default: localhost)
Example with custom settings:
```bash
curl -sSL https://opensourcepos.org/install | DB_PASS=mypassword APACHE_SERVER_NAME=pos.example.com sudo -E bash
```
**Note:** This script is designed for fresh servers. For production use, ensure you configure SSL/TLS certificates after installation.

View File

@@ -18,8 +18,7 @@ We release patches for security vulnerabilities. Which versions are eligible to
| --------- | -------------------------------------------------- |
| 7.3 | 3.3.5 |
| 9.8 | 3.3.6 |
| 6.8 | 3.4.2 |
## Reporting a Vulnerability
Please report (suspected) security vulnerabilities to **[jeroen@steganos.dev](mailto:jeroen@steganos.dev)**. You will receive a response from us within 48 hours. If the issue is confirmed, we will release a patch as soon as possible depending on complexity but historically within a few days.
Please report (suspected) security vulnerabilities to **[jekkos@opensourcepos.org](mailto:jekkos@opensourcepos.org)**. You will receive a response from us within 48 hours. If the issue is confirmed, we will release a patch as soon as possible depending on complexity but historically within a few days.

View File

@@ -3,42 +3,31 @@
namespace Config;
use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Session\Handlers\DatabaseHandler;
class App extends BaseConfig
{
/**
* This is the code version of the Open Source Point of Sale you're running.
*
* @var string
*/
public string $application_version = '3.4.2';
public string $application_version = '3.4.1';
/**
* This is the commit hash for the version you are currently using.
*
* @var string
*/
public string $commit_sha1 = 'dev';
/**
* Logs are stored in writable/logs
*
* @var bool
*/
public bool $db_log_enabled = false;
/**
* DB Query Log only long-running queries
*
* @var bool
*/
public bool $db_log_only_long = false;
/**
* Defines whether to require/reroute to HTTPS
*
* @var bool
*/
public bool $https_on; // Set in the constructor
@@ -117,7 +106,7 @@ class App extends BaseConfig
| DO NOT CHANGE THIS UNLESS YOU FULLY UNDERSTAND THE REPERCUSSIONS!!
|
*/
public string $permittedURIChars = 'a-z 0-9~%.:_\-=';
public string $permittedURIChars = 'a-z 0-9~%.:_\-';
/**
* --------------------------------------------------------------------------
@@ -283,8 +272,8 @@ class App extends BaseConfig
public function __construct()
{
parent::__construct();
$this->https_on = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') || (isset($_ENV['FORCE_HTTPS']) && $_ENV['FORCE_HTTPS'] == 'true');
$this->baseURL = $this->https_on ? 'https' : 'http';
$this->https_on = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') || (isset($_ENV['FORCE_HTTPS']) && $_ENV['FORCE_HTTPS'] === 'true');
$this->baseURL = $this->https_on ? 'https' : 'http';
$this->baseURL .= '://' . ((isset($_SERVER['HTTP_HOST'])) ? $_SERVER['HTTP_HOST'] : 'localhost') . '/';
$this->baseURL .= str_replace(basename($_SERVER['SCRIPT_NAME']), '', $_SERVER['SCRIPT_NAME']);
}

View File

@@ -42,7 +42,7 @@ class Autoload extends AutoloadConfig
public $psr4 = [
APP_NAMESPACE => APPPATH,
'Config' => APPPATH . 'Config',
'dompdf' => APPPATH . 'ThirdParty/dompdf/src'
'dompdf' => APPPATH . 'ThirdParty/dompdf/src',
];
/**
@@ -169,7 +169,7 @@ class Autoload extends AutoloadConfig
'Token_lib' => '/App/Libraries/Token_lib.php',
// Miscellaneous
'Rounding_mode' => '/App/Models/Enums/Rounding_mode.php'
'Rounding_mode' => '/App/Models/Enums/Rounding_mode.php',
];
/**
@@ -205,6 +205,6 @@ class Autoload extends AutoloadConfig
'cookie',
'tabular',
'locale',
'security'
'security',
];
}

View File

@@ -33,17 +33,17 @@ defined('COMPOSER_PATH') || define('COMPOSER_PATH', ROOTPATH . 'vendor/autoload.
| Provide simple ways to work with the myriad of PHP functions that
| require information to be in seconds.
*/
defined('SECOND') || define('SECOND', 1);
defined('MINUTE') || define('MINUTE', 60);
defined('HOUR') || define('HOUR', 3600);
defined('DAY') || define('DAY', 86400);
defined('WEEK') || define('WEEK', 604800);
defined('MONTH') || define('MONTH', 2_592_000);
defined('YEAR') || define('YEAR', 31_536_000);
defined('DECADE') || define('DECADE', 315_360_000);
defined('SECOND') || define('SECOND', 1);
defined('MINUTE') || define('MINUTE', 60);
defined('HOUR') || define('HOUR', 3600);
defined('DAY') || define('DAY', 86400);
defined('WEEK') || define('WEEK', 604800);
defined('MONTH') || define('MONTH', 2_592_000);
defined('YEAR') || define('YEAR', 31_536_000);
defined('DECADE') || define('DECADE', 315_360_000);
defined('DEFAULT_DATE') || define('DEFAULT_DATE', mktime(0, 0, 0, 1, 1, 2010));
defined('DEFAULT_DATETIME') || define('DEFAULT_DATETIME', mktime(0, 0, 0, 1, 1, 2010));
defined('NOW') || define('NOW', time());
defined('NOW') || define('NOW', time());
/*
| --------------------------------------------------------------------------
@@ -85,48 +85,47 @@ defined('EXIT__AUTO_MAX') || define('EXIT__AUTO_MAX', 125); // highest a
* Global Constants.
*/
const NEW_ENTRY = -1;
const ACTIVE = 0;
const DELETED = 1;
const ACTIVE = 0;
const DELETED = 1;
/**
* Attribute Related Constants.
*/
const GROUP = 'GROUP';
const DROPDOWN = 'DROPDOWN';
const DECIMAL = 'DECIMAL';
const DATE = 'DATE';
const TEXT = 'TEXT';
const CHECKBOX = 'CHECKBOX';
const NO_DEFINITION_ID = 0;
const GROUP = 'GROUP';
const DROPDOWN = 'DROPDOWN';
const DECIMAL = 'DECIMAL';
const DATE = 'DATE';
const TEXT = 'TEXT';
const CHECKBOX = 'CHECKBOX';
const NO_DEFINITION_ID = 0;
const CATEGORY_DEFINITION_ID = -1;
const DEFINITION_TYPES = [GROUP, DROPDOWN, DECIMAL, TEXT, DATE, CHECKBOX];
const ATTRIBUTE_VALUE_TYPES = ['attribute_value', 'attribute_decimal', 'attribute_date'];
const DEFINITION_TYPES = [GROUP, DROPDOWN, DECIMAL, TEXT, DATE, CHECKBOX];
/**
* Item Related Constants.
*/
const HAS_STOCK = 0;
const HAS_STOCK = 0;
const HAS_NO_STOCK = 1;
const ITEM = 0;
const ITEM_KIT = 1;
const ITEM = 0;
const ITEM_KIT = 1;
const ITEM_AMOUNT_ENTRY = 2;
const ITEM_TEMP = 3;
const NEW_ITEM = -1;
const ITEM_TEMP = 3;
const NEW_ITEM = -1;
const PRINT_ALL = 0;
const PRINT_ALL = 0;
const PRINT_PRICED = 1;
const PRINT_KIT = 2;
const PRINT_KIT = 2;
const PRINT_YES = 0;
const PRINT_NO = 1;
const PRINT_NO = 1;
const PRICE_ALL = 0;
const PRICE_KIT = 1;
const PRICE_ALL = 0;
const PRICE_KIT = 1;
const PRICE_KIT_ITEMS = 2;
const PRICE_OPTION_ALL = 0;
const PRICE_OPTION_KIT = 1;
const PRICE_OPTION_ALL = 0;
const PRICE_OPTION_KIT = 1;
const PRICE_OPTION_KIT_STOCK = 2;
const NAME_SEPARATOR = ' | ';
@@ -136,37 +135,37 @@ const NAME_SEPARATOR = ' | ';
*/
const COMPLETED = 0;
const SUSPENDED = 1;
const CANCELED = 2;
const CANCELED = 2;
const SALE_TYPE_POS = 0;
const SALE_TYPE_INVOICE = 1;
const SALE_TYPE_POS = 0;
const SALE_TYPE_INVOICE = 1;
const SALE_TYPE_WORK_ORDER = 2;
const SALE_TYPE_QUOTE = 3;
const SALE_TYPE_RETURN = 4;
const SALE_TYPE_QUOTE = 3;
const SALE_TYPE_RETURN = 4;
const PERCENT = 0;
const FIXED = 1;
const FIXED = 1;
const PRICE_MODE_STANDARD = 0;
const PRICE_MODE_KIT = 1;
const PRICE_MODE_KIT = 1;
const PAYMENT_TYPE_UNASSIGNED = '--';
const CASH_ADJUSTMENT_TRUE = 1;
const CASH_ADJUSTMENT_TRUE = 1;
const CASH_ADJUSTMENT_FALSE = 0;
const CASH_MODE_TRUE = 1;
const CASH_MODE_FALSE = 0;
const CASH_MODE_TRUE = 1;
const CASH_MODE_FALSE = 0;
/**
* Supplier Related Constants
*/
const GOODS_SUPPLIER = 0;
const COST_SUPPLIER = 1;
const COST_SUPPLIER = 1;
/**
* Locale Related Constants
*/
const MAX_PRECISION = 1e14;
const DEFAULT_PRECISION = 2;
const DEFAULT_LANGUAGE = 'english';
const MAX_PRECISION = 1e14;
const DEFAULT_PRECISION = 2;
const DEFAULT_LANGUAGE = 'english';
const DEFAULT_LANGUAGE_CODE = 'en';

View File

@@ -61,7 +61,7 @@ class ContentSecurityPolicy extends BaseConfig
'self',
'unsafe-inline',
'unsafe-eval',
'www.google.com www.gstatic.com'
'www.google.com www.gstatic.com',
];
/**

View File

@@ -25,24 +25,24 @@ class Database extends Config
* @var array<string, mixed>
*/
public array $default = [
'DSN' => '',
'hostname' => 'localhost',
'username' => 'admin',
'password' => 'pointofsale',
'database' => 'ospos',
'DBDriver' => 'MySQLi',
'DBPrefix' => 'ospos_',
'pConnect' => false,
'DBDebug' => (ENVIRONMENT !== 'production'),
'charset' => 'utf8mb4',
'DBCollat' => 'utf8mb4_general_ci',
'swapPre' => '',
'encrypt' => false,
'compress' => false,
'strictOn' => false,
'failover' => [],
'port' => 3306,
'dateFormat' => [
'DSN' => '',
'hostname' => 'localhost',
'username' => 'admin',
'password' => 'pointofsale',
'database' => 'ospos',
'DBDriver' => 'MySQLi',
'DBPrefix' => 'ospos_',
'pConnect' => false,
'DBDebug' => (ENVIRONMENT !== 'production'),
'charset' => 'utf8mb4',
'DBCollat' => 'utf8mb4_general_ci',
'swapPre' => '',
'encrypt' => false,
'compress' => false,
'strictOn' => false,
'failover' => [],
'port' => 3306,
'dateFormat' => [
'date' => 'Y-m-d',
'datetime' => 'Y-m-d H:i:s',
'time' => 'H:i:s',
@@ -55,26 +55,26 @@ class Database extends Config
* @var array<string, mixed>
*/
public array $tests = [
'DSN' => '',
'hostname' => 'localhost',
'username' => 'admin',
'password' => 'pointofsale',
'database' => 'ospos',
'DBDriver' => 'MySQLi',
'DBPrefix' => 'ospos_',
'pConnect' => false,
'DBDebug' => (ENVIRONMENT !== 'production'),
'charset' => 'utf8mb4',
'DBCollat' => 'utf8mb4_general_ci',
'swapPre' => '',
'encrypt' => false,
'compress' => false,
'strictOn' => false,
'failover' => [],
'port' => 3306,
'foreignKeys' => true,
'busyTimeout' => 1000,
'dateFormat' => [
'DSN' => '',
'hostname' => 'localhost',
'username' => 'admin',
'password' => 'pointofsale',
'database' => 'ospos',
'DBDriver' => 'MySQLi',
'DBPrefix' => 'ospos_',
'pConnect' => false,
'DBDebug' => (ENVIRONMENT !== 'production'),
'charset' => 'utf8mb4',
'DBCollat' => 'utf8mb4_general_ci',
'swapPre' => '',
'encrypt' => false,
'compress' => false,
'strictOn' => false,
'failover' => [],
'port' => 3306,
'foreignKeys' => true,
'busyTimeout' => 1000,
'dateFormat' => [
'date' => 'Y-m-d',
'datetime' => 'Y-m-d H:i:s',
'time' => 'H:i:s',
@@ -87,26 +87,26 @@ class Database extends Config
* @var array
*/
public $development = [
'DSN' => '',
'hostname' => 'localhost',
'username' => 'admin',
'password' => 'pointofsale',
'database' => 'ospos',
'DBDriver' => 'MySQLi',
'DBPrefix' => 'ospos_',
'pConnect' => false,
'DBDebug' => (ENVIRONMENT !== 'production'),
'charset' => 'utf8mb4',
'DBCollat' => 'utf8mb4_general_ci',
'swapPre' => '',
'encrypt' => false,
'compress' => false,
'strictOn' => false,
'failover' => [],
'port' => 3306,
'foreignKeys' => true,
'busyTimeout' => 1000,
'dateFormat' => [
'DSN' => '',
'hostname' => 'localhost',
'username' => 'admin',
'password' => 'pointofsale',
'database' => 'ospos',
'DBDriver' => 'MySQLi',
'DBPrefix' => 'ospos_',
'pConnect' => false,
'DBDebug' => (ENVIRONMENT !== 'production'),
'charset' => 'utf8mb4',
'DBCollat' => 'utf8mb4_general_ci',
'swapPre' => '',
'encrypt' => false,
'compress' => false,
'strictOn' => false,
'failover' => [],
'port' => 3306,
'foreignKeys' => true,
'busyTimeout' => 1000,
'dateFormat' => [
'date' => 'Y-m-d',
'datetime' => 'Y-m-d H:i:s',
'time' => 'H:i:s',
@@ -124,16 +124,17 @@ class Database extends Config
case 'testing':
$this->defaultGroup = 'tests';
break;
case 'development';
case 'development':
$this->defaultGroup = 'development';
break;
}
foreach ([&$this->development, &$this->tests, &$this->default] as &$config) {
$config['hostname'] = !getenv('MYSQL_HOST_NAME') ? $config['hostname'] : getenv('MYSQL_HOST_NAME');
$config['username'] = !getenv('MYSQL_USERNAME') ? $config['username'] : getenv('MYSQL_USERNAME');
$config['password'] = !getenv('MYSQL_PASSWORD') ? $config['password'] : getenv('MYSQL_PASSWORD');
$config['database'] = !getenv('MYSQL_DB_NAME') ? $config['database'] : getenv('MYSQL_DB_NAME');
$config['hostname'] = ! getenv('MYSQL_HOST_NAME') ? $config['hostname'] : getenv('MYSQL_HOST_NAME');
$config['username'] = ! getenv('MYSQL_USERNAME') ? $config['username'] : getenv('MYSQL_USERNAME');
$config['password'] = ! getenv('MYSQL_PASSWORD') ? $config['password'] : getenv('MYSQL_PASSWORD');
$config['database'] = ! getenv('MYSQL_DB_NAME') ? $config['database'] : getenv('MYSQL_DB_NAME');
}
}
}

View File

@@ -2,12 +2,12 @@
namespace Config;
use CodeIgniter\Events\Events;
use CodeIgniter\Exceptions\FrameworkException;
use CodeIgniter\HotReloader\HotReloader;
use App\Events\Db_log;
use App\Events\Load_config;
use App\Events\Method;
use CodeIgniter\Events\Events;
use CodeIgniter\Exceptions\FrameworkException;
use CodeIgniter\HotReloader\HotReloader;
/*
* --------------------------------------------------------------------

View File

@@ -70,7 +70,7 @@ class Filters extends BaseFilters
public array $globals = [
'before' => [
'honeypot',
'csrf' => ['except' => 'login'],
// 'csrf' => ['except' => 'login'], // TODO: Temporarily disable CSRF until we get everything sorted
'invalidchars',
],
'after' => [

View File

@@ -24,9 +24,6 @@ class OSPOS extends BaseConfig
$this->set_settings();
}
/**
* @return void
*/
public function set_settings(): void
{
$cache = $this->cache->get('settings');
@@ -35,6 +32,7 @@ class OSPOS extends BaseConfig
$this->settings = decode_array($cache);
} else {
$appconfig = model(Appconfig::class);
foreach ($appconfig->get_all()->getResult() as $app_config) {
$this->settings[$app_config->key] = $app_config->value;
}
@@ -42,9 +40,6 @@ class OSPOS extends BaseConfig
}
}
/**
* @return void
*/
public function update_settings(): void
{
$this->cache->delete('settings');

View File

@@ -56,6 +56,6 @@ class Pager extends BaseConfig
'first_tag_open' => '<li>',
'first_tagl_close' => '</li>',
'last_tag_open' => '<li>',
'last_tagl_close' => '</li>'
'last_tagl_close' => '</li>',
];
}

View File

@@ -15,7 +15,7 @@ class Security extends BaseConfig
*
* @var string 'cookie' or 'session'
*/
public string $csrfProtection = 'session';
public string $csrfProtection = 'cookie';
/**
* --------------------------------------------------------------------------
@@ -71,7 +71,7 @@ class Security extends BaseConfig
*
* Regenerate CSRF Token on every submission.
*/
public bool $regenerate = false;
public bool $regenerate = true;
/**
* --------------------------------------------------------------------------

View File

@@ -2,12 +2,11 @@
namespace Config;
use Locale;
use CodeIgniter\Config\BaseService;
use CodeIgniter\HTTP\IncomingRequest;
use Config\Services as AppServices;
use HTMLPurifier;
use HTMLPurifier_Config;
use CodeIgniter\Config\BaseService;
use Config\Services as AppServices;
use CodeIgniter\HTTP\IncomingRequest;
/**
* Services Configuration file.
@@ -24,6 +23,7 @@ use CodeIgniter\HTTP\IncomingRequest;
*/
class Services extends BaseService
{
private static $htmlPurifier;
/*
* public static function example($getShared = true)
* {
@@ -58,16 +58,14 @@ class Services extends BaseService
return new \App\Libraries\MY_Language($locale);
}
private static $htmlPurifier;
public static function htmlPurifier($getShared = true)
{
if ($getShared) {
return static::getSharedInstance('htmlPurifier');
}
if (!isset(static::$htmlPurifier)) {
$config = HTMLPurifier_Config::createDefault();
if (! isset(static::$htmlPurifier)) {
$config = HTMLPurifier_Config::createDefault();
static::$htmlPurifier = new HTMLPurifier($config);
}

View File

@@ -2,12 +2,12 @@
namespace Config;
use App\Config\Validation\OSPOSRules;
use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Validation\StrictRules\CreditCardRules;
use CodeIgniter\Validation\StrictRules\FileRules;
use CodeIgniter\Validation\StrictRules\FormatRules;
use CodeIgniter\Validation\StrictRules\Rules;
use App\Config\Validation\OSPOSRules;
class Validation extends BaseConfig
{

View File

@@ -19,28 +19,30 @@ class OSPOSRules
/**
* Validates the username and password sent to the login view. User is logged in on successful validation.
*
* @param string $username Username to check against.
* @param string $fields Comma separated string of the fields for validation.
* @param array $data Data sent to the view.
* @param string|null $error The error sent back to the validation handler on failure.
* @param string $username Username to check against.
* @param string $fields Comma separated string of the fields for validation.
* @param array $data Data sent to the view.
* @param string|null $error The error sent back to the validation handler on failure.
*
* @return bool True if validation passes or false if there are errors.
*
* @noinspection PhpUnused
*/
public function login_check(string $username, string $fields, array $data, ?string &$error = null): bool
{
$employee = model(Employee::class);
$employee = model(Employee::class);
$this->request = Services::request();
$this->config = config(OSPOS::class)->settings;
$this->config = config(OSPOS::class)->settings;
// Installation Check
if (!$this->installation_check()) {
if (! $this->installation_check()) {
$error = lang('Login.invalid_installation');
return false;
}
$password = $data['password'];
if (!$employee->login($username, $password)) {
if (! $employee->login($username, $password)) {
$error = lang('Login.invalid_username_and_password');
return false;
@@ -50,7 +52,7 @@ class OSPOSRules
if ($gcaptcha_enabled) {
$g_recaptcha_response = $this->request->getPost('g-recaptcha-response');
if (!$this->gcaptcha_check($g_recaptcha_response)) {
if (! $this->gcaptcha_check($g_recaptcha_response)) {
$error = lang('Login.invalid_gcaptcha');
return false;
@@ -63,21 +65,22 @@ class OSPOSRules
/**
* Checks to see if GCaptcha verification was successful.
*
* @param $response
* @param mixed $response
*
* @return bool true on successful GCaptcha verification or false if GCaptcha failed.
*/
private function gcaptcha_check($response): bool
{
if (!empty($response)) {
if (! empty($response)) {
$check = [
'secret' => $this->config['gcaptcha_secret_key'],
'response' => $response,
'remoteip' => $this->request->getIPAddress()
'remoteip' => $this->request->getIPAddress(),
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://www.google.com/recaptcha/api/siteverify");
curl_setopt($ch, CURLOPT_URL, 'https://www.google.com/recaptcha/api/siteverify');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($check));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
@@ -88,7 +91,7 @@ class OSPOSRules
$status = json_decode($result, true);
if (!empty($status['success'])) {
if (! empty($status['success'])) {
return true;
}
}
@@ -98,14 +101,12 @@ class OSPOSRules
/**
* Checks to make sure dependency PHP extensions are installed
*
* @return bool
*/
private function installation_check(): bool
{
$installed_extensions = implode(', ', get_loaded_extensions());
$required_extensions = ['bcmath', 'intl', 'gd', 'openssl', 'mbstring', 'curl', 'xml', 'json'];
$pattern = '/';
$required_extensions = ['bcmath', 'intl', 'gd', 'openssl', 'mbstring', 'curl', 'xml', 'json'];
$pattern = '/';
foreach ($required_extensions as $extension) {
$pattern .= '(?=.*\b' . preg_quote($extension, '/') . '\b)';
@@ -114,9 +115,9 @@ class OSPOSRules
$pattern .= '/i';
$is_installed = preg_match($pattern, $installed_extensions);
if (!$is_installed) {
if (! $is_installed) {
log_message('error', '[ERROR] Check your php.ini.');
log_message('error', "PHP installed extensions: $installed_extensions");
log_message('error', "PHP installed extensions: {$installed_extensions}");
log_message('error', 'PHP required extensions: ' . implode(', ', $required_extensions));
}
@@ -126,9 +127,6 @@ class OSPOSRules
/**
* Validates the candidate as a decimal number. Takes the locale into account. Used in validation rule calls.
*
* @param string $candidate
* @param string|null $error
* @return bool
* @noinspection PhpUnused
*/
public function decimal_locale(string $candidate, ?string &$error = null): bool

View File

@@ -3,13 +3,12 @@
namespace App\Controllers;
use App\Models\Attribute;
use Config\Services;
require_once('Secure_Controller.php');
require_once 'Secure_Controller.php';
/**
* Attributes controls the custom attributes assigned to items
**/
*/
class Attributes extends Secure_Controller
{
private Attribute $attribute;
@@ -23,9 +22,7 @@ class Attributes extends Secure_Controller
/**
* Gets and sends the main view for Attributes to the browser.
*
* @return void
**/
*/
public function getIndex(): void
{
$data['table_headers'] = get_attribute_definition_manage_table_headers();
@@ -48,9 +45,10 @@ class Attributes extends Secure_Controller
$total_rows = $this->attribute->get_found_rows($search);
$data_rows = [];
foreach ($attributes->getResult() as $attribute_row) {
$attribute_row->definition_flags = $this->get_attributes($attribute_row->definition_flags);
$data_rows[] = get_attribute_definition_data_row($attribute_row);
$data_rows[] = get_attribute_definition_data_row($attribute_row);
}
echo json_encode(['total' => $total_rows, 'rows' => $data_rows]);
@@ -58,7 +56,7 @@ class Attributes extends Secure_Controller
/**
* AJAX called function which saves the attribute value sent via POST by using the model save function.
* @return void
*
* @noinspection PhpUnused
*/
public function postSaveAttributeValue(): void
@@ -67,22 +65,22 @@ class Attributes extends Secure_Controller
html_entity_decode($this->request->getPost('attribute_value')),
$this->request->getPost('definition_id', FILTER_SANITIZE_NUMBER_INT),
$this->request->getPost('item_id', FILTER_SANITIZE_NUMBER_INT) ?? false,
$this->request->getPost('attribute_id', FILTER_SANITIZE_NUMBER_INT) ?? false
$this->request->getPost('attribute_id', FILTER_SANITIZE_NUMBER_INT) ?? false,
);
echo json_encode(['success' => $success != 0]);
echo json_encode(['success' => $success !== 0]);
}
/**
* AJAX called function deleting an attribute value using the model delete function.
* @return void
*
* @noinspection PhpUnused
*/
public function postDeleteDropdownAttributeValue(): void
{
$success = $this->attribute->deleteDropdownAttributeValue(
html_entity_decode($this->request->getPost('attribute_value')),
$this->request->getPost('definition_id', FILTER_SANITIZE_NUMBER_INT)
$this->request->getPost('definition_id', FILTER_SANITIZE_NUMBER_INT),
);
echo json_encode(['success' => $success]);
@@ -91,8 +89,6 @@ class Attributes extends Secure_Controller
/**
* AJAX called function which saves the attribute definition.
*
* @param int $definition_id
* @return void
* @noinspection PhpUnused
*/
public function postSaveDefinition(int $definition_id = NO_DEFINITION_ID): void
@@ -108,20 +104,20 @@ class Attributes extends Secure_Controller
// Save definition data
$definition_data = [
'definition_name' => $this->request->getPost('definition_name'),
'definition_unit' => $this->request->getPost('definition_unit') != '' ? $this->request->getPost('definition_unit') : null,
'definition_unit' => $this->request->getPost('definition_unit') !== '' ? $this->request->getPost('definition_unit') : null,
'definition_flags' => $definition_flags,
'definition_fk' => $this->request->getPost('definition_group') != '' ? $this->request->getPost('definition_group') : null
'definition_fk' => $this->request->getPost('definition_group') !== '' ? $this->request->getPost('definition_group') : null,
];
if ($this->request->getPost('definition_type') != null) {
if ($this->request->getPost('definition_type') !== null) {
$definition_data['definition_type'] = DEFINITION_TYPES[$this->request->getPost('definition_type')];
}
$definition_name = $definition_data['definition_name'];
if ($this->attribute->saveDefinition($definition_data, $definition_id)) {
if ($this->attribute->save_definition($definition_data, $definition_id)) {
// New definition
if ($definition_id == NO_DEFINITION_ID) {
if ($definition_id === NO_DEFINITION_ID) {
$definition_values = json_decode(html_entity_decode($this->request->getPost('definition_values')));
foreach ($definition_values as $definition_value) {
@@ -131,28 +127,25 @@ class Attributes extends Secure_Controller
echo json_encode([
'success' => true,
'message' => lang('Attributes.definition_successful_adding') . ' ' . $definition_name,
'id' => $definition_data['definition_id']
'id' => $definition_data['definition_id'],
]);
} else { // Existing definition
echo json_encode([
'success' => true,
'message' => lang('Attributes.definition_successful_updating') . ' ' . $definition_name,
'id' => $definition_id
'id' => $definition_id,
]);
}
} else { // Failure
echo json_encode([
'success' => false,
'message' => lang('Attributes.definition_error_adding_updating', [$definition_name]),
'id' => NEW_ENTRY
'id' => NEW_ENTRY,
]);
}
}
/**
*
* @param int $definition_id
* @return void
* @noinspection PhpUnused
*/
public function getSuggestAttribute(int $definition_id): void
@@ -162,54 +155,45 @@ class Attributes extends Secure_Controller
echo json_encode($suggestions);
}
/**
* @param int $row_id
* @return void
*/
public function getRow(int $row_id): void
{
$attribute_definition_info = $this->attribute->getAttributeInfo($row_id);
$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);
$data_row = get_attribute_definition_data_row($attribute_definition_info);
echo json_encode($data_row);
}
/**
* @param int $definition_flags
* @return array
*/
private function get_attributes(int $definition_flags = 0): array
{
$definition_flag_names = [];
foreach (Attribute::get_definition_flags() as $id => $term) {
if ($id & $definition_flags) {
$definition_flag_names[$id] = lang('Attributes.' . strtolower($term) . '_visibility');
}
}
return $definition_flag_names;
}
/**
* @param int $definition_id
* @return void
*/
public function getView(int $definition_id = NO_DEFINITION_ID): void
{
$info = $this->attribute->getAttributeInfo($definition_id);
foreach (get_object_vars($info) as $property => $value) {
$info->$property = $value;
$info->{$property} = $value;
}
$data['definition_id'] = $definition_id;
$data['definition_values'] = $this->attribute->get_definition_values($definition_id);
$data['definition_group'] = $this->attribute->get_definitions_by_type(GROUP, $definition_id);
$data['definition_id'] = $definition_id;
$data['definition_values'] = $this->attribute->get_definition_values($definition_id);
$data['definition_group'] = $this->attribute->get_definitions_by_type(GROUP, $definition_id);
$data['definition_group'][''] = lang('Common.none_selected_text');
$data['definition_info'] = $info;
$data['definition_info'] = $info;
$show_all = Attribute::SHOW_IN_ITEMS | Attribute::SHOW_IN_RECEIVINGS | Attribute::SHOW_IN_SALES;
$data['definition_flags'] = $this->get_attributes($show_all);
$selected_flags = $info->definition_flags === '' ? $show_all : $info->definition_flags;
$show_all = Attribute::SHOW_IN_ITEMS | Attribute::SHOW_IN_RECEIVINGS | Attribute::SHOW_IN_SALES;
$data['definition_flags'] = $this->get_attributes($show_all);
$selected_flags = $info->definition_flags === '' ? $show_all : $info->definition_flags;
$data['selected_definition_flags'] = $this->get_attributes($selected_flags);
echo view('attributes/form', $data);
@@ -217,13 +201,12 @@ class Attributes extends Secure_Controller
/**
* Deletes an attribute definition
* @return void
*/
public function postDelete(): void
{
$attributes_to_delete = $this->request->getPost('ids', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
if($this->attribute->deleteDefinitionList($attributes_to_delete)) {
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]);
} else {

View File

@@ -6,7 +6,6 @@ use App\Models\Cashup;
use App\Models\Expense;
use App\Models\Reports\Summary_payments;
use Config\OSPOS;
use Config\Services;
class Cashups extends Secure_Controller
{
@@ -19,15 +18,12 @@ class Cashups extends Secure_Controller
{
parent::__construct('cashups');
$this->cashup = model(Cashup::class);
$this->expense = model(Expense::class);
$this->cashup = model(Cashup::class);
$this->expense = model(Expense::class);
$this->summary_payments = model(Summary_payments::class);
$this->config = config(OSPOS::class)->settings;
$this->config = config(OSPOS::class)->settings;
}
/**
* @return void
*/
public function getIndex(): void
{
$data['table_headers'] = get_cashups_manage_table_headers();
@@ -38,28 +34,26 @@ class Cashups extends Secure_Controller
echo view('cashups/manage', $data);
}
/**
* @return void
*/
public function getSearch(): void
{
$search = $this->request->getGet('search');
$limit = $this->request->getGet('limit', FILTER_SANITIZE_NUMBER_INT);
$offset = $this->request->getGet('offset', FILTER_SANITIZE_NUMBER_INT);
$sort = $this->sanitizeSortColumn(cashup_headers(), $this->request->getGet('sort', FILTER_SANITIZE_FULL_SPECIAL_CHARS), 'cashup_id');
$order = $this->request->getGet('order', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$search = $this->request->getGet('search');
$limit = $this->request->getGet('limit', FILTER_SANITIZE_NUMBER_INT);
$offset = $this->request->getGet('offset', FILTER_SANITIZE_NUMBER_INT);
$sort = $this->sanitizeSortColumn(cashup_headers(), $this->request->getGet('sort', FILTER_SANITIZE_FULL_SPECIAL_CHARS), 'cashup_id');
$order = $this->request->getGet('order', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$filters = [
'start_date' => $this->request->getGet('start_date', FILTER_SANITIZE_FULL_SPECIAL_CHARS), // TODO: Is this the best way to filter dates
'end_date' => $this->request->getGet('end_date', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
'is_deleted' => false
'is_deleted' => false,
];
// Check if any filter is set in the multiselect dropdown
$request_filters = array_fill_keys($this->request->getGet('filters', FILTER_SANITIZE_FULL_SPECIAL_CHARS) ?? [], true);
$filters = array_merge($filters, $request_filters);
$cash_ups = $this->cashup->search($search, $filters, $limit, $offset, $sort, $order);
$total_rows = $this->cashup->get_found_rows($search, $filters);
$data_rows = [];
$filters = array_merge($filters, $request_filters);
$cash_ups = $this->cashup->search($search, $filters, $limit, $offset, $sort, $order);
$total_rows = $this->cashup->get_found_rows($search, $filters);
$data_rows = [];
foreach ($cash_ups->getResult() as $cash_up) {
$data_rows[] = get_cash_up_data_row($cash_up);
}
@@ -67,18 +61,15 @@ class Cashups extends Secure_Controller
echo json_encode(['total' => $total_rows, 'rows' => $data_rows]);
}
/**
* @param int $cashup_id
* @return void
*/
public function getView(int $cashup_id = NEW_ENTRY): void
{
$data = [];
$data['employees'] = [];
foreach ($this->employee->get_all()->getResult() as $employee) {
foreach (get_object_vars($employee) as $property => $value) {
$employee->$property = $value;
$employee->{$property} = $value;
}
$data['employees'][$employee->person_id] = $employee->first_name . ' ' . $employee->last_name;
@@ -87,22 +78,22 @@ class Cashups extends Secure_Controller
$cash_ups_info = $this->cashup->get_info($cashup_id);
foreach (get_object_vars($cash_ups_info) as $property => $value) {
$cash_ups_info->$property = $value;
$cash_ups_info->{$property} = $value;
}
// Open cashup
if ($cash_ups_info->cashup_id == NEW_ENTRY) {
$cash_ups_info->open_date = date('Y-m-d H:i:s');
$cash_ups_info->close_date = $cash_ups_info->open_date;
$cash_ups_info->open_employee_id = $this->employee->get_logged_in_employee_info()->person_id;
if ($cash_ups_info->cashup_id === NEW_ENTRY) {
$cash_ups_info->open_date = date('Y-m-d H:i:s');
$cash_ups_info->close_date = $cash_ups_info->open_date;
$cash_ups_info->open_employee_id = $this->employee->get_logged_in_employee_info()->person_id;
$cash_ups_info->close_employee_id = $this->employee->get_logged_in_employee_info()->person_id;
}
// If all the amounts are null or 0 that means it's a close cashup
elseif (
floatval($cash_ups_info->closed_amount_cash) == 0
&& floatval($cash_ups_info->closed_amount_due) == 0
&& floatval($cash_ups_info->closed_amount_card) == 0
&& floatval($cash_ups_info->closed_amount_check) == 0
(float) ($cash_ups_info->closed_amount_cash) === 0
&& (float) ($cash_ups_info->closed_amount_due) === 0
&& (float) ($cash_ups_info->closed_amount_card) === 0
&& (float) ($cash_ups_info->closed_amount_check) === 0
) {
// Set the close date and time to the actual as this is a close session
$cash_ups_info->close_date = date('Y-m-d H:i:s');
@@ -112,12 +103,12 @@ class Cashups extends Secure_Controller
// If it's date mode only and not date & time truncate the open and end date to date only
if (empty($this->config['date_or_time_format'])) {
if ($cash_ups_info->open_date != null) {
if ($cash_ups_info->open_date !== null) {
$start_date = substr($cash_ups_info->open_date, 0, 10);
} else {
$start_date = null;
}
if ($cash_ups_info->close_date != null) {
if ($cash_ups_info->close_date !== null) {
$end_date = substr($cash_ups_info->close_date, 0, 10);
} else {
$end_date = null;
@@ -127,7 +118,7 @@ class Cashups extends Secure_Controller
'start_date' => $start_date,
'end_date' => $end_date,
'sale_type' => 'complete',
'location_id' => 'all'
'location_id' => 'all',
];
} else {
// Search for all the payments given the time range
@@ -135,7 +126,7 @@ class Cashups extends Secure_Controller
'start_date' => $cash_ups_info->open_date,
'end_date' => $cash_ups_info->close_date,
'sale_type' => 'complete',
'location_id' => 'all'
'location_id' => 'all',
];
}
@@ -143,17 +134,17 @@ class Cashups extends Secure_Controller
$reports_data = $this->summary_payments->getData($inputs);
foreach ($reports_data as $row) {
if ($row['trans_group'] == lang('Reports.trans_payments')) {
if ($row['trans_type'] == lang('Sales.cash')) {
if ($row['trans_group'] === lang('Reports.trans_payments')) {
if ($row['trans_type'] === lang('Sales.cash')) {
$cash_ups_info->closed_amount_cash += $row['trans_amount'];
} elseif ($row['trans_type'] == lang('Sales.due')) {
} elseif ($row['trans_type'] === lang('Sales.due')) {
$cash_ups_info->closed_amount_due += $row['trans_amount'];
} elseif (
$row['trans_type'] == lang('Sales.debit') ||
$row['trans_type'] == lang('Sales.credit')
$row['trans_type'] === lang('Sales.debit')
|| $row['trans_type'] === lang('Sales.credit')
) {
$cash_ups_info->closed_amount_card += $row['trans_amount'];
} elseif ($row['trans_type'] == lang('Sales.check')) {
} elseif ($row['trans_type'] === lang('Sales.check')) {
$cash_ups_info->closed_amount_check += $row['trans_amount'];
}
}
@@ -166,7 +157,7 @@ class Cashups extends Secure_Controller
'only_check' => false,
'only_credit' => false,
'only_debit' => false,
'is_deleted' => false
'is_deleted' => false,
];
$payments = $this->expense->get_payments_summary('', array_merge($inputs, $filters));
@@ -180,31 +171,23 @@ class Cashups extends Secure_Controller
$data['cash_ups_info'] = $cash_ups_info;
echo view("cashups/form", $data);
echo view('cashups/form', $data);
}
/**
* @param int $row_id
* @return void
*/
public function getRow(int $row_id): void
{
$cash_ups_info = $this->cashup->get_info($row_id);
$data_row = get_cash_up_data_row($cash_ups_info);
$data_row = get_cash_up_data_row($cash_ups_info);
echo json_encode($data_row);
}
/**
* @param int $cashup_id
* @return void
*/
public function postSave(int $cashup_id = NEW_ENTRY): void
{
$open_date = $this->request->getPost('open_date');
$open_date = $this->request->getPost('open_date');
$open_date_formatter = date_create_from_format($this->config['dateformat'] . ' ' . $this->config['timeformat'], $open_date);
$close_date = $this->request->getPost('close_date');
$close_date = $this->request->getPost('close_date');
$close_date_formatter = date_create_from_format($this->config['dateformat'] . ' ' . $this->config['timeformat'], $close_date);
$cash_up_data = [
@@ -217,16 +200,16 @@ class Cashups extends Secure_Controller
'closed_amount_card' => parse_decimals($this->request->getPost('closed_amount_card')),
'closed_amount_check' => parse_decimals($this->request->getPost('closed_amount_check')),
'closed_amount_total' => parse_decimals($this->request->getPost('closed_amount_total')),
'note' => $this->request->getPost('note') != null,
'note' => $this->request->getPost('note') !== null,
'description' => $this->request->getPost('description', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
'open_employee_id' => $this->request->getPost('open_employee_id', FILTER_SANITIZE_NUMBER_INT),
'close_employee_id' => $this->request->getPost('close_employee_id', FILTER_SANITIZE_NUMBER_INT),
'deleted' => $this->request->getPost('deleted') != null
'deleted' => $this->request->getPost('deleted') !== null,
];
if ($this->cashup->save_value($cash_up_data, $cashup_id)) {
// New cashup_id
if ($cashup_id == NEW_ENTRY) {
if ($cashup_id === NEW_ENTRY) {
echo json_encode(['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]);
@@ -236,9 +219,6 @@ class Cashups extends Secure_Controller
}
}
/**
* @return void
*/
public function postDelete(): void
{
$cash_ups_to_delete = $this->request->getPost('ids', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
@@ -253,17 +233,16 @@ class Cashups extends Secure_Controller
/**
* Calculate the total for cashups. Used in app\Views\cashups\form.php
*
* @return void
* @noinspection PhpUnused
*/
public function postAjax_cashup_total(): void
{
$open_amount_cash = parse_decimals($this->request->getPost('open_amount_cash'));
$open_amount_cash = parse_decimals($this->request->getPost('open_amount_cash'));
$transfer_amount_cash = parse_decimals($this->request->getPost('transfer_amount_cash'));
$closed_amount_cash = parse_decimals($this->request->getPost('closed_amount_cash'));
$closed_amount_due = parse_decimals($this->request->getPost('closed_amount_due'));
$closed_amount_card = parse_decimals($this->request->getPost('closed_amount_card'));
$closed_amount_check = parse_decimals($this->request->getPost('closed_amount_check'));
$closed_amount_cash = parse_decimals($this->request->getPost('closed_amount_cash'));
$closed_amount_due = parse_decimals($this->request->getPost('closed_amount_due'));
$closed_amount_card = parse_decimals($this->request->getPost('closed_amount_card'));
$closed_amount_check = parse_decimals($this->request->getPost('closed_amount_check'));
$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
@@ -272,9 +251,11 @@ class Cashups extends Secure_Controller
/**
* Calculate total
*
* @param mixed $closed_amount_check
*/
private function _calculate_total(float $open_amount_cash, float $transfer_amount_cash, float $closed_amount_due, float $closed_amount_cash, float $closed_amount_card, $closed_amount_check): float // TODO: need to get rid of hungarian notation here. Also, the signature is pretty long. Perhaps they need to go into an object or array?
{
return ($closed_amount_cash - $open_amount_cash - $transfer_amount_cash + $closed_amount_due + $closed_amount_card + $closed_amount_check);
return $closed_amount_cash - $open_amount_cash - $transfer_amount_cash + $closed_amount_due + $closed_amount_card + $closed_amount_check;
}
}

View File

@@ -11,8 +11,8 @@ use App\Models\Appconfig;
use App\Models\Attribute;
use App\Models\Customer_rewards;
use App\Models\Dinner_table;
use App\Models\Module;
use App\Models\Enums\Rounding_mode;
use App\Models\Module;
use App\Models\Stock_location;
use App\Models\Tax;
use CodeIgniter\Database\BaseConnection;
@@ -42,24 +42,23 @@ class Config extends Secure_Controller
private Tax $tax;
private array $config;
public function __construct()
{
parent::__construct('config');
$this->barcode_lib = new Barcode_lib();
$this->sale_lib = new Sale_lib();
$this->receiving_lib = new receiving_lib();
$this->tax_lib = new Tax_lib();
$this->appconfig = model(Appconfig::class);
$this->attribute = model(Attribute::class);
$this->barcode_lib = new Barcode_lib();
$this->sale_lib = new Sale_lib();
$this->receiving_lib = new Receiving_lib();
$this->tax_lib = new Tax_lib();
$this->appconfig = model(Appconfig::class);
$this->attribute = model(Attribute::class);
$this->customer_rewards = model(Customer_rewards::class);
$this->dinner_table = model(Dinner_table::class);
$this->module = model(Module::class);
$this->stock_location = model(Stock_location::class);
$this->tax = model(Tax::class);
$this->config = config(OSPOS::class)->settings;
$this->db = Database::connect();
$this->dinner_table = model(Dinner_table::class);
$this->module = model(Module::class);
$this->stock_location = model(Stock_location::class);
$this->tax = model(Tax::class);
$this->config = config(OSPOS::class)->settings;
$this->db = Database::connect();
helper('security');
if (check_encryption()) {
@@ -74,11 +73,11 @@ class Config extends Secure_Controller
*/
private function _licenses(): array // TODO: remove hungarian notation. Super long function. Perhaps we need to refactor out functions?
{
$i = 0;
$i = 0;
$composer = false;
$npmProd = false;
$npmDev = false;
$license = [];
$npmProd = false;
$npmDev = false;
$license = [];
$license[$i]['title'] = 'Open Source Point Of Sale ' . config('App')->application_version;
@@ -93,8 +92,8 @@ class Config extends Secure_Controller
foreach ($dir as $fileinfo) { // TODO: $fileinfo doesn't match our variable naming convention
// License files must be in couples: .version (name & version) & .license (license text)
if ($fileinfo->isFile()) {
if ($fileinfo->getExtension() == 'version') {
++$i;
if ($fileinfo->getExtension() === 'version') {
$i++;
$basename = 'license/' . $fileinfo->getBasename('.version');
@@ -107,13 +106,13 @@ class Config extends Secure_Controller
} else {
$license[$i]['text'] = $license_text_file . ' file is missing';
}
} elseif ($fileinfo->getBasename() == 'composer.LICENSES') {
} elseif ($fileinfo->getBasename() === 'composer.LICENSES') {
// Set a flag to indicate that the composer.LICENSES file is available and needs to be attached at the end
$composer = true;
} elseif ($fileinfo->getBasename() == 'npm-prod.LICENSES') {
} elseif ($fileinfo->getBasename() === 'npm-prod.LICENSES') {
// Set a flag to indicate that the npm-prod.LICENSES file is available and needs to be attached at the end
$npmProd = true;
} elseif ($fileinfo->getBasename() == 'npm-dev.LICENSES') {
} elseif ($fileinfo->getBasename() === 'npm-dev.LICENSES') {
// Set a flag to indicate that the npm-dev.LICENSES file is available and needs to be attached at the end
$npmDev = true;
}
@@ -122,22 +121,22 @@ class Config extends Secure_Controller
// Attach the licenses from the LICENSES file generated by Composer
if ($composer) {
++$i;
$i++;
$license[$i]['title'] = 'Composer Libraries';
$license[$i]['text'] = '';
$license[$i]['text'] = '';
$file = file_get_contents('license/composer.LICENSES');
$file = file_get_contents('license/composer.LICENSES');
$array = json_decode($file, true);
if (isset($array['dependencies'])) {
foreach ($array['dependencies'] as $dependency => $details) {
$license[$i]['text'] .= "library: $dependency\n";
$license[$i]['text'] .= "library: {$dependency}\n";
foreach ($details as $key => $value) {
if (is_array($value)) {
$license[$i]['text'] .= "$key: " . implode(' ', $value) . "\n";
$license[$i]['text'] .= "{$key}: " . implode(' ', $value) . "\n";
} else {
$license[$i]['text'] .= "$key: $value\n";
$license[$i]['text'] .= "{$key}: {$value}\n";
}
}
@@ -149,11 +148,11 @@ class Config extends Secure_Controller
// Attach the licenses from the LICENSES file generated by license-report
if ($npmProd) {
++$i;
$i++;
$license[$i]['title'] = 'NPM Production Libraries';
$license[$i]['text'] = '';
$license[$i]['text'] = '';
$file = file_get_contents('license/npm-prod.LICENSES');
$file = file_get_contents('license/npm-prod.LICENSES');
$array = json_decode($file, true);
foreach ($array as $dependency) {
@@ -169,11 +168,11 @@ class Config extends Secure_Controller
}
if ($npmDev) {
++$i;
$i++;
$license[$i]['title'] = 'NPM Development Libraries';
$license[$i]['text'] = '';
$license[$i]['text'] = '';
$file = file_get_contents('license/npm-dev.LICENSES');
$file = file_get_contents('license/npm-dev.LICENSES');
$array = json_decode($file, true);
foreach ($array as $dependency) {
@@ -193,7 +192,6 @@ class Config extends Secure_Controller
/**
* This function loads all the available themes in the dist/bootswatch directory
* @return array
*/
private function _themes(): array // TODO: Hungarian notation
{
@@ -203,8 +201,8 @@ class Config extends Secure_Controller
$dir = new DirectoryIterator('resources/bootswatch');
foreach ($dir as $dirinfo) { // TODO: $dirinfo doesn't follow naming convention
if ($dirinfo->isDir() && !$dirinfo->isDot() && $dirinfo->getFileName() != 'fonts') {
$file = $dirinfo->getFileName();
if ($dirinfo->isDir() && ! $dirinfo->isDot() && $dirinfo->getFileName() !== 'fonts') {
$file = $dirinfo->getFileName();
$themes[$file] = ucfirst($file);
}
}
@@ -214,26 +212,24 @@ class Config extends Secure_Controller
return $themes;
}
/**
*/
public function getIndex(): void
{
$data['stock_locations'] = $this->stock_location->get_all()->getResultArray();
$data['dinner_tables'] = $this->dinner_table->get_all()->getResultArray();
$data['customer_rewards'] = $this->customer_rewards->get_all()->getResultArray();
$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['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();
$data['rounding_options'] = rounding_mode::get_rounding_options();
$data['tax_code_options'] = $this->tax_lib->get_tax_code_options();
$data['tax_category_options'] = $this->tax_lib->get_tax_category_options();
$data['stock_locations'] = $this->stock_location->get_all()->getResultArray();
$data['dinner_tables'] = $this->dinner_table->get_all()->getResultArray();
$data['customer_rewards'] = $this->customer_rewards->get_all()->getResultArray();
$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['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();
$data['rounding_options'] = Rounding_mode::get_rounding_options();
$data['tax_code_options'] = $this->tax_lib->get_tax_code_options();
$data['tax_category_options'] = $this->tax_lib->get_tax_category_options();
$data['tax_jurisdiction_options'] = $this->tax_lib->get_tax_jurisdiction_options();
$data['show_office_group'] = $this->module->get_show_office_group();
$data['currency_code'] = $this->config['currency_code'] ?? '';
$data['dbVersion'] = mysqli_get_server_info($this->db->getConnection());
$data['show_office_group'] = $this->module->get_show_office_group();
$data['currency_code'] = $this->config['currency_code'] ?? '';
$data['dbVersion'] = mysqli_get_server_info($this->db->getConnection());
// Load all the license statements, they are already XSS cleaned in the private function
$data['licenses'] = $this->_licenses();
@@ -242,24 +238,24 @@ class Config extends Secure_Controller
$data['themes'] = $this->_themes();
// General related fields
$image_allowed_types = ['jpg', 'jpeg', 'gif', 'svg', 'webp', 'bmp', 'png', 'tif', 'tiff'];
$data['image_allowed_types'] = array_combine($image_allowed_types, $image_allowed_types);
$image_allowed_types = ['jpg', 'jpeg', 'gif', 'svg', 'webp', 'bmp', 'png', 'tif', 'tiff'];
$data['image_allowed_types'] = array_combine($image_allowed_types, $image_allowed_types);
$data['selected_image_allowed_types'] = explode(',', $this->config['image_allowed_types']);
// Integrations Related fields
$data['mailchimp'] = [];
$data['mailchimp'] = [];
if (check_encryption()) { // TODO: Hungarian notation
if (!isset($this->encrypter)) {
if (! isset($this->encrypter)) {
helper('security');
$this->encrypter = Services::encrypter();
}
$data['mailchimp']['api_key'] = (isset($this->config['mailchimp_api_key']) && !empty($this->config['mailchimp_api_key']))
$data['mailchimp']['api_key'] = (isset($this->config['mailchimp_api_key']) && ! empty($this->config['mailchimp_api_key']))
? $this->encrypter->decrypt($this->config['mailchimp_api_key'])
: '';
$data['mailchimp']['list_id'] = (isset($this->config['mailchimp_list_id']) && !empty($this->config['mailchimp_list_id']))
$data['mailchimp']['list_id'] = (isset($this->config['mailchimp_list_id']) && ! empty($this->config['mailchimp_list_id']))
? $this->encrypter->decrypt($this->config['mailchimp_list_id'])
: '';
@@ -279,12 +275,11 @@ class Config extends Secure_Controller
* Saves company information. Used in app/Views/configs/info_config.php
*
* @throws ReflectionException
* @return void
* @noinspection PhpUnused
*/
public function postSaveInfo(): void
{
$upload_data = $this->upload_logo();
$upload_data = $this->upload_logo();
$upload_success = empty($upload_data['error']);
$batch_save_data = [
@@ -294,14 +289,14 @@ class Config extends Secure_Controller
'email' => strtolower($this->request->getPost('email', FILTER_SANITIZE_EMAIL)),
'fax' => $this->request->getPost('fax'),
'website' => $this->request->getPost('website', FILTER_SANITIZE_URL),
'return_policy' => $this->request->getPost('return_policy')
'return_policy' => $this->request->getPost('return_policy'),
];
if (!empty($upload_data['orig_name']) && $upload_data['raw_name']) {
if (! empty($upload_data['orig_name']) && $upload_data['raw_name']) {
$batch_save_data['company_logo'] = $upload_data['raw_name'] . '.' . $upload_data['file_ext'];
}
$result = $this->appconfig->batch_save($batch_save_data);
$result = $this->appconfig->batch_save($batch_save_data);
$success = $upload_success && $result;
$message = lang('Config.saved_' . ($success ? '' : 'un') . 'successfully');
$message = $upload_success ? $message : strip_tags($upload_data['error']);
@@ -309,14 +304,10 @@ class Config extends Secure_Controller
echo json_encode(['success' => $success, 'message' => $message]);
}
/**
* @return array
*/
private function upload_logo(): array
{
$file = $this->request->getFile('company_logo');
if (!$file) {
if (! $file) {
return [];
}
@@ -331,27 +322,26 @@ class Config extends Secure_Controller
'mime_in[company_logo,image/png,image/jpg,image/jpeg,image/gif]',
'ext_in[company_logo,png,jpg,gif]',
'max_dims[company_logo,800,680]',
]
]
],
],
];
if (!$this->validate($validation_rule)) {
return (['error' => $this->validator->getError('company_logo')]);
if (! $this->validate($validation_rule)) {
return ['error' => $this->validator->getError('company_logo')];
}
$filename = $file->getClientName();
$info = pathinfo($filename);
$info = pathinfo($filename);
$file_info = [
'orig_name' => $filename,
'raw_name' => $info['filename'],
'file_ext' => $file->guessExtension()
'file_ext' => $file->guessExtension(),
];
$file->move(FCPATH . 'uploads/', $file_info['raw_name'] . '.' . $file_info['file_ext'], true);
return ($file_info);
return $file_info;
}
/**
@@ -362,15 +352,15 @@ class Config extends Secure_Controller
*/
public function postSaveGeneral(): void
{
$batchSaveData = [
$batch_save_data = [
'theme' => $this->request->getPost('theme'),
'login_form' => $this->request->getPost('login_form'),
'default_sales_discount_type' => $this->request->getPost('default_sales_discount_type') != null,
'default_sales_discount_type' => $this->request->getPost('default_sales_discount_type') !== null,
'default_sales_discount' => parse_decimals($this->request->getPost('default_sales_discount')),
'default_receivings_discount_type' => $this->request->getPost('default_receivings_discount_type') != null,
'default_receivings_discount_type' => $this->request->getPost('default_receivings_discount_type') !== null,
'default_receivings_discount' => parse_decimals($this->request->getPost('default_receivings_discount')),
'enforce_privacy' => $this->request->getPost('enforce_privacy') != null,
'receiving_calculate_average_price' => $this->request->getPost('receiving_calculate_average_price') != null,
'enforce_privacy' => $this->request->getPost('enforce_privacy') !== null,
'receiving_calculate_average_price' => $this->request->getPost('receiving_calculate_average_price') !== null,
'lines_per_page' => $this->request->getPost('lines_per_page', FILTER_SANITIZE_NUMBER_INT),
'notify_horizontal_position' => $this->request->getPost('notify_horizontal_position'),
'notify_vertical_position' => $this->request->getPost('notify_vertical_position'),
@@ -378,34 +368,34 @@ class Config extends Secure_Controller
'image_max_height' => $this->request->getPost('image_max_height', FILTER_SANITIZE_NUMBER_INT),
'image_max_size' => $this->request->getPost('image_max_size', FILTER_SANITIZE_NUMBER_INT),
'image_allowed_types' => implode(',', $this->request->getPost('image_allowed_types')),
'gcaptcha_enable' => $this->request->getPost('gcaptcha_enable') != null,
'gcaptcha_enable' => $this->request->getPost('gcaptcha_enable') !== null,
'gcaptcha_secret_key' => $this->request->getPost('gcaptcha_secret_key'),
'gcaptcha_site_key' => $this->request->getPost('gcaptcha_site_key'),
'suggestions_first_column' => $this->request->getPost('suggestions_first_column'),
'suggestions_second_column' => $this->request->getPost('suggestions_second_column'),
'suggestions_third_column' => $this->request->getPost('suggestions_third_column'),
'giftcard_number' => $this->request->getPost('giftcard_number'),
'derive_sale_quantity' => $this->request->getPost('derive_sale_quantity') != null,
'multi_pack_enabled' => $this->request->getPost('multi_pack_enabled') != null,
'include_hsn' => $this->request->getPost('include_hsn') != null,
'category_dropdown' => $this->request->getPost('category_dropdown') != null
'derive_sale_quantity' => $this->request->getPost('derive_sale_quantity') !== null,
'multi_pack_enabled' => $this->request->getPost('multi_pack_enabled') !== null,
'include_hsn' => $this->request->getPost('include_hsn') !== null,
'category_dropdown' => $this->request->getPost('category_dropdown') !== null,
];
$this->module->set_show_office_group($this->request->getPost('show_office_group') != null);
$this->module->set_show_office_group($this->request->getPost('show_office_group') !== null);
if ($batchSaveData['category_dropdown']) {
$definitionData['definition_name'] = 'ospos_category';
$definitionData['definition_flags'] = 0;
$definitionData['definition_type'] = 'DROPDOWN';
$definitionData['definition_id'] = CATEGORY_DEFINITION_ID;
$definitionData['deleted'] = 0;
if ($batch_save_data['category_dropdown'] === 1) {
$definition_data['definition_name'] = 'ospos_category';
$definition_data['definition_flags'] = 0;
$definition_data['definition_type'] = 'DROPDOWN';
$definition_data['definition_id'] = CATEGORY_DEFINITION_ID;
$definition_data['deleted'] = 0;
$this->attribute->saveDefinition($definitionData, CATEGORY_DEFINITION_ID);
} elseif ($batchSaveData['category_dropdown'] == NO_DEFINITION_ID) {
$this->attribute->save_definition($definition_data, CATEGORY_DEFINITION_ID);
} elseif ($batch_save_data['category_dropdown'] === NO_DEFINITION_ID) {
$this->attribute->deleteDefinition(CATEGORY_DEFINITION_ID);
}
$success = $this->appconfig->batch_save($batchSaveData);
$success = $this->appconfig->batch_save($batch_save_data);
echo json_encode(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
}
@@ -413,25 +403,24 @@ class Config extends Secure_Controller
/**
* Checks a number against the currently selected locale. Used in app/Views/configs/locale_config.php
*
* @return void
* @noinspection PhpUnused
*/
public function postCheckNumberLocale(): void
{
$number_locale = $this->request->getPost('number_locale');
$number_locale = $this->request->getPost('number_locale');
$save_number_locale = $this->request->getPost('save_number_locale');
$fmt = new NumberFormatter($number_locale, NumberFormatter::CURRENCY);
if ($number_locale != $save_number_locale) {
$currency_symbol = $fmt->getSymbol(NumberFormatter::CURRENCY_SYMBOL);
$currency_code = $fmt->getTextAttribute(NumberFormatter::CURRENCY_CODE);
if ($number_locale !== $save_number_locale) {
$currency_symbol = $fmt->getSymbol(NumberFormatter::CURRENCY_SYMBOL);
$currency_code = $fmt->getTextAttribute(NumberFormatter::CURRENCY_CODE);
$save_number_locale = $number_locale;
} else {
$currency_symbol = empty($this->request->getPost('currency_symbol')) ? $fmt->getSymbol(NumberFormatter::CURRENCY_SYMBOL) : $this->request->getPost('currency_symbol');
$currency_code = empty($this->request->getPost('currency_code')) ? $fmt->getTextAttribute(NumberFormatter::CURRENCY_CODE) : $this->request->getPost('currency_code');
$currency_code = empty($this->request->getPost('currency_code')) ? $fmt->getTextAttribute(NumberFormatter::CURRENCY_CODE) : $this->request->getPost('currency_code');
}
if ($this->request->getPost('thousands_separator') == 'false') {
if ($this->request->getPost('thousands_separator') === 'false') {
$fmt->setTextAttribute(NumberFormatter::GROUPING_SEPARATOR_SYMBOL, '');
}
@@ -439,7 +428,7 @@ class Config extends Secure_Controller
$number_local_example = $fmt->format(1234567890.12300);
echo json_encode([
'success' => $number_local_example != false,
'success' => $number_local_example !== false,
'save_number_locale' => $save_number_locale,
'number_locale_example' => $number_local_example,
'currency_symbol' => $currency_symbol,
@@ -451,12 +440,11 @@ class Config extends Secure_Controller
* Saves locale configuration. Used in app/Views/configs/locale_config.php
*
* @throws ReflectionException
* @return void
* @noinspection PhpUnused
*/
public function postSaveLocale(): void
{
$exploded = explode(":", $this->request->getPost('language'));
$exploded = explode(':', $this->request->getPost('language'));
$batch_save_data = [
'currency_symbol' => $this->request->getPost('currency_symbol'),
'currency_code' => $this->request->getPost('currency_code'),
@@ -465,17 +453,17 @@ class Config extends Secure_Controller
'timezone' => $this->request->getPost('timezone'),
'dateformat' => $this->request->getPost('dateformat'),
'timeformat' => $this->request->getPost('timeformat'),
'thousands_separator' => $this->request->getPost('thousands_separator') != null,
'thousands_separator' => $this->request->getPost('thousands_separator') !== null,
'number_locale' => $this->request->getPost('number_locale'),
'currency_decimals' => $this->request->getPost('currency_decimals', FILTER_SANITIZE_NUMBER_INT),
'tax_decimals' => $this->request->getPost('tax_decimals', FILTER_SANITIZE_NUMBER_INT),
'quantity_decimals' => $this->request->getPost('quantity_decimals', FILTER_SANITIZE_NUMBER_INT),
'country_codes' => htmlspecialchars($this->request->getPost('country_codes')),
'payment_options_order' => $this->request->getPost('payment_options_order'),
'date_or_time_format' => $this->request->getPost('date_or_time_format') != null,
'date_or_time_format' => $this->request->getPost('date_or_time_format') !== null,
'cash_decimals' => $this->request->getPost('cash_decimals', FILTER_SANITIZE_NUMBER_INT),
'cash_rounding_code' => $this->request->getPost('cash_rounding_code'),
'financial_year' => $this->request->getPost('financial_year', FILTER_SANITIZE_NUMBER_INT)
'financial_year' => $this->request->getPost('financial_year', FILTER_SANITIZE_NUMBER_INT),
];
$success = $this->appconfig->batch_save($batch_save_data);
@@ -487,14 +475,13 @@ class Config extends Secure_Controller
* Saves email configuration. Used in app/Views/configs/email_config.php
*
* @throws ReflectionException
* @return void
* @noinspection PhpUnused
*/
public function postSaveEmail(): void
{
$password = '';
if (check_encryption() && !empty($this->request->getPost('smtp_pass'))) {
if (check_encryption() && ! empty($this->request->getPost('smtp_pass'))) {
$password = $this->encrypter->encrypt($this->request->getPost('smtp_pass'));
}
@@ -506,7 +493,7 @@ class Config extends Secure_Controller
'smtp_pass' => $password,
'smtp_port' => $this->request->getPost('smtp_port', FILTER_SANITIZE_NUMBER_INT),
'smtp_timeout' => $this->request->getPost('smtp_timeout', FILTER_SANITIZE_NUMBER_INT),
'smtp_crypto' => $this->request->getPost('smtp_crypto')
'smtp_crypto' => $this->request->getPost('smtp_crypto'),
];
$success = $this->appconfig->batch_save($batch_save_data);
@@ -518,14 +505,13 @@ class Config extends Secure_Controller
* Saves SMS message configuration. Used in app/Views/configs/message_config.php.
*
* @throws ReflectionException
* @return void
* @noinspection PhpUnused
*/
public function postSaveMessage(): void
{
$password = '';
if (check_encryption() && !empty($this->request->getPost('msg_pwd'))) {
if (check_encryption() && ! empty($this->request->getPost('msg_pwd'))) {
$password = $this->encrypter->encrypt($this->request->getPost('msg_pwd'));
}
@@ -533,7 +519,7 @@ class Config extends Secure_Controller
'msg_msg' => $this->request->getPost('msg_msg'),
'msg_uid' => $this->request->getPost('msg_uid'),
'msg_pwd' => $password,
'msg_src' => $this->request->getPost('msg_src')
'msg_src' => $this->request->getPost('msg_src'),
];
$success = $this->appconfig->batch_save($batch_save_data);
@@ -552,7 +538,7 @@ class Config extends Secure_Controller
$lists = $mailchimp_lib->getLists();
if ($lists !== false) {
if (is_array($lists) && !empty($lists['lists']) && is_array($lists['lists'])) {
if (is_array($lists) && ! empty($lists['lists']) && is_array($lists['lists'])) {
foreach ($lists['lists'] as $list) {
$result[$list['id']] = $list['name'] . ' [' . $list['stats']['member_count'] . ']';
}
@@ -565,18 +551,17 @@ 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
* @noinspection PhpUnused
*/
public function postCheckMailchimpApiKey(): void
{
$lists = $this->_mailchimp($this->request->getPost('mailchimp_api_key'));
$lists = $this->_mailchimp($this->request->getPost('mailchimp_api_key'));
$success = count($lists) > 0;
echo json_encode([
'success' => $success,
'message' => lang('Config.mailchimp_key_' . ($success ? '' : 'un') . 'successfully'),
'mailchimp_lists' => $lists
'mailchimp_lists' => $lists,
]);
}
@@ -584,7 +569,6 @@ class Config extends Secure_Controller
* Saves Mailchimp configuration. Used in app/Views/configs/integrations_config.php
*
* @throws ReflectionException
* @return void
* @noinspection PhpUnused
*/
public function postSaveMailchimp(): void
@@ -594,12 +578,12 @@ class Config extends Secure_Controller
if (check_encryption()) {
$api_key_unencrypted = $this->request->getPost('mailchimp_api_key');
if (!empty($api_key_unencrypted)) {
if (! empty($api_key_unencrypted)) {
$api_key = $this->encrypter->encrypt($api_key_unencrypted);
}
$list_id_unencrypted = $this->request->getPost('mailchimp_list_id');
if (!empty($list_id_unencrypted)) {
if (! empty($list_id_unencrypted)) {
$list_id = $this->encrypter->encrypt($list_id_unencrypted);
}
}
@@ -614,7 +598,6 @@ class Config extends Secure_Controller
/**
* Gets all stock locations. Used in app/Views/configs/stock_config.php
*
* @return void
* @noinspection PhpUnused
*/
public function getStockLocations(): void
@@ -624,9 +607,6 @@ class Config extends Secure_Controller
echo view('partial/stock_locations', ['stock_locations' => $stock_locations]);
}
/**
* @return void
*/
public function getDinnerTables(): void
{
$dinner_tables = $this->dinner_table->get_all()->getResultArray();
@@ -634,11 +614,8 @@ class Config extends Secure_Controller
echo view('partial/dinner_tables', ['dinner_tables' => $dinner_tables]);
}
/**
* Gets all tax categories.
*
* @return void
*/
public function ajax_tax_categories(): void // TODO: Is this function called anywhere in the code?
{
@@ -650,7 +627,6 @@ class Config extends Secure_Controller
/**
* Gets all customer rewards. Used in app/Views/configs/reward_config.php
*
* @return void
* @noinspection PhpUnused
*/
public function getCustomerRewards(): void
@@ -660,9 +636,6 @@ class Config extends Secure_Controller
echo view('partial/customer_rewards', ['customer_rewards' => $customer_rewards]);
}
/**
* @return void
*/
private function _clear_session_state(): void // TODO: Hungarian notation
{
$this->sale_lib->clear_sale_location();
@@ -677,7 +650,6 @@ class Config extends Secure_Controller
/**
* Saves stock locations. Used in app/Views/configs/stock_config.php
*
* @return void
* @noinspection PhpUnused
*/
public function postSaveLocations(): void
@@ -685,13 +657,14 @@ class Config extends Secure_Controller
$this->db->transStart();
$not_to_delete = [];
foreach ($this->request->getPost() as $key => $value) {
if (str_contains($key, 'stock_location')) {
// Save or update
foreach ($value as $location_id => $location_name) {
$location_data = ['location_name' => $location_name];
if ($this->stock_location->save_value($location_data, $location_id)) {
$location_id = $this->stock_location->get_location_id($location_name);
$location_id = $this->stock_location->get_location_id($location_name);
$not_to_delete[] = $location_id;
$this->_clear_session_state();
}
@@ -703,7 +676,7 @@ class Config extends Secure_Controller
$deleted_locations = $this->stock_location->get_all()->getResultArray();
foreach ($deleted_locations as $location => $location_data) {
if (!in_array($location_data['location_id'], $not_to_delete)) {
if (! in_array($location_data['location_id'], $not_to_delete, true)) {
$this->stock_location->delete($location_data['location_id']);
}
}
@@ -719,22 +692,22 @@ class Config extends Secure_Controller
* Saves all dinner tables. Used in app/Views/configs/table_config.php
*
* @throws ReflectionException
* @return void
* @noinspection PhpUnused
*/
public function postSaveTables(): void
{
$this->db->transStart();
$dinner_table_enable = $this->request->getPost('dinner_table_enable') != null;
$dinner_table_enable = $this->request->getPost('dinner_table_enable') !== null;
$this->appconfig->save(['dinner_table_enable' => $dinner_table_enable]);
if ($dinner_table_enable) {
$not_to_delete = [];
foreach ($this->request->getPost() as $key => $value) { // TODO: Not sure if this is the best way to filter the array
if (strstr($key, 'dinner_table') && $key != 'dinner_table_enable') {
$dinner_table_id = preg_replace("/.*?_(\d+)$/", "$1", $key);
if (strstr($key, 'dinner_table') && $key !== 'dinner_table_enable') {
$dinner_table_id = preg_replace('/.*?_(\\d+)$/', '$1', $key);
$not_to_delete[] = $dinner_table_id;
// Save or update
@@ -749,7 +722,7 @@ class Config extends Secure_Controller
$deleted_tables = $this->dinner_table->get_all()->getResultArray();
foreach ($deleted_tables as $dinner_tables => $table) {
if (!in_array($table['dinner_table_id'], $not_to_delete)) {
if (! in_array($table['dinner_table_id'], $not_to_delete, true)) {
$this->dinner_table->delete($table['dinner_table_id']);
}
}
@@ -766,7 +739,6 @@ class Config extends Secure_Controller
* Saves tax configuration. Used in app/Views/configs/tax_config.php
*
* @throws ReflectionException
* @return void
* @noinspection PhpUnused
*/
public function postSaveTax(): void
@@ -779,12 +751,12 @@ class Config extends Secure_Controller
'default_tax_1_name' => $this->request->getPost('default_tax_1_name'),
'default_tax_2_rate' => parse_tax(filter_var($default_tax_2_rate, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION)),
'default_tax_2_name' => $this->request->getPost('default_tax_2_name'),
'tax_included' => $this->request->getPost('tax_included') != null,
'use_destination_based_tax' => $this->request->getPost('use_destination_based_tax') != null,
'tax_included' => $this->request->getPost('tax_included') !== null,
'use_destination_based_tax' => $this->request->getPost('use_destination_based_tax') !== null,
'default_tax_code' => $this->request->getPost('default_tax_code'),
'default_tax_category' => $this->request->getPost('default_tax_category'),
'default_tax_jurisdiction' => $this->request->getPost('default_tax_jurisdiction'),
'tax_id' => $this->request->getPost('tax_id', FILTER_SANITIZE_NUMBER_INT)
'tax_id' => $this->request->getPost('tax_id', FILTER_SANITIZE_NUMBER_INT),
];
$success = $this->appconfig->batch_save($batch_save_data);
@@ -798,32 +770,32 @@ class Config extends Secure_Controller
* Saves customer rewards configuration. Used in app/Views/configs/reward_config.php
*
* @throws ReflectionException
* @return void
* @noinspection PhpUnused
*/
public function postSaveRewards(): void
{
$this->db->transStart();
$customer_reward_enable = $this->request->getPost('customer_reward_enable') != null;
$customer_reward_enable = $this->request->getPost('customer_reward_enable') !== null;
$this->appconfig->save(['customer_reward_enable' => $customer_reward_enable]);
if ($customer_reward_enable) {
$not_to_delete = [];
$array_save = [];
$array_save = [];
foreach ($this->request->getPost() as $key => $value) {
if (strstr($key, 'customer_reward') && $key != 'customer_reward_enable') {
$customer_reward_id = preg_replace("/.*?_(\d+)$/", "$1", $key);
$not_to_delete[] = $customer_reward_id;
if (strstr($key, 'customer_reward') && $key !== 'customer_reward_enable') {
$customer_reward_id = preg_replace('/.*?_(\\d+)$/', '$1', $key);
$not_to_delete[] = $customer_reward_id;
$array_save[$customer_reward_id]['package_name'] = $value;
} elseif (str_contains($key, 'reward_points')) {
$customer_reward_id = preg_replace("/.*?_(\d+)$/", "$1", $key);
$customer_reward_id = preg_replace('/.*?_(\\d+)$/', '$1', $key);
$array_save[$customer_reward_id]['points_percent'] = $value;
}
}
if (!empty($array_save)) {
if (! empty($array_save)) {
foreach ($array_save as $key => $value) {
// Save or update
$package_data = ['package_name' => $value['package_name'], 'points_percent' => $value['points_percent']];
@@ -835,7 +807,7 @@ class Config extends Secure_Controller
$deleted_packages = $this->customer_rewards->get_all()->getResultArray();
foreach ($deleted_packages as $customer_rewards => $reward_category) {
if (!in_array($reward_category['package_id'], $not_to_delete)) {
if (! in_array($reward_category['package_id'], $not_to_delete, true)) {
$this->customer_rewards->delete($reward_category['package_id']);
}
}
@@ -852,7 +824,6 @@ class Config extends Secure_Controller
* Saves barcode configuration. Used in app/Views/configs/barcode_config.php
*
* @throws ReflectionException
* @return void
* @noinspection PhpUnused
*/
public function postSaveBarcode(): void
@@ -869,10 +840,10 @@ class Config extends Secure_Controller
'barcode_num_in_row' => $this->request->getPost('barcode_num_in_row', FILTER_SANITIZE_NUMBER_INT),
'barcode_page_width' => $this->request->getPost('barcode_page_width', FILTER_SANITIZE_NUMBER_INT),
'barcode_page_cellspacing' => $this->request->getPost('barcode_page_cellspacing', FILTER_SANITIZE_NUMBER_INT),
'barcode_generate_if_empty' => $this->request->getPost('barcode_generate_if_empty') != null,
'allow_duplicate_barcodes' => $this->request->getPost('allow_duplicate_barcodes') != null,
'barcode_generate_if_empty' => $this->request->getPost('barcode_generate_if_empty') !== null,
'allow_duplicate_barcodes' => $this->request->getPost('allow_duplicate_barcodes') !== null,
'barcode_content' => $this->request->getPost('barcode_content'),
'barcode_formats' => json_encode($this->request->getPost('barcode_formats'))
'barcode_formats' => json_encode($this->request->getPost('barcode_formats')),
];
$success = $this->appconfig->batch_save($batch_save_data);
@@ -884,7 +855,6 @@ class Config extends Secure_Controller
* Saves receipt configuration. Used in app/Views/configs/receipt_config.php.
*
* @throws ReflectionException
* @return void
* @noinspection PhpUnused
*/
public function postSaveReceipt(): void
@@ -895,19 +865,19 @@ class Config extends Secure_Controller
'print_delay_autoreturn' => $this->request->getPost('print_delay_autoreturn', FILTER_SANITIZE_NUMBER_INT),
'email_receipt_check_behaviour' => $this->request->getPost('email_receipt_check_behaviour'),
'print_receipt_check_behaviour' => $this->request->getPost('print_receipt_check_behaviour'),
'receipt_show_company_name' => $this->request->getPost('receipt_show_company_name') != null,
'receipt_show_taxes' => $this->request->getPost('receipt_show_taxes') != null,
'receipt_show_tax_ind' => $this->request->getPost('receipt_show_tax_ind') != null,
'receipt_show_total_discount' => $this->request->getPost('receipt_show_total_discount') != null,
'receipt_show_description' => $this->request->getPost('receipt_show_description') != null,
'receipt_show_serialnumber' => $this->request->getPost('receipt_show_serialnumber') != null,
'print_silently' => $this->request->getPost('print_silently') != null,
'print_header' => $this->request->getPost('print_header') != null,
'print_footer' => $this->request->getPost('print_footer') != null,
'receipt_show_company_name' => $this->request->getPost('receipt_show_company_name') !== null,
'receipt_show_taxes' => $this->request->getPost('receipt_show_taxes') !== null,
'receipt_show_tax_ind' => $this->request->getPost('receipt_show_tax_ind') !== null,
'receipt_show_total_discount' => $this->request->getPost('receipt_show_total_discount') !== null,
'receipt_show_description' => $this->request->getPost('receipt_show_description') !== null,
'receipt_show_serialnumber' => $this->request->getPost('receipt_show_serialnumber') !== null,
'print_silently' => $this->request->getPost('print_silently') !== null,
'print_header' => $this->request->getPost('print_header') !== null,
'print_footer' => $this->request->getPost('print_footer') !== null,
'print_top_margin' => $this->request->getPost('print_top_margin', FILTER_SANITIZE_NUMBER_INT),
'print_left_margin' => $this->request->getPost('print_left_margin', FILTER_SANITIZE_NUMBER_INT),
'print_bottom_margin' => $this->request->getPost('print_bottom_margin', FILTER_SANITIZE_NUMBER_INT),
'print_right_margin' => $this->request->getPost('print_right_margin', FILTER_SANITIZE_NUMBER_INT)
'print_right_margin' => $this->request->getPost('print_right_margin', FILTER_SANITIZE_NUMBER_INT),
];
$success = $this->appconfig->batch_save($batch_save_data);
@@ -919,13 +889,12 @@ class Config extends Secure_Controller
* Saves invoice configuration. Used in app/Views/configs/invoice_config.php.
*
* @throws ReflectionException
* @return void
* @noinspection PhpUnused
*/
public function postSaveInvoice(): void
{
$batch_save_data = [
'invoice_enable' => $this->request->getPost('invoice_enable') != null,
'invoice_enable' => $this->request->getPost('invoice_enable') !== null,
'sales_invoice_format' => $this->request->getPost('sales_invoice_format'),
'sales_quote_format' => $this->request->getPost('sales_quote_format'),
'recv_invoice_format' => $this->request->getPost('recv_invoice_format'),
@@ -935,10 +904,10 @@ class Config extends Secure_Controller
'last_used_invoice_number' => $this->request->getPost('last_used_invoice_number', FILTER_SANITIZE_NUMBER_INT),
'last_used_quote_number' => $this->request->getPost('last_used_quote_number', FILTER_SANITIZE_NUMBER_INT),
'quote_default_comments' => $this->request->getPost('quote_default_comments'),
'work_order_enable' => $this->request->getPost('work_order_enable') != null,
'work_order_enable' => $this->request->getPost('work_order_enable') !== null,
'work_order_format' => $this->request->getPost('work_order_format'),
'last_used_work_order_number' => $this->request->getPost('last_used_work_order_number', FILTER_SANITIZE_NUMBER_INT),
'invoice_type' => $this->request->getPost('invoice_type')
'invoice_type' => $this->request->getPost('invoice_type'),
];
$success = $this->appconfig->batch_save($batch_save_data);
@@ -959,7 +928,6 @@ class Config extends Secure_Controller
/**
* Removes the company logo from the database. Used in app/Views/configs/info_config.php.
*
* @return void
* @throws ReflectionException
* @noinspection PhpUnused
*/

View File

@@ -3,7 +3,6 @@
namespace App\Controllers;
use App\Libraries\Mailchimp_lib;
use App\Models\Customer;
use App\Models\Customer_rewards;
use App\Models\Tax_code;
@@ -24,24 +23,21 @@ class Customers extends Persons
public function __construct()
{
parent::__construct('customers');
$this->mailchimp_lib = new Mailchimp_lib();
$this->mailchimp_lib = new Mailchimp_lib();
$this->customer_rewards = model(Customer_rewards::class);
$this->customer = model(Customer::class);
$this->tax_code = model(Tax_code::class);
$this->config = config(OSPOS::class)->settings;
$this->customer = model(Customer::class);
$this->tax_code = model(Tax_code::class);
$this->config = config(OSPOS::class)->settings;
$encrypter = Services::encrypter();
if (!empty($this->config['mailchimp_list_id'])) {
if (! empty($this->config['mailchimp_list_id'])) {
$this->_list_id = $encrypter->decrypt($this->config['mailchimp_list_id']);
} else {
$this->_list_id = '';
}
}
/**
* @return void
*/
public function getIndex(): void
{
$data['table_headers'] = get_customer_manage_table_headers();
@@ -61,13 +57,13 @@ class Customers extends Persons
if (empty($stats)) {
// Create object with empty properties.
$stats = new stdClass();
$stats->total = 0;
$stats->min = 0;
$stats->max = 0;
$stats->average = 0;
$stats = new stdClass();
$stats->total = 0;
$stats->min = 0;
$stats->max = 0;
$stats->average = 0;
$stats->avg_discount = 0;
$stats->quantity = 0;
$stats->quantity = 0;
}
$data_row = get_customer_data_row($person, $stats);
@@ -75,21 +71,18 @@ class Customers extends Persons
echo json_encode($data_row);
}
/**
* Returns customer table data rows. This will be called with AJAX.
*
* @return void
*/
public function getSearch(): void
{
$search = $this->request->getGet('search');
$limit = $this->request->getGet('limit', FILTER_SANITIZE_NUMBER_INT);
$limit = $this->request->getGet('limit', FILTER_SANITIZE_NUMBER_INT);
$offset = $this->request->getGet('offset', FILTER_SANITIZE_NUMBER_INT);
$sort = $this->sanitizeSortColumn(customer_headers(), $this->request->getGet('sort', FILTER_SANITIZE_FULL_SPECIAL_CHARS), 'people.person_id');
$order = $this->request->getGet('order', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$sort = $this->sanitizeSortColumn(customer_headers(), $this->request->getGet('sort', FILTER_SANITIZE_FULL_SPECIAL_CHARS), 'people.person_id');
$order = $this->request->getGet('order', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$customers = $this->customer->search($search, $limit, $offset, $sort, $order);
$customers = $this->customer->search($search, $limit, $offset, $sort, $order);
$total_rows = $this->customer->get_found_rows($search);
$data_rows = [];
@@ -99,13 +92,13 @@ class Customers extends Persons
$stats = $this->customer->get_stats($person->person_id); // TODO: duplicated... see above
if (empty($stats)) {
// Create object with empty properties.
$stats = new stdClass();
$stats->total = 0;
$stats->min = 0;
$stats->max = 0;
$stats->average = 0;
$stats = new stdClass();
$stats->total = 0;
$stats->min = 0;
$stats->max = 0;
$stats->average = 0;
$stats->avg_discount = 0;
$stats->quantity = 0;
$stats->quantity = 0;
}
$data_rows[] = get_customer_data_row($person, $stats);
@@ -119,18 +112,15 @@ class Customers extends Persons
*/
public function getSuggest(): void
{
$search = $this->request->getGet('term');
$search = $this->request->getGet('term');
$suggestions = $this->customer->get_search_suggestions($search);
echo json_encode($suggestions);
}
/**
* @return void
*/
public function suggest_search(): void
{
$search = $this->request->getGet('term');
$search = $this->request->getGet('term');
$suggestions = $this->customer->get_search_suggestions($search, 25, false);
echo json_encode($suggestions);
@@ -142,50 +132,54 @@ class Customers extends Persons
public function getView(int $customer_id = NEW_ENTRY): void
{
// Set default values
if ($customer_id == null) $customer_id = NEW_ENTRY;
if ($customer_id === null) {
$customer_id = NEW_ENTRY;
}
$info = $this->customer->get_info($customer_id);
foreach (get_object_vars($info) as $property => $value) {
$info->$property = $value;
$info->{$property} = $value;
}
$data['person_info'] = $info;
if (empty($info->person_id) || empty($info->date) || empty($info->employee_id)) {
$data['person_info']->date = date('Y-m-d H:i:s');
$data['person_info']->date = date('Y-m-d H:i:s');
$data['person_info']->employee_id = $this->employee->get_logged_in_employee_info()->person_id;
}
$employee_info = $this->employee->get_info($info->employee_id);
$employee_info = $this->employee->get_info($info->employee_id);
$data['employee'] = $employee_info->first_name . ' ' . $employee_info->last_name;
$tax_code_info = $this->tax_code->get_info($info->sales_tax_code_id);
if ($tax_code_info->tax_code != null) {
if ($tax_code_info->tax_code !== null) {
$data['sales_tax_code_label'] = $tax_code_info->tax_code . ' ' . $tax_code_info->tax_code_name;
} else {
$data['sales_tax_code_label'] = '';
}
$packages = ['' => lang('Items.none')];
foreach ($this->customer_rewards->get_all()->getResultArray() as $row) {
$packages[$row['package_id']] = $row['package_name'];
}
$data['packages'] = $packages;
$data['packages'] = $packages;
$data['selected_package'] = $info->package_id;
$data['use_destination_based_tax'] = $this->config['use_destination_based_tax'];
// Retrieve the total amount the customer spent so far together with min, max and average values
$stats = $this->customer->get_stats($customer_id);
if (!empty($stats)) {
if (! empty($stats)) {
foreach (get_object_vars($stats) as $property => $value) {
$info->$property = $value;
$info->{$property} = $value;
}
$data['stats'] = $stats;
}
// Retrieve the info from Mailchimp only if there is an email address assigned
if (!empty($info->email)) {
if (! empty($info->email)) {
// Collect Mailchimp customer info
if (($mailchimp_info = $this->mailchimp_lib->getMemberInfo($this->_list_id, $info->email)) !== false) {
$data['mailchimp_info'] = $mailchimp_info;
@@ -193,41 +187,41 @@ class Customers extends Persons
// Collect customer Mailchimp emails activities (stats)
if (($activities = $this->mailchimp_lib->getMemberActivity($this->_list_id, $info->email)) !== false) {
if (array_key_exists('activity', $activities)) {
$open = 0;
$unopen = 0;
$click = 0;
$total = 0;
$open = 0;
$unopen = 0;
$click = 0;
$total = 0;
$lastopen = '';
foreach ($activities['activity'] as $activity) {
if ($activity['action'] == 'sent') {
++$unopen;
} elseif ($activity['action'] == 'open') {
if ($activity['action'] === 'sent') {
$unopen++;
} elseif ($activity['action'] === 'open') {
if (empty($lastopen)) {
$lastopen = substr($activity['timestamp'], 0, 10);
}
++$open;
} elseif ($activity['action'] == 'click') {
$open++;
} elseif ($activity['action'] === 'click') {
if (empty($lastopen)) {
$lastopen = substr($activity['timestamp'], 0, 10);
}
++$click;
$click++;
}
++$total;
$total++;
}
$data['mailchimp_activity']['total'] = $total;
$data['mailchimp_activity']['open'] = $open;
$data['mailchimp_activity']['unopen'] = $unopen;
$data['mailchimp_activity']['click'] = $click;
$data['mailchimp_activity']['total'] = $total;
$data['mailchimp_activity']['open'] = $open;
$data['mailchimp_activity']['unopen'] = $unopen;
$data['mailchimp_activity']['click'] = $click;
$data['mailchimp_activity']['lastopen'] = $lastopen;
}
}
}
}
echo view("customers/form", $data);
echo view('customers/form', $data);
}
/**
@@ -236,12 +230,12 @@ class Customers extends Persons
public function postSave(int $customer_id = NEW_ENTRY): void
{
$first_name = $this->request->getPost('first_name');
$last_name = $this->request->getPost('last_name');
$email = strtolower($this->request->getPost('email', FILTER_SANITIZE_EMAIL));
$last_name = $this->request->getPost('last_name');
$email = strtolower($this->request->getPost('email', FILTER_SANITIZE_EMAIL));
// Format first and last name properly
$first_name = $this->nameize($first_name);
$last_name = $this->nameize($last_name);
$last_name = $this->nameize($last_name);
$person_data = [
'first_name' => $first_name,
@@ -255,23 +249,23 @@ class Customers extends Persons
'state' => $this->request->getPost('state'),
'zip' => $this->request->getPost('zip'),
'country' => $this->request->getPost('country'),
'comments' => $this->request->getPost('comments')
'comments' => $this->request->getPost('comments'),
];
$date_formatter = date_create_from_format($this->config['dateformat'] . ' ' . $this->config['timeformat'], $this->request->getPost('date'));
$customer_data = [
'consent' => $this->request->getPost('consent') != null,
'account_number' => $this->request->getPost('account_number') == '' ? null : $this->request->getPost('account_number'),
'consent' => $this->request->getPost('consent') !== null,
'account_number' => $this->request->getPost('account_number') === '' ? null : $this->request->getPost('account_number'),
'tax_id' => $this->request->getPost('tax_id'),
'company_name' => $this->request->getPost('company_name') == '' ? null : $this->request->getPost('company_name'),
'discount' => $this->request->getPost('discount') == '' ? 0.00 : parse_decimals($this->request->getPost('discount')),
'discount_type' => $this->request->getPost('discount_type') == null ? PERCENT : $this->request->getPost('discount_type', FILTER_SANITIZE_NUMBER_INT),
'package_id' => $this->request->getPost('package_id') == '' ? null : $this->request->getPost('package_id'),
'taxable' => $this->request->getPost('taxable') != null,
'company_name' => $this->request->getPost('company_name') === '' ? null : $this->request->getPost('company_name'),
'discount' => $this->request->getPost('discount') === '' ? 0.00 : parse_decimals($this->request->getPost('discount')),
'discount_type' => $this->request->getPost('discount_type') === null ? PERCENT : $this->request->getPost('discount_type', FILTER_SANITIZE_NUMBER_INT),
'package_id' => $this->request->getPost('package_id') === '' ? null : $this->request->getPost('package_id'),
'taxable' => $this->request->getPost('taxable') !== null,
'date' => $date_formatter->format('Y-m-d H:i:s'),
'employee_id' => $this->request->getPost('employee_id', FILTER_SANITIZE_NUMBER_INT),
'sales_tax_code_id' => $this->request->getPost('sales_tax_code_id') == '' ? null : $this->request->getPost('sales_tax_code_id', FILTER_SANITIZE_NUMBER_INT)
'sales_tax_code_id' => $this->request->getPost('sales_tax_code_id') === '' ? null : $this->request->getPost('sales_tax_code_id', FILTER_SANITIZE_NUMBER_INT),
];
if ($this->customer->save_customer($person_data, $customer_data, $customer_id)) {
@@ -282,29 +276,29 @@ class Customers extends Persons
$email,
$first_name,
$last_name,
$mailchimp_status == null ? "" : $mailchimp_status,
['vip' => $this->request->getPost('mailchimp_vip') != null]
$mailchimp_status === null ? '' : $mailchimp_status,
['vip' => $this->request->getPost('mailchimp_vip') !== null],
);
// New customer
if ($customer_id == NEW_ENTRY) {
if ($customer_id === NEW_ENTRY) {
echo json_encode([
'success' => true,
'message' => lang('Customers.successful_adding') . ' ' . $first_name . ' ' . $last_name,
'id' => $customer_data['person_id']
'id' => $customer_data['person_id'],
]);
} else { // Existing customer
echo json_encode([
'success' => true,
'message' => lang('Customers.successful_updating') . ' ' . $first_name . ' ' . $last_name,
'id' => $customer_id
'id' => $customer_id,
]);
}
} else { // Failure
echo json_encode([
'success' => false,
'message' => lang('Customers.error_adding_updating') . ' ' . $first_name . ' ' . $last_name,
'id' => NEW_ENTRY
'id' => NEW_ENTRY,
]);
}
}
@@ -312,30 +306,28 @@ class Customers extends Persons
/**
* Verifies if an email address already exists. Used in app/Views/customers/form.php
*
* @return void
* @noinspection PhpUnused
*/
public function postCheckEmail(): void
{
$email = strtolower($this->request->getPost('email', FILTER_SANITIZE_EMAIL));
$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';
echo ! $exists ? 'true' : 'false';
}
/**
* Verifies if an account number already exists. Used in app/Views/customers/form.php
*
* @return void
* @noinspection PhpUnused
*/
public function postCheckAccountNumber(): void
{
$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';
echo ! $exists ? 'true' : 'false';
}
/**
@@ -344,7 +336,7 @@ class Customers extends Persons
public function postDelete(): void
{
$customers_to_delete = $this->request->getPost('ids');
$customers_info = $this->customer->get_multiple_info($customers_to_delete);
$customers_info = $this->customer->get_multiple_info($customers_to_delete);
$count = 0;
@@ -357,10 +349,10 @@ class Customers extends Persons
}
}
if ($count == count($customers_to_delete)) {
if ($count === count($customers_to_delete)) {
echo json_encode([
'success' => true,
'message' => lang('Customers.successful_deleted') . ' ' . $count . ' ' . lang('Customers.one_or_multiple')
'message' => lang('Customers.successful_deleted') . ' ' . $count . ' ' . lang('Customers.one_or_multiple'),
]);
} else {
echo json_encode(['success' => false, 'message' => lang('Customers.cannot_be_deleted')]);
@@ -371,19 +363,20 @@ class Customers extends Persons
* Customers import from csv spreadsheet
*
* @return DownloadResponse The template for Customer CSV imports is returned and download forced.
*
* @noinspection PhpUnused
*/
public function getCsv(): DownloadResponse
{
$name = 'importCustomers.csv';
$data = file_get_contents(WRITEPATH . "uploads/$name");
$data = file_get_contents(WRITEPATH . "uploads/{$name}");
return $this->response->download($name, $data);
}
/**
* Displays the customer CSV import modal. Used in app/Views/people/manage.php
*
* @return void
* @noinspection PhpUnused
*/
public function getCsvImport(): void
@@ -394,15 +387,14 @@ class Customers extends Persons
/**
* Imports a CSV file containing customers. Used in app/Views/customers/form_csv_import.php
*
* @return void
* @noinspection PhpUnused
*/
public function postImportCsvFile(): void
{
if ($_FILES['file_path']['error'] != UPLOAD_ERR_OK) {
if ($_FILES['file_path']['error'] !== UPLOAD_ERR_OK) {
echo json_encode(['success' => false, 'message' => lang('Customers.csv_import_failed')]);
} else {
if (($handle = fopen($_FILES['file_path']['tmp_name'], 'r')) !== false) {
if (($handle = fopen($_FILES['file_path']['tmp_name'], 'rb')) !== false) {
// Skip the first row as it's the table description
fgetcsv($handle);
$i = 1;
@@ -410,10 +402,10 @@ class Customers extends Persons
$failCodes = [];
while (($data = fgetcsv($handle)) !== false) {
$consent = $data[3] == '' ? 0 : 1;
$consent = $data[3] === '' ? 0 : 1;
if (sizeof($data) >= 16 && $consent) {
$email = strtolower($data[4]);
if (count($data) >= 16 && $consent) {
$email = strtolower($data[4]);
$person_data = [
'first_name' => $data[0],
'last_name' => $data[1],
@@ -426,7 +418,7 @@ class Customers extends Persons
'state' => $data[9],
'zip' => $data[10],
'country' => $data[11],
'comments' => $data[12]
'comments' => $data[12],
];
$customer_data = [
@@ -434,16 +426,16 @@ class Customers extends Persons
'company_name' => $data[13],
'discount' => $data[15],
'discount_type' => $data[16],
'taxable' => $data[17] == '' ? 0 : 1,
'taxable' => $data[17] === '' ? 0 : 1,
'date' => date('Y-m-d H:i:s'),
'employee_id' => $this->employee->get_logged_in_employee_info()->person_id
'employee_id' => $this->employee->get_logged_in_employee_info()->person_id,
];
$account_number = $data[14];
// Don't duplicate people with same email
$invalidated = $this->customer->check_email_exists($email);
if ($account_number != '') {
if ($account_number !== '') {
$customer_data['account_number'] = $account_number;
$invalidated &= $this->customer->check_account_number_exists($account_number);
}
@@ -453,7 +445,7 @@ class Customers extends Persons
if ($invalidated) {
$failCodes[] = $i;
log_message('error', "Row $i was not imported: Either email or account number already exist or data was invalid.");
log_message('error', "Row {$i} was not imported: Either email or account number already exist or data was invalid.");
} elseif ($this->customer->save_customer($person_data, $customer_data)) {
// Save customer to Mailchimp selected list
$this->mailchimp_lib->addOrUpdateMember($this->_list_id, $person_data['email'], $person_data['first_name'], '', $person_data['last_name']);
@@ -461,7 +453,7 @@ class Customers extends Persons
$failCodes[] = $i;
}
++$i;
$i++;
}
if (count($failCodes) > 0) {

View File

@@ -3,13 +3,9 @@
namespace App\Controllers;
use App\Models\Module;
use Config\Services;
/**
*
*
* @property module module
*
* @property Module module
*/
class Employees extends Persons
{
@@ -22,8 +18,6 @@ class Employees extends Persons
/**
* Returns employee table data rows. This will be called with AJAX.
*
* @return void
*/
public function getSearch(): void
{
@@ -33,10 +27,11 @@ class Employees extends Persons
$sort = $this->sanitizeSortColumn(person_headers(), $this->request->getGet('sort', FILTER_SANITIZE_FULL_SPECIAL_CHARS), 'people.person_id');
$order = $this->request->getGet('order', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$employees = $this->employee->search($search, $limit, $offset, $sort, $order);
$employees = $this->employee->search($search, $limit, $offset, $sort, $order);
$total_rows = $this->employee->get_found_rows($search);
$data_rows = [];
foreach ($employees->getResult() as $person) {
$data_rows[] = get_person_data_row($person);
}
@@ -46,23 +41,18 @@ class Employees extends Persons
/**
* AJAX called function gives search suggestions based on what is being searched for.
*
* @return void
*/
public function getSuggest(): void
{
$search = $this->request->getGet('term');
$search = $this->request->getGet('term');
$suggestions = $this->employee->get_search_suggestions($search, 25, true);
echo json_encode($suggestions);
}
/**
* @return void
*/
public function suggest_search(): void
{
$search = $this->request->getPost('term');
$search = $this->request->getPost('term');
$suggestions = $this->employee->get_search_suggestions($search);
echo json_encode($suggestions);
@@ -74,15 +64,17 @@ class Employees extends Persons
public function getView(int $employee_id = NEW_ENTRY): void
{
$person_info = $this->employee->get_info($employee_id);
foreach (get_object_vars($person_info) as $property => $value) {
$person_info->$property = $value;
$person_info->{$property} = $value;
}
$data['person_info'] = $person_info;
$data['employee_id'] = $employee_id;
$modules = [];
foreach ($this->module->get_all_modules()->getResult() as $module) {
$module->grant = $this->employee->has_grant($module->module_id, $person_info->person_id);
$module->grant = $this->employee->has_grant($module->module_id, $person_info->person_id);
$module->menu_group = $this->employee->get_menu_group($module->module_id, $person_info->person_id);
$modules[] = $module;
@@ -90,9 +82,10 @@ class Employees extends Persons
$data['all_modules'] = $modules;
$permissions = [];
foreach ($this->module->get_all_subpermissions()->getResult() as $permission) { // TODO: subpermissions does not follow naming standards.
$permission->permission_id = str_replace(' ', '_', $permission->permission_id);
$permission->grant = $this->employee->has_grant($permission->permission_id, $person_info->person_id);
$permission->grant = $this->employee->has_grant($permission->permission_id, $person_info->person_id);
$permissions[] = $permission;
}
@@ -107,12 +100,12 @@ class Employees extends Persons
public function postSave(int $employee_id = NEW_ENTRY): void
{
$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);
$email = strtolower($this->request->getPost('email', FILTER_SANITIZE_EMAIL));
$last_name = $this->request->getPost('last_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$email = strtolower($this->request->getPost('email', FILTER_SANITIZE_EMAIL));
// format first and last name properly
$first_name = $this->nameize($first_name);
$last_name = $this->nameize($last_name);
$last_name = $this->nameize($last_name);
$person_data = [
'first_name' => $first_name,
@@ -126,60 +119,61 @@ class Employees extends Persons
'state' => $this->request->getPost('state', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
'zip' => $this->request->getPost('zip', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
'country' => $this->request->getPost('country', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
'comments' => $this->request->getPost('comments', FILTER_SANITIZE_FULL_SPECIAL_CHARS)
'comments' => $this->request->getPost('comments', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
];
$grants_array = [];
foreach ($this->module->get_all_permissions()->getResult() as $permission) {
$grants = [];
$grant = $this->request->getPost('grant_' . $permission->permission_id) != null ? $this->request->getPost('grant_' . $permission->permission_id, FILTER_SANITIZE_FULL_SPECIAL_CHARS) : '';
$grant = $this->request->getPost('grant_' . $permission->permission_id) !== null ? $this->request->getPost('grant_' . $permission->permission_id, FILTER_SANITIZE_FULL_SPECIAL_CHARS) : '';
if ($grant == $permission->permission_id) {
if ($grant === $permission->permission_id) {
$grants['permission_id'] = $permission->permission_id;
$grants['menu_group'] = $this->request->getPost('menu_group_' . $permission->permission_id) != null ? $this->request->getPost('menu_group_' . $permission->permission_id, FILTER_SANITIZE_FULL_SPECIAL_CHARS) : '--';
$grants_array[] = $grants;
$grants['menu_group'] = $this->request->getPost('menu_group_' . $permission->permission_id) !== null ? $this->request->getPost('menu_group_' . $permission->permission_id, FILTER_SANITIZE_FULL_SPECIAL_CHARS) : '--';
$grants_array[] = $grants;
}
}
// Password has been changed OR first time password set
if (!empty($this->request->getPost('password')) && ENVIRONMENT != 'testing') {
$exploded = explode(":", $this->request->getPost('language', FILTER_SANITIZE_FULL_SPECIAL_CHARS));
if (! empty($this->request->getPost('password')) && ENVIRONMENT !== 'testing') {
$exploded = explode(':', $this->request->getPost('language', FILTER_SANITIZE_FULL_SPECIAL_CHARS));
$employee_data = [
'username' => $this->request->getPost('username', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
'password' => password_hash($this->request->getPost('password'), PASSWORD_DEFAULT),
'hash_version' => 2,
'language_code' => $exploded[0],
'language' => $exploded[1]
'language' => $exploded[1],
];
} else { // Password not changed
$exploded = explode(":", $this->request->getPost('language', FILTER_SANITIZE_FULL_SPECIAL_CHARS));
$exploded = explode(':', $this->request->getPost('language', FILTER_SANITIZE_FULL_SPECIAL_CHARS));
$employee_data = [
'username' => $this->request->getPost('username', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
'language_code' => $exploded[0],
'language' => $exploded[1]
'language' => $exploded[1],
];
}
if ($this->employee->save_employee($person_data, $employee_data, $grants_array, $employee_id)) {
// New employee
if ($employee_id == NEW_ENTRY) {
if ($employee_id === NEW_ENTRY) {
echo json_encode([
'success' => true,
'message' => lang('Employees.successful_adding') . ' ' . $first_name . ' ' . $last_name,
'id' => $employee_data['person_id']
'id' => $employee_data['person_id'],
]);
} else { // Existing employee
echo json_encode([
'success' => true,
'message' => lang('Employees.successful_updating') . ' ' . $first_name . ' ' . $last_name,
'id' => $employee_id
'id' => $employee_id,
]);
}
} else { // Failure
echo json_encode([
'success' => false,
'message' => lang('Employees.error_adding_updating') . ' ' . $first_name . ' ' . $last_name,
'id' => NEW_ENTRY
'id' => NEW_ENTRY,
]);
}
}
@@ -194,7 +188,7 @@ class Employees extends Persons
if ($this->employee->delete_list($employees_to_delete)) { // TODO: this is passing a string, but delete_list expects an array
echo json_encode([
'success' => true,
'message' => lang('Employees.successful_deleted') . ' ' . count($employees_to_delete) . ' ' . lang('Employees.one_or_multiple')
'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')]);
@@ -204,13 +198,13 @@ class Employees extends Persons
/**
* Checks an employee username against the database. Used in app\Views\employees\form.php
*
* @param $employee_id
* @return void
* @noinspection PhpUnused
*
* @param mixed $employee_id
*/
public function getCheckUsername($employee_id): void
{
$exists = $this->employee->username_exists($employee_id, $this->request->getGet('username'));
echo !$exists ? 'true' : 'false';
echo ! $exists ? 'true' : 'false';
}
}

View File

@@ -5,7 +5,6 @@ namespace App\Controllers;
use App\Models\Expense;
use App\Models\Expense_category;
use Config\OSPOS;
use Config\Services;
class Expenses extends Secure_Controller
{
@@ -16,13 +15,10 @@ class Expenses extends Secure_Controller
{
parent::__construct('expenses');
$this->expense = model(Expense::class);
$this->expense = model(Expense::class);
$this->expense_category = model(Expense_category::class);
}
/**
* @return void
*/
public function getIndex(): void
{
$data['table_headers'] = get_expenses_manage_table_headers();
@@ -34,23 +30,20 @@ class Expenses extends Secure_Controller
'only_check' => lang('Expenses.check_filter'),
'only_credit' => lang('Expenses.credit_filter'),
'only_debit' => lang('Expenses.debit_filter'),
'is_deleted' => lang('Expenses.is_deleted')
'is_deleted' => lang('Expenses.is_deleted'),
];
echo view('expenses/manage', $data);
}
/**
* @return void
*/
public function getSearch(): void
{
$search = $this->request->getGet('search');
$limit = $this->request->getGet('limit', FILTER_SANITIZE_NUMBER_INT);
$offset = $this->request->getGet('offset', FILTER_SANITIZE_NUMBER_INT);
$sort = $this->sanitizeSortColumn(expense_headers(), $this->request->getGet('sort', FILTER_SANITIZE_FULL_SPECIAL_CHARS), 'expense_id');
$order = $this->request->getGet('order', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$filters = [
$search = $this->request->getGet('search');
$limit = $this->request->getGet('limit', FILTER_SANITIZE_NUMBER_INT);
$offset = $this->request->getGet('offset', FILTER_SANITIZE_NUMBER_INT);
$sort = $this->sanitizeSortColumn(expense_headers(), $this->request->getGet('sort', FILTER_SANITIZE_FULL_SPECIAL_CHARS), 'expense_id');
$order = $this->request->getGet('order', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$filters = [
'start_date' => $this->request->getGet('start_date', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
'end_date' => $this->request->getGet('end_date', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
'only_cash' => false,
@@ -58,17 +51,17 @@ class Expenses extends Secure_Controller
'only_check' => false,
'only_credit' => false,
'only_debit' => false,
'is_deleted' => false
'is_deleted' => false,
];
// Check if any filter is set in the multiselect dropdown
$request_filters = array_fill_keys($this->request->getGet('filters', FILTER_SANITIZE_FULL_SPECIAL_CHARS) ?? [], true);
$filters = array_merge($filters, $request_filters);
$expenses = $this->expense->search($search, $filters, $limit, $offset, $sort, $order);
$total_rows = $this->expense->get_found_rows($search, $filters);
$payments = $this->expense->get_payments_summary($search, $filters);
$filters = array_merge($filters, $request_filters);
$expenses = $this->expense->search($search, $filters, $limit, $offset, $sort, $order);
$total_rows = $this->expense->get_found_rows($search, $filters);
$payments = $this->expense->get_payments_summary($search, $filters);
$payment_summary = get_expenses_manage_payments_summary($payments, $expenses);
$data_rows = [];
$data_rows = [];
foreach ($expenses->getResult() as $expense) {
$data_rows[] = get_expenses_data_row($expense);
@@ -81,18 +74,15 @@ class Expenses extends Secure_Controller
echo json_encode(['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
{
$data = []; // TODO: Duplicated code
$data['employees'] = [];
foreach ($this->employee->get_all()->getResult() as $employee) {
foreach (get_object_vars($employee) as $property => $value) {
$employee->$property = $value;
$employee->{$property} = $value;
}
$data['employees'][$employee->person_id] = $employee->first_name . ' ' . $employee->last_name;
@@ -101,6 +91,7 @@ class Expenses extends Secure_Controller
$data['expenses_info'] = $this->expense->get_info($expense_id);
$expense_categories = [];
foreach ($this->expense_category->get_all(0, 0, true)->getResultArray() as $row) {
$expense_categories[$row['expense_category_id']] = $row['category_name'];
}
@@ -108,15 +99,16 @@ class Expenses extends Secure_Controller
$expense_id = $data['expenses_info']->expense_id;
if ($expense_id == NEW_ENTRY) {
$data['expenses_info']->date = date('Y-m-d H:i:s');
if ($expense_id === NEW_ENTRY) {
$data['expenses_info']->date = date('Y-m-d H:i:s');
$data['expenses_info']->employee_id = $this->employee->get_logged_in_employee_info()->person_id;
}
$data['payments'] = [];
foreach ($this->expense->get_expense_payment($expense_id)->getResult() as $payment) {
foreach (get_object_vars($payment) as $property => $value) {
$payment->$property = $value;
$payment->{$property} = $value;
}
$data['payments'][] = $payment;
@@ -125,35 +117,27 @@ 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);
echo view('expenses/form', $data);
}
/**
* @param int $row_id
* @return void
*/
public function getRow(int $row_id): void
{
$expense_info = $this->expense->get_info($row_id);
$data_row = get_expenses_data_row($expense_info);
$data_row = get_expenses_data_row($expense_info);
echo json_encode($data_row);
}
/**
* @param int $expense_id
* @return void
*/
public function postSave(int $expense_id = NEW_ENTRY): void
{
$config = config(OSPOS::class)->settings;
$config = config(OSPOS::class)->settings;
$newdate = $this->request->getPost('date', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$date_formatter = date_create_from_format($config['dateformat'] . ' ' . $config['timeformat'], $newdate);
$expense_data = [
'date' => $date_formatter->format('Y-m-d H:i:s'),
'supplier_id' => $this->request->getPost('supplier_id') == '' ? null : $this->request->getPost('supplier_id', FILTER_SANITIZE_NUMBER_INT),
'supplier_id' => $this->request->getPost('supplier_id') === '' ? null : $this->request->getPost('supplier_id', FILTER_SANITIZE_NUMBER_INT),
'supplier_tax_code' => $this->request->getPost('supplier_tax_code', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
'amount' => parse_decimals($this->request->getPost('amount')),
'tax_amount' => parse_decimals($this->request->getPost('tax_amount')),
@@ -161,12 +145,12 @@ class Expenses extends Secure_Controller
'expense_category_id' => $this->request->getPost('expense_category_id', FILTER_SANITIZE_NUMBER_INT),
'description' => $this->request->getPost('description', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
'employee_id' => $this->request->getPost('employee_id', FILTER_SANITIZE_NUMBER_INT),
'deleted' => $this->request->getPost('deleted') != null
'deleted' => $this->request->getPost('deleted') !== null,
];
if ($this->expense->save_value($expense_data, $expense_id)) {
// New Expense
if ($expense_id == NEW_ENTRY) {
if ($expense_id === NEW_ENTRY) {
echo json_encode(['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]);
@@ -176,9 +160,6 @@ class Expenses extends Secure_Controller
}
}
/**
* @return void
*/
public function postDelete(): void
{
$expenses_to_delete = $this->request->getPost('ids', FILTER_SANITIZE_FULL_SPECIAL_CHARS);

View File

@@ -3,7 +3,6 @@
namespace App\Controllers;
use App\Models\Expense_category;
use Config\Services;
class Expenses_categories extends Secure_Controller // TODO: Is this class ever used?
{
@@ -16,9 +15,6 @@ class Expenses_categories extends Secure_Controller // TODO: Is this class ev
$this->expense_category = model(Expense_category::class);
}
/**
* @return void
*/
public function getIndex(): void
{
$data['table_headers'] = get_expense_category_manage_table_headers();
@@ -28,7 +24,7 @@ class Expenses_categories extends Secure_Controller // TODO: Is this class ev
/**
* Returns expense_category_manage table data rows. This will be called with AJAX.
**/
*/
public function getSearch(): void
{
$search = $this->request->getGet('search');
@@ -38,9 +34,10 @@ class Expenses_categories extends Secure_Controller // TODO: Is this class ev
$order = $this->request->getGet('order', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$expense_categories = $this->expense_category->search($search, $limit, $offset, $sort, $order);
$total_rows = $this->expense_category->get_found_rows($search);
$total_rows = $this->expense_category->get_found_rows($search);
$data_rows = [];
foreach ($expense_categories->getResult() as $expense_category) {
$data_rows[] = get_expense_category_data_row($expense_category);
}
@@ -48,10 +45,6 @@ class Expenses_categories extends Secure_Controller // TODO: Is this class ev
echo json_encode(['total' => $total_rows, 'rows' => $data_rows]);
}
/**
* @param int $row_id
* @return void
*/
public function getRow(int $row_id): void
{
$data_row = get_expense_category_data_row($this->expense_category->get_info($row_id));
@@ -59,55 +52,44 @@ class Expenses_categories extends Secure_Controller // TODO: Is this class ev
echo json_encode($data_row);
}
/**
* @param int $expense_category_id
* @return void
*/
public function getView(int $expense_category_id = NEW_ENTRY): void
{
$data['category_info'] = $this->expense_category->get_info($expense_category_id);
echo view("expenses_categories/form", $data);
echo view('expenses_categories/form', $data);
}
/**
* @param int $expense_category_id
* @return void
*/
public function postSave(int $expense_category_id = NEW_ENTRY): void
{
$expense_category_data = [
'category_name' => $this->request->getPost('category_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
'category_description' => $this->request->getPost('category_description', FILTER_SANITIZE_FULL_SPECIAL_CHARS)
'category_description' => $this->request->getPost('category_description', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
];
if ($this->expense_category->save_value($expense_category_data, $expense_category_id)) {
// New expense_category
if ($expense_category_id == NEW_ENTRY) {
if ($expense_category_id === NEW_ENTRY) {
echo json_encode([
'success' => true,
'message' => lang('Expenses_categories.successful_adding'),
'id' => $expense_category_data['expense_category_id']
'id' => $expense_category_data['expense_category_id'],
]);
} else { // Existing Expense Category
echo json_encode([
'success' => true,
'message' => lang('Expenses_categories.successful_updating'),
'id' => $expense_category_id
'id' => $expense_category_id,
]);
}
} else { // Failure
echo json_encode([
'success' => true,
'message' => lang('Expenses_categories.error_adding_updating') . ' ' . $expense_category_data['category_name'],
'id' => NEW_ENTRY
'id' => NEW_ENTRY,
]);
}
}
/**
* @return void
*/
public function postDelete(): void
{
$expense_category_to_delete = $this->request->getPost('ids', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
@@ -115,7 +97,7 @@ class Expenses_categories extends Secure_Controller // TODO: Is this class ev
if ($this->expense_category->delete_list($expense_category_to_delete)) { // TODO: Convert to ternary notation.
echo json_encode([
'success' => true,
'message' => lang('Expenses_categories.successful_deleted') . ' ' . count($expense_category_to_delete) . ' ' . lang('Expenses_categories.one_or_multiple')
'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')]);

View File

@@ -4,7 +4,6 @@ namespace App\Controllers;
use App\Models\Giftcard;
use Config\OSPOS;
use Config\Services;
class Giftcards extends Secure_Controller
{
@@ -17,9 +16,6 @@ class Giftcards extends Secure_Controller
$this->giftcard = model(Giftcard::class);
}
/**
* @return void
*/
public function getIndex(): void
{
$data['table_headers'] = get_giftcards_manage_table_headers();
@@ -38,10 +34,11 @@ class Giftcards extends Secure_Controller
$sort = $this->sanitizeSortColumn(giftcard_headers(), $this->request->getGet('sort', FILTER_SANITIZE_FULL_SPECIAL_CHARS), 'giftcard_id');
$order = $this->request->getGet('order', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$giftcards = $this->giftcard->search($search, $limit, $offset, $sort, $order);
$giftcards = $this->giftcard->search($search, $limit, $offset, $sort, $order);
$total_rows = $this->giftcard->get_found_rows($search);
$data_rows = [];
foreach ($giftcards->getResult() as $giftcard) {
$data_rows[] = get_giftcard_data_row($giftcard);
}
@@ -52,32 +49,24 @@ class Giftcards extends Secure_Controller
/**
* Gets search suggestions for giftcards. Used in app\Views\sales\register.php
*
* @return void
* @noinspection PhpUnused
*/
public function getSuggest(): void
{
$search = $this->request->getGet('term');
$search = $this->request->getGet('term');
$suggestions = $this->giftcard->get_search_suggestions($search, true);
echo json_encode($suggestions);
}
/**
* @return void
*/
public function suggest_search(): void
{
$search = $this->request->getPost('term');
$search = $this->request->getPost('term');
$suggestions = $this->giftcard->get_search_suggestions($search);
echo json_encode($suggestions);
}
/**
* @param int $row_id
* @return void
*/
public function getRow(int $row_id): void
{
$data_row = get_giftcard_data_row($this->giftcard->get_info($row_id));
@@ -85,39 +74,31 @@ class Giftcards extends Secure_Controller
echo json_encode($data_row);
}
/**
* @param int $giftcard_id
* @return void
*/
public function getView(int $giftcard_id = NEW_ENTRY): void
{
$config = config(OSPOS::class)->settings;
$config = config(OSPOS::class)->settings;
$giftcard_info = $this->giftcard->get_info($giftcard_id);
$data['selected_person_name'] = ($giftcard_id > 0 && isset($giftcard_info->person_id)) ? $giftcard_info->first_name . ' ' . $giftcard_info->last_name : '';
$data['selected_person_id'] = $giftcard_info->person_id;
if ($config['giftcard_number'] == 'random') {
$data['selected_person_id'] = $giftcard_info->person_id;
if ($config['giftcard_number'] === 'random') {
$data['giftcard_number'] = $giftcard_id > 0 ? $giftcard_info->giftcard_number : '';
} else {
$max_number_obj = $this->giftcard->get_max_number();
$max_giftnumber = isset($max_number_obj) ? $this->giftcard->get_max_number()->giftcard_number : 0; // TODO: variable does not follow naming standard.
$max_number_obj = $this->giftcard->get_max_number();
$max_giftnumber = isset($max_number_obj) ? $this->giftcard->get_max_number()->giftcard_number : 0; // TODO: variable does not follow naming standard.
$data['giftcard_number'] = $giftcard_id > 0 ? $giftcard_info->giftcard_number : $max_giftnumber + 1;
}
$data['giftcard_id'] = $giftcard_id;
$data['giftcard_id'] = $giftcard_id;
$data['giftcard_value'] = $giftcard_info->value;
echo view("giftcards/form", $data);
echo view('giftcards/form', $data);
}
/**
* @param int $giftcard_id
* @return void
*/
public function postSave(int $giftcard_id = NEW_ENTRY): void
{
$giftcard_number = $this->request->getPost('giftcard_number', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
if ($giftcard_id == NEW_ENTRY && trim($giftcard_number) == '') {
if ($giftcard_id === NEW_ENTRY && trim($giftcard_number) === '') {
$giftcard_number = $this->giftcard->generate_unique_giftcard_name($giftcard_number);
}
@@ -125,29 +106,29 @@ class Giftcards extends Secure_Controller
'record_time' => date('Y-m-d H:i:s'),
'giftcard_number' => $giftcard_number,
'value' => parse_decimals($this->request->getPost('giftcard_amount')),
'person_id' => empty($this->request->getPost('person_id')) ? null : $this->request->getPost('person_id', FILTER_SANITIZE_NUMBER_INT)
'person_id' => $this->request->getPost('person_id') === '' ? null : $this->request->getPost('person_id', FILTER_SANITIZE_NUMBER_INT),
];
if ($this->giftcard->save_value($giftcard_data, $giftcard_id)) {
// New giftcard
if ($giftcard_id == NEW_ENTRY) { // TODO: Constant needed
if ($giftcard_id === NEW_ENTRY) { // TODO: Constant needed
echo json_encode([
'success' => true,
'message' => lang('Giftcards.successful_adding') . ' ' . $giftcard_data['giftcard_number'],
'id' => $giftcard_data['giftcard_id']
'id' => $giftcard_data['giftcard_id'],
]);
} else { // Existing giftcard
echo json_encode([
'success' => true,
'message' => lang('Giftcards.successful_updating') . ' ' . $giftcard_data['giftcard_number'],
'id' => $giftcard_id
'id' => $giftcard_id,
]);
}
} else { // Failure
echo json_encode([
'success' => false,
'message' => lang('Giftcards.error_adding_updating') . ' ' . $giftcard_data['giftcard_number'],
'id' => NEW_ENTRY
'id' => NEW_ENTRY,
]);
}
}
@@ -155,22 +136,15 @@ class Giftcards extends Secure_Controller
/**
* Checks the giftcard number validity. Used in app\Views\giftcards\form.php
*
* @return void
* @noinspection PhpUnused
*/
public function postCheckNumberGiftcard(): void
{
$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';
$giftcard_amount = parse_decimals($this->request->getPost('giftcard_amount'));
$parsed_value = filter_var($giftcard_amount, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
echo json_encode(['success' => $parsed_value !== false && $parsed_value > 0 && $giftcard_amount !== false, 'giftcard_amount' => to_currency_no_money($parsed_value)]);
}
/**
* @return void
*/
public function postDelete(): void
{
$giftcards_to_delete = $this->request->getPost('ids', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
@@ -178,7 +152,7 @@ class Giftcards extends Secure_Controller
if ($this->giftcard->delete_list($giftcards_to_delete)) {
echo json_encode([
'success' => true,
'message' => lang('Giftcards.successful_deleted') . ' ' . count($giftcards_to_delete) . ' ' . lang('Giftcards.one_or_multiple')
'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')]);

View File

@@ -11,9 +11,6 @@ class Home extends Secure_Controller
parent::__construct('home', null, 'home');
}
/**
* @return void
*/
public function getIndex(): void
{
$logged_in = $this->employee->is_logged_in();
@@ -23,12 +20,12 @@ class Home extends Secure_Controller
/**
* Logs the currently logged in employee out of the system. Used in app/Views/partial/header.php
*
* @return RedirectResponse
* @noinspection PhpUnused
*/
public function getLogout(): RedirectResponse
{
$this->employee->logout();
return redirect()->to('login');
}
@@ -40,8 +37,9 @@ class Home extends Secure_Controller
public function getChangePassword(int $employee_id = -1): void // TODO: Replace -1 with a constant
{
$person_info = $this->employee->get_info($employee_id);
foreach (get_object_vars($person_info) as $property => $value) {
$person_info->$property = $value;
$person_info->{$property} = $value;
}
$data['person_info'] = $person_info;
@@ -53,39 +51,39 @@ class Home extends Secure_Controller
*/
public function postSave(int $employee_id = -1): void // TODO: Replace -1 with a constant
{
if (!empty($this->request->getPost('current_password')) && $employee_id != -1) {
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'))) {
$employee_data = [
'username' => $this->request->getPost('username', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
'password' => password_hash($this->request->getPost('password'), PASSWORD_DEFAULT),
'hash_version' => 2
'hash_version' => 2,
];
if ($this->employee->change_password($employee_data, $employee_id) && strlen($employee_data['password']) >= 8) {
if ($this->employee->change_password($employee_data, $employee_id)) {
echo json_encode([
'success' => true,
'message' => lang('Employees.successful_change_password'),
'id' => $employee_id
'id' => $employee_id,
]);
} else { // Failure // TODO: Replace -1 with constant
echo json_encode([
'success' => false,
'message' => lang('Employees.unsuccessful_change_password'),
'id' => -1
'id' => -1,
]);
}
} else { // TODO: Replace -1 with constant
echo json_encode([
'success' => false,
'message' => lang('Employees.current_password_invalid'),
'id' => -1
'id' => -1,
]);
}
} else { // TODO: Replace -1 with constant
echo json_encode([
'success' => false,
'message' => lang('Employees.current_password_invalid'),
'id' => -1
'id' => -1,
]);
}
}

View File

@@ -3,11 +3,9 @@
namespace App\Controllers;
use App\Libraries\Barcode_lib;
use App\Models\Item;
use App\Models\Item_kit;
use App\Models\Item_kit_items;
use Config\Services;
class Item_kits extends Secure_Controller
{
@@ -19,8 +17,8 @@ class Item_kits extends Secure_Controller
{
parent::__construct('item_kits');
$this->item = model(Item::class);
$this->item_kit = model(Item_kit::class);
$this->item = model(Item::class);
$this->item_kit = model(Item_kit::class);
$this->item_kit_items = model(Item_kit_items::class);
}
@@ -33,17 +31,18 @@ class Item_kits extends Secure_Controller
$item_kit->total_cost_price = 0;
$item_kit->total_unit_price = $kit_item_info->unit_price;
$total_quantity = 0;
$total_quantity = 0;
foreach ($this->item_kit_items->get_info($item_kit->item_kit_id) as $item_kit_item) {
$item_info = $this->item->get_info($item_kit_item['item_id']);
foreach (get_object_vars($item_info) as $property => $value) {
$item_info->$property = $value;
$item_info->{$property} = $value;
}
$item_kit->total_cost_price += $item_info->cost_price * $item_kit_item['quantity'];
if ($item_kit->price_option == PRICE_OPTION_ALL || ($item_kit->price_option == PRICE_OPTION_KIT_STOCK && $item_info->stock_type == HAS_STOCK)) {
if ($item_kit->price_option === PRICE_OPTION_ALL || ($item_kit->price_option === PRICE_OPTION_KIT_STOCK && $item_info->stock_type === HAS_STOCK)) {
$item_kit->total_unit_price += $item_info->unit_price * $item_kit_item['quantity'];
$total_quantity += $item_kit_item['quantity'];
}
@@ -51,16 +50,13 @@ class Item_kits extends Secure_Controller
$discount_fraction = bcdiv($item_kit->kit_discount, '100');
$item_kit->total_unit_price = $item_kit->total_unit_price - round(($item_kit->kit_discount_type == PERCENT)
$item_kit->total_unit_price -= round(($item_kit->kit_discount_type === PERCENT)
? bcmul($item_kit->total_unit_price, $discount_fraction)
: $item_kit->kit_discount, totals_decimals(), PHP_ROUND_HALF_UP);
return $item_kit;
}
/**
* @return void
*/
public function getIndex(): void
{
$data['table_headers'] = get_item_kits_manage_table_headers();
@@ -79,34 +75,28 @@ class Item_kits extends Secure_Controller
$sort = $this->sanitizeSortColumn(item_kit_headers(), $this->request->getGet('sort', FILTER_SANITIZE_FULL_SPECIAL_CHARS), 'item_kit_id');
$order = $this->request->getGet('order', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$item_kits = $this->item_kit->search($search, $limit, $offset, $sort, $order);
$item_kits = $this->item_kit->search($search, $limit, $offset, $sort, $order);
$total_rows = $this->item_kit->get_found_rows($search);
$data_rows = [];
foreach ($item_kits->getResult() as $item_kit) {
// Calculate the total cost and retail price of the Kit, so it can be printed out in the manage table
$item_kit = $this->_add_totals_to_item_kit($item_kit);
$item_kit = $this->_add_totals_to_item_kit($item_kit);
$data_rows[] = get_item_kit_data_row($item_kit);
}
echo json_encode(['total' => $total_rows, 'rows' => $data_rows]);
}
/**
* @return void
*/
public function suggest_search(): void
{
$search = $this->request->getPost('term');
$search = $this->request->getPost('term');
$suggestions = $this->item_kit->get_search_suggestions($search);
echo json_encode($suggestions);
}
/**
* @param int $row_id
* @return void
*/
public function getRow(int $row_id): void
{
// Calculate the total cost and retail price of the Kit, so it can be added to the table refresh
@@ -115,35 +105,31 @@ class Item_kits extends Secure_Controller
echo json_encode(get_item_kit_data_row($item_kit));
}
/**
* @param int $item_kit_id
* @return void
*/
public function getView(int $item_kit_id = NEW_ENTRY): void
{
$info = $this->item_kit->get_info($item_kit_id);
if ($item_kit_id == NEW_ENTRY) {
if ($item_kit_id === NEW_ENTRY) {
$info->price_option = '0';
$info->print_option = PRINT_ALL;
$info->kit_item_id = 0;
$info->item_number = '';
$info->kit_item_id = 0;
$info->item_number = '';
$info->kit_discount = 0;
}
foreach (get_object_vars($info) as $property => $value) {
$info->$property = $value;
$info->{$property} = $value;
}
$data['item_kit_info'] = $info;
$data['item_kit_info'] = $info;
$items = [];
foreach ($this->item_kit_items->get_info($item_kit_id) as $item_kit_item) {
$item['kit_sequence'] = $item_kit_item['kit_sequence'];
$item['name'] = $this->item->get_info($item_kit_item['item_id'])->name;
$item['item_id'] = $item_kit_item['item_id'];
$item['quantity'] = $item_kit_item['quantity'];
$item['name'] = $this->item->get_info($item_kit_item['item_id'])->name;
$item['item_id'] = $item_kit_item['item_id'];
$item['quantity'] = $item_kit_item['quantity'];
$items[] = $item;
}
@@ -151,50 +137,47 @@ class Item_kits extends Secure_Controller
$data['item_kit_items'] = $items;
$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 : '';
$data['selected_kit_item'] = ($item_kit_id > 0 && isset($info->kit_item_id)) ? $info->item_name : '';
echo view("item_kits/form", $data);
echo view('item_kits/form', $data);
}
/**
* @param int $item_kit_id
* @return void
*/
public function postSave(int $item_kit_id = NEW_ENTRY): void
{
$item_kit_data = [
'name' => $this->request->getPost('name'),
'item_kit_number' => $this->request->getPost('item_kit_number'),
'item_id' => $this->request->getPost('kit_item_id'),
'item_id' => $this->request->getPost('kit_item_id') ? null : (int) ($this->request->getPost('kit_item_id')),
'kit_discount' => parse_decimals($this->request->getPost('kit_discount')),
'kit_discount_type' => $this->request->getPost('kit_discount_type') === null ? PERCENT : intval($this->request->getPost('kit_discount_type')),
'price_option' => $this->request->getPost('price_option') === null ? PRICE_ALL : intval($this->request->getPost('price_option')),
'print_option' => $this->request->getPost('print_option') === null ? PRINT_ALL : intval($this->request->getPost('print_option')),
'description' => $this->request->getPost('description')
'kit_discount_type' => $this->request->getPost('kit_discount_type') === null ? PERCENT : (int) ($this->request->getPost('kit_discount_type')),
'price_option' => $this->request->getPost('price_option') === null ? PRICE_ALL : (int) ($this->request->getPost('price_option')),
'print_option' => $this->request->getPost('print_option') === null ? PRINT_ALL : (int) ($this->request->getPost('print_option')),
'description' => $this->request->getPost('description'),
];
if ($this->item_kit->save_value($item_kit_data, $item_kit_id)) {
$new_item = false;
// New item kit
if ($item_kit_id == NEW_ENTRY) {
if ($item_kit_id === NEW_ENTRY) {
$item_kit_id = $item_kit_data['item_kit_id'];
$new_item = true;
$new_item = true;
}
$item_kit_items_array = $this->request->getPost('item_kit_qty') === null ? null : $this->request->getPost('item_kit_qty');
if ($item_kit_items_array != null) {
if ($item_kit_items_array !== null) {
$item_kit_items = [];
foreach ($item_kit_items_array as $item_id => $item_kit_qty) {
$item_kit_items[] = [
'item_id' => $item_id,
'quantity' => $item_kit_qty === null ? 0 : parse_quantity($item_kit_qty),
'kit_sequence' => $this->request->getPost("item_kit_seq[$item_id]") === null ? 0 : intval($this->request->getPost("item_kit_seq[$item_id]"))
'kit_sequence' => $this->request->getPost("item_kit_seq[{$item_id}]") === null ? 0 : (int) ($this->request->getPost("item_kit_seq[{$item_id}]")),
];
}
}
if (!empty($item_kit_items)) {
if (! empty($item_kit_items)) {
$success = $this->item_kit_items->save_value($item_kit_items, $item_kit_id);
} else {
$success = true;
@@ -204,27 +187,24 @@ class Item_kits extends Secure_Controller
echo json_encode([
'success' => $success,
'message' => lang('Item_kits.successful_adding') . ' ' . $item_kit_data['name'],
'id' => $item_kit_id
'id' => $item_kit_id,
]);
} else {
echo json_encode([
'success' => $success,
'message' => lang('Item_kits.successful_updating') . ' ' . $item_kit_data['name'],
'id' => $item_kit_id
'id' => $item_kit_id,
]);
}
} else { // Failure
echo json_encode([
'success' => false,
'message' => lang('Item_kits.error_adding_updating') . ' ' . $item_kit_data['name'],
'id' => NEW_ENTRY
'id' => NEW_ENTRY,
]);
}
}
/**
* @return void
*/
public function postDelete(): void
{
$item_kits_to_delete = $this->request->getPost('ids', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
@@ -232,7 +212,7 @@ class Item_kits extends Secure_Controller
if ($this->item_kit->delete_list($item_kits_to_delete)) {
echo json_encode([
'success' => true,
'message' => lang('Item_kits.successful_deleted') . ' ' . count($item_kits_to_delete) . ' ' . lang('Item_kits.one_or_multiple')
'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')]);
@@ -242,28 +222,28 @@ class Item_kits extends Secure_Controller
/**
* Checks the validity of the item kit number. Used in app/Views/item_kits/form.php
*
* @return void
* @noinspection PhpUnused
*/
public function postCheckItemNumber(): void
{
$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';
echo ! $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
*
* @noinspection PhpUnused
*/
public function getGenerateBarcodes(string $item_kit_ids): void
{
$barcode_lib = new Barcode_lib();
$result = [];
$result = [];
$item_kit_ids = explode(':', $item_kit_ids);
foreach ($item_kit_ids as $item_kid_id) {
// Calculate the total cost and retail price of the Kit, so it can be added to the barcode text at the bottom
$item_kit = $this->_add_totals_to_item_kit($this->item_kit->get_info($item_kid_id));
@@ -275,20 +255,20 @@ class Item_kits extends Secure_Controller
'item_id' => $item_kid_id,
'item_number' => $item_kid_id,
'cost_price' => $item_kit->total_cost_price,
'unit_price' => $item_kit->total_unit_price
'unit_price' => $item_kit->total_unit_price,
];
}
$data['items'] = $result;
$data['items'] = $result;
$barcode_config = $barcode_lib->get_barcode_config();
// In case the selected barcode type is not Code39 or Code128 we set by default Code128
// The rationale for this is that EAN codes cannot have strings as seed, so 'KIT ' is not allowed
if ($barcode_config['barcode_type'] != 'C39' && $barcode_config['barcode_type'] != 'C128') {
if ($barcode_config['barcode_type'] !== 'C39' && $barcode_config['barcode_type'] !== 'C128') {
$barcode_config['barcode_type'] = 'C128';
}
$data['barcode_config'] = $barcode_config;
// Display barcodes
echo view("barcodes/barcode_sheet", $data);
echo view('barcodes/barcode_sheet', $data);
}
}

View File

File diff suppressed because it is too large Load Diff

View File

@@ -10,21 +10,18 @@ use Config\OSPOS;
use Config\Services;
/**
* @property employee employee
* @property Employee employee
*/
class Login extends BaseController
{
public Model $employee;
/**
* @return RedirectResponse|string
*/
public function index(): string|RedirectResponse
public function index(): RedirectResponse|string
{
$this->employee = model(Employee::class);
if (!$this->employee->is_logged_in()) {
if (! $this->employee->is_logged_in()) {
$migration = new MY_Migration(config('Migrations'));
$config = config(OSPOS::class)->settings;
$config = config(OSPOS::class)->settings;
$gcaptcha_enabled = array_key_exists('gcaptcha_enable', $config)
? $config['gcaptcha_enable']
@@ -40,31 +37,32 @@ class Login extends BaseController
'latest_version' => $migration->get_latest_migration(),
'gcaptcha_enabled' => $gcaptcha_enabled,
'config' => $config,
'validation' => $validation
'validation' => $validation,
];
if ($this->request->getMethod() !== 'POST') {
return view('login', $data);
}
$rules = ['username' => 'required|login_check[data]'];
$rules = ['username' => 'required|login_check[data]'];
$messages = [
'username' => [
'required' => lang('Login.required_username'),
'login_check' => lang('Login.invalid_username_and_password'),
]
],
];
if (!$this->validate($rules, $messages)) {
$data['has_errors'] = !empty($validation->getErrors());
if (! $this->validate($rules, $messages)) {
$data['has_errors'] = ! empty($validation->getErrors());
return view('login', $data);
}
if (!$data['is_latest']) {
if (! $data['is_latest']) {
set_time_limit(3600);
$migration->setNamespace('App')->latest();
return redirect()->to('login');
}
}

View File

@@ -3,7 +3,6 @@
namespace App\Controllers;
use App\Libraries\Sms_lib;
use App\Models\Person;
class Messages extends Secure_Controller
@@ -17,34 +16,24 @@ class Messages extends Secure_Controller
$this->sms_lib = new Sms_lib();
}
/**
* @return void
*/
public function getIndex(): void
{
echo view('messages/sms');
}
/**
* @param int $person_id
* @return void
*/
public function getView(int $person_id = NEW_ENTRY): void
{
$person = model(Person::class);
$info = $person->get_info($person_id);
$info = $person->get_info($person_id);
foreach (get_object_vars($info) as $property => $value) {
$info->$property = $value;
$info->{$property} = $value;
}
$data['person_info'] = $info;
echo view('messages/form_sms', $data);
}
/**
* @return void
*/
public function send(): void
{
$phone = $this->request->getPost('phone', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
@@ -62,8 +51,6 @@ 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
* @noinspection PhpUnused
*/
public function send_form(int $person_id = NEW_ENTRY): void
@@ -77,13 +64,13 @@ class Messages extends Secure_Controller
echo json_encode([
'success' => true,
'message' => lang('Messages.successfully_sent') . ' ' . esc($phone),
'person_id' => $person_id
'person_id' => $person_id,
]);
} else {
echo json_encode([
'success' => false,
'message' => lang('Messages.unsuccessfully_sent') . ' ' . esc($phone),
'person_id' => NEW_ENTRY
'person_id' => NEW_ENTRY,
]);
}
}

View File

@@ -8,7 +8,7 @@ use App\Models\Module;
* Part of the grants mechanism to restrict access to modules that the user doesn't have permission for.
* Instantiated in the views.
*
* @property module module
* @property Module module
*/
class No_access extends BaseController
{
@@ -19,11 +19,6 @@ class No_access extends BaseController
$this->module = model(Module::class);
}
/**
* @param string $module_id
* @param string $permission_id
* @return void
*/
public function getIndex(string $module_id = '', string $permission_id = ''): void
{
$data['module_name'] = $this->module->get_module_name($module_id);

View File

@@ -16,17 +16,11 @@ class Office extends Secure_Controller
parent::__construct('office', null, 'office');
}
/**
* @return void
*/
public function getIndex(): void
{
echo view('home/office');
}
/**
* @return void
*/
public function logout(): void
{
$this->employee = model(Employee::class);

View File

@@ -3,16 +3,13 @@
namespace App\Controllers;
use App\Models\Person;
use Config\Services;
use function Tamtamchik\NameCase\str_name_case;
abstract class Persons extends Secure_Controller
{
protected Person $person;
/**
* @param string|null $module_id
*/
public function __construct(?string $module_id = null)
{
parent::__construct($module_id);
@@ -20,9 +17,6 @@ abstract class Persons extends Secure_Controller
$this->person = model(Person::class);
}
/**
* @return void
*/
public function getIndex(): void
{
$data['table_headers'] = get_people_manage_table_headers();
@@ -35,7 +29,7 @@ abstract class Persons extends Secure_Controller
*/
public function getSuggest(): void
{
$search = $this->request->getGet('term');
$search = $this->request->getGet('term');
$suggestions = $this->person->get_search_suggestions($search);
echo json_encode($suggestions);
@@ -66,8 +60,6 @@ abstract class Persons extends Secure_Controller
$adjusted_name = str_name_case($input);
// TODO: Use preg_replace to match HTML entities and convert them to lowercase. This is a workaround for https://github.com/tamtamchik/namecase/issues/20
return preg_replace_callback('/&[a-zA-Z0-9#]+;/', function ($matches) {
return strtolower($matches[0]);
}, $adjusted_name);
return preg_replace_callback('/&[a-zA-Z0-9#]+;/', static fn ($matches) => strtolower($matches[0]), $adjusted_name);
}
}

View File

@@ -2,9 +2,9 @@
namespace App\Controllers;
use App\Libraries\Barcode_lib;
use App\Libraries\Receiving_lib;
use App\Libraries\Token_lib;
use App\Libraries\Barcode_lib;
use App\Models\Inventory;
use App\Models\Item;
use App\Models\Item_kit;
@@ -12,7 +12,6 @@ use App\Models\Receiving;
use App\Models\Stock_location;
use App\Models\Supplier;
use Config\OSPOS;
use Config\Services;
use ReflectionException;
class Receivings extends Secure_Controller
@@ -33,21 +32,18 @@ class Receivings extends Secure_Controller
parent::__construct('receivings');
$this->receiving_lib = new Receiving_lib();
$this->token_lib = new Token_lib();
$this->barcode_lib = new Barcode_lib();
$this->token_lib = new Token_lib();
$this->barcode_lib = new Barcode_lib();
$this->inventory = model(Inventory::class);
$this->item_kit = model(Item_kit::class);
$this->item = model(Item::class);
$this->receiving = model(Receiving::class);
$this->inventory = model(Inventory::class);
$this->item_kit = model(Item_kit::class);
$this->item = model(Item::class);
$this->receiving = model(Receiving::class);
$this->stock_location = model(Stock_location::class);
$this->supplier = model(Supplier::class);
$this->config = config(OSPOS::class)->settings;
$this->supplier = model(Supplier::class);
$this->config = config(OSPOS::class)->settings;
}
/**
* @return void
*/
public function getIndex(): void
{
$this->_reload();
@@ -56,12 +52,11 @@ class Receivings extends Secure_Controller
/**
* Returns search suggestions for an item. Used in app/Views/sales/register.php
*
* @return void
* @noinspection PhpUnused
*/
public function getItemSearch(): void
{
$search = $this->request->getGet('term');
$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));
@@ -71,12 +66,11 @@ class Receivings extends Secure_Controller
/**
* Gets search suggestions for a stock item. Used in app/Views/receivings/receiving.php
*
* @return void
* @noinspection PhpUnused
*/
public function getStockItemSearch(): void
{
$search = $this->request->getGet('term');
$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));
@@ -86,7 +80,6 @@ class Receivings extends Secure_Controller
/**
* Set supplier if it exists in the database. Used in app/Views/receivings/receiving.php
*
* @return void
* @noinspection PhpUnused
*/
public function postSelectSupplier(): void
@@ -102,16 +95,15 @@ class Receivings extends Secure_Controller
/**
* Change receiving mode for current receiving. Used in app/Views/receivings/receiving.php
*
* @return void
* @noinspection PhpUnused
*/
public function postChangeMode(): void
{
$stock_destination = $this->request->getPost('stock_destination', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$stock_source = $this->request->getPost('stock_source', FILTER_SANITIZE_NUMBER_INT);
$stock_source = $this->request->getPost('stock_source', FILTER_SANITIZE_NUMBER_INT);
if ((!$stock_source || $stock_source == $this->receiving_lib->get_stock_source()) &&
(!$stock_destination || $stock_destination == $this->receiving_lib->get_stock_destination())
if ((! $stock_source || $stock_source === $this->receiving_lib->get_stock_source())
&& (! $stock_destination || $stock_destination === $this->receiving_lib->get_stock_destination())
) {
$this->receiving_lib->clear_reference();
$mode = $this->request->getPost('mode', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
@@ -127,7 +119,6 @@ class Receivings extends Secure_Controller
/**
* Sets receiving comment. Used in app/Views/receivings/receiving.php
*
* @return void
* @noinspection PhpUnused
*/
public function postSetComment(): void
@@ -138,18 +129,16 @@ class Receivings extends Secure_Controller
/**
* Sets the print after sale flag for the receiving. Used in app/Views/receivings/receiving.php
*
* @return void
* @noinspection PhpUnused
*/
public function postSetPrintAfterSale(): void
{
$this->receiving_lib->set_print_after_sale($this->request->getPost('recv_print_after_sale') != null);
$this->receiving_lib->set_print_after_sale($this->request->getPost('recv_print_after_sale') !== null);
}
/**
* Sets the reference number for the receiving. Used in app/Views/receivings/receiving.php
*
* @return void
* @noinspection PhpUnused
*/
public function postSetReference(): void
@@ -160,26 +149,25 @@ class Receivings extends Secure_Controller
/**
* Add an item to the receiving. Used in app/Views/receivings/receiving.php
*
* @return void
* @noinspection PhpUnused
*/
public function postAdd(): void
{
$data = [];
$mode = $this->receiving_lib->get_mode();
$mode = $this->receiving_lib->get_mode();
$item_id_or_number_or_item_kit_or_receipt = $this->request->getPost('item', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$this->token_lib->parse_barcode($quantity, $price, $item_id_or_number_or_item_kit_or_receipt);
$quantity = ($mode == 'receive' || $mode == 'requisition') ? $quantity : -$quantity;
$quantity = ($mode === 'receive' || $mode === 'requisition') ? $quantity : -$quantity;
$item_location = $this->receiving_lib->get_stock_source();
$discount = $this->config['default_receivings_discount'];
$discount = $this->config['default_receivings_discount'];
$discount_type = $this->config['default_receivings_discount_type'];
if ($mode == 'return' && $this->receiving->is_valid_receipt($item_id_or_number_or_item_kit_or_receipt)) {
if ($mode === 'return' && $this->receiving->is_valid_receipt($item_id_or_number_or_item_kit_or_receipt)) {
$this->receiving_lib->return_entire_receiving($item_id_or_number_or_item_kit_or_receipt);
} elseif ($this->item_kit->is_valid_item_kit($item_id_or_number_or_item_kit_or_receipt)) {
$this->receiving_lib->add_item_kit($item_id_or_number_or_item_kit_or_receipt, $item_location, $discount, $discount_type);
} elseif (!$this->receiving_lib->add_item($item_id_or_number_or_item_kit_or_receipt, $quantity, $item_location, $discount, $discount_type)) {
} elseif (! $this->receiving_lib->add_item($item_id_or_number_or_item_kit_or_receipt, $quantity, $item_location, $discount, $discount_type)) {
$data['error'] = lang('Receivings.unable_to_add_item');
}
@@ -189,9 +177,9 @@ class Receivings extends Secure_Controller
/**
* Edit line item in current receiving. Used in app/Views/receivings/receiving.php
*
* @param $item_id
* @return void
* @noinspection PhpUnused
*
* @param mixed $item_id
*/
public function postEditItem($item_id): void
{
@@ -203,14 +191,14 @@ class Receivings extends Secure_Controller
'discount' => 'trim|permit_empty|decimal_locale',
];
$price = parse_decimals($this->request->getPost('price'));
$quantity = parse_quantity($this->request->getPost('quantity'));
$price = parse_decimals($this->request->getPost('price'));
$quantity = parse_quantity($this->request->getPost('quantity'));
$raw_receiving_quantity = parse_quantity($this->request->getPost('receiving_quantity'));
$description = $this->request->getPost('description', FILTER_SANITIZE_FULL_SPECIAL_CHARS); // TODO: Duplicated code
$serialnumber = $this->request->getPost('serialnumber', FILTER_SANITIZE_FULL_SPECIAL_CHARS) ?? '';
$description = $this->request->getPost('description', FILTER_SANITIZE_FULL_SPECIAL_CHARS); // TODO: Duplicated code
$serialnumber = $this->request->getPost('serialnumber', FILTER_SANITIZE_FULL_SPECIAL_CHARS) ?? '';
$discount_type = $this->request->getPost('discount_type', FILTER_SANITIZE_NUMBER_INT);
$discount = $discount_type
$discount = $discount_type
? parse_quantity(filter_var($this->request->getPost('discount'), FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION))
: parse_decimals(filter_var($this->request->getPost('discount'), FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION));
@@ -228,28 +216,30 @@ class Receivings extends Secure_Controller
/**
* Edit a receiving. Used in app/Controllers/Receivings.php
*
* @param $receiving_id
* @return void
* @noinspection PhpUnused
*
* @param mixed $receiving_id
*/
public function getEdit($receiving_id): void
{
$data = [];
$data['suppliers'] = ['' => 'No Supplier'];
foreach ($this->supplier->get_all()->getResult() as $supplier) {
$data['suppliers'][$supplier->person_id] = $supplier->first_name . ' ' . $supplier->last_name;
}
$data['employees'] = [];
foreach ($this->employee->get_all()->getResult() as $employee) {
$data['employees'][$employee->person_id] = $employee->first_name . ' ' . $employee->last_name;
}
$receiving_info = $this->receiving->get_info($receiving_id)->getRowArray();
$data['selected_supplier_name'] = !empty($receiving_info['supplier_id']) ? $receiving_info['company_name'] : '';
$data['selected_supplier_id'] = $receiving_info['supplier_id'];
$data['receiving_info'] = $receiving_info;
$receiving_info = $this->receiving->get_info($receiving_id)->getRowArray();
$data['selected_supplier_name'] = ! empty($receiving_info['supplier_id']) ? $receiving_info['company_name'] : '';
$data['selected_supplier_id'] = $receiving_info['supplier_id'];
$data['receiving_info'] = $receiving_info;
echo view('receivings/form', $data);
}
@@ -257,9 +247,9 @@ class Receivings extends Secure_Controller
/**
* Deletes an item from the current receiving. Used in app/Views/receivings/receiving.php
*
* @param $item_number
* @return void
* @noinspection PhpUnused
*
* @param mixed $item_number
*/
public function getDeleteItem($item_number): void
{
@@ -273,14 +263,14 @@ class Receivings extends Secure_Controller
*/
public function postDelete(int $receiving_id = -1, bool $update_inventory = true): void
{
$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
$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([
'success' => true,
'message' => lang('Receivings.successfully_deleted') . ' ' . count($receiving_ids) . ' ' . lang('Receivings.one_or_multiple'),
'ids' => $receiving_ids
'ids' => $receiving_ids,
]);
} else {
echo json_encode(['success' => false, 'message' => lang('Receivings.cannot_be_deleted')]);
@@ -290,7 +280,6 @@ class Receivings extends Secure_Controller
/**
* Removes a supplier from a receiving. Used in app/Views/receivings/receiving.php
*
* @return void
* @noinspection PhpUnused
*/
public function getRemoveSupplier(): void
@@ -309,36 +298,35 @@ class Receivings extends Secure_Controller
*/
public function postComplete(): void
{
$data = [];
$data['cart'] = $this->receiving_lib->get_cart();
$data['total'] = $this->receiving_lib->get_total();
$data['transaction_time'] = to_datetime(time());
$data['mode'] = $this->receiving_lib->get_mode();
$data['comment'] = $this->receiving_lib->get_comment();
$data['reference'] = $this->receiving_lib->get_reference();
$data['payment_type'] = $this->request->getPost('payment_type', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$data['cart'] = $this->receiving_lib->get_cart();
$data['total'] = $this->receiving_lib->get_total();
$data['transaction_time'] = to_datetime(time());
$data['mode'] = $this->receiving_lib->get_mode();
$data['comment'] = $this->receiving_lib->get_comment();
$data['reference'] = $this->receiving_lib->get_reference();
$data['payment_type'] = $this->request->getPost('payment_type', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$data['show_stock_locations'] = $this->stock_location->show_locations('receivings');
$data['stock_location'] = $this->receiving_lib->get_stock_source();
if ($this->request->getPost('amount_tendered') != null) {
$data['stock_location'] = $this->receiving_lib->get_stock_source();
if ($this->request->getPost('amount_tendered') !== null) {
$data['amount_tendered'] = parse_decimals($this->request->getPost('amount_tendered'));
$data['amount_change'] = to_currency($data['amount_tendered'] - $data['total']);
$data['amount_change'] = to_currency($data['amount_tendered'] - $data['total']);
}
$employee_id = $this->employee->get_logged_in_employee_info()->person_id;
$employee_info = $this->employee->get_info($employee_id);
$employee_id = $this->employee->get_logged_in_employee_info()->person_id;
$employee_info = $this->employee->get_info($employee_id);
$data['employee'] = $employee_info->first_name . ' ' . $employee_info->last_name;
$supplier_id = $this->receiving_lib->get_supplier();
if ($supplier_id != -1) {
$supplier_info = $this->supplier->get_info($supplier_id);
$data['supplier'] = $supplier_info->company_name; // TODO: duplicated code
$data['first_name'] = $supplier_info->first_name;
$data['last_name'] = $supplier_info->last_name;
$data['supplier_email'] = $supplier_info->email;
if ($supplier_id !== -1) {
$supplier_info = $this->supplier->get_info($supplier_id);
$data['supplier'] = $supplier_info->company_name; // TODO: duplicated code
$data['first_name'] = $supplier_info->first_name;
$data['last_name'] = $supplier_info->last_name;
$data['supplier_email'] = $supplier_info->email;
$data['supplier_address'] = $supplier_info->address_1;
if (!empty($supplier_info->zip) or !empty($supplier_info->city)) {
if (! empty($supplier_info->zip) || ! empty($supplier_info->city)) {
$data['supplier_location'] = $supplier_info->zip . ' ' . $supplier_info->city;
} else {
$data['supplier_location'] = '';
@@ -348,7 +336,7 @@ class Receivings extends Secure_Controller
// SAVE receiving to database
$data['receiving_id'] = 'RECV ' . $this->receiving->save_value($data['cart'], $supplier_id, $employee_id, $data['comment'], $data['reference'], $data['payment_type'], $data['stock_location']);
if ($data['receiving_id'] == 'RECV -1') {
if ($data['receiving_id'] === 'RECV -1') {
$data['error_message'] = lang('Receivings.transaction_failed');
} else {
$data['barcode'] = $this->barcode_lib->generate_receipt_barcode($data['receiving_id']);
@@ -356,7 +344,7 @@ class Receivings extends Secure_Controller
$data['print_after_sale'] = $this->receiving_lib->is_print_after_sale();
echo view("receivings/receipt", $data);
echo view('receivings/receipt', $data);
$this->receiving_lib->clear_all();
}
@@ -369,7 +357,7 @@ class Receivings extends Secure_Controller
*/
public function postRequisitionComplete(): void
{
if ($this->receiving_lib->get_stock_source() != $this->receiving_lib->get_stock_destination()) {
if ($this->receiving_lib->get_stock_source() !== $this->receiving_lib->get_stock_destination()) {
foreach ($this->receiving_lib->get_cart() as $item) {
$this->receiving_lib->delete_item($item['line']);
$this->receiving_lib->add_item($item['item_id'], $item['quantity'], $this->receiving_lib->get_stock_destination(), $item['discount_type']);
@@ -387,35 +375,35 @@ class Receivings extends Secure_Controller
/**
* Gets the receipt for a receiving. Used in app/Views/receivings/form.php
*
* @param $receiving_id
* @return void
* @noinspection PhpUnused
*
* @param mixed $receiving_id
*/
public function getReceipt($receiving_id): void
{
$receiving_info = $this->receiving->get_info($receiving_id)->getRowArray();
$this->receiving_lib->copy_entire_receiving($receiving_id);
$data['cart'] = $this->receiving_lib->get_cart();
$data['total'] = $this->receiving_lib->get_total();
$data['mode'] = $this->receiving_lib->get_mode();
$data['transaction_time'] = to_datetime(strtotime($receiving_info['receiving_time']));
$data['cart'] = $this->receiving_lib->get_cart();
$data['total'] = $this->receiving_lib->get_total();
$data['mode'] = $this->receiving_lib->get_mode();
$data['transaction_time'] = to_datetime(strtotime($receiving_info['receiving_time']));
$data['show_stock_locations'] = $this->stock_location->show_locations('receivings');
$data['payment_type'] = $receiving_info['payment_type'];
$data['reference'] = $this->receiving_lib->get_reference();
$data['receiving_id'] = 'RECV ' . $receiving_id;
$data['barcode'] = $this->barcode_lib->generate_receipt_barcode($data['receiving_id']);
$employee_info = $this->employee->get_info($receiving_info['employee_id']);
$data['employee'] = $employee_info->first_name . ' ' . $employee_info->last_name;
$data['payment_type'] = $receiving_info['payment_type'];
$data['reference'] = $this->receiving_lib->get_reference();
$data['receiving_id'] = 'RECV ' . $receiving_id;
$data['barcode'] = $this->barcode_lib->generate_receipt_barcode($data['receiving_id']);
$employee_info = $this->employee->get_info($receiving_info['employee_id']);
$data['employee'] = $employee_info->first_name . ' ' . $employee_info->last_name;
$supplier_id = $this->receiving_lib->get_supplier(); // TODO: Duplicated code
if ($supplier_id != -1) {
$supplier_info = $this->supplier->get_info($supplier_id);
$data['supplier'] = $supplier_info->company_name;
$data['first_name'] = $supplier_info->first_name;
$data['last_name'] = $supplier_info->last_name;
$data['supplier_email'] = $supplier_info->email;
if ($supplier_id !== -1) {
$supplier_info = $this->supplier->get_info($supplier_id);
$data['supplier'] = $supplier_info->company_name;
$data['first_name'] = $supplier_info->first_name;
$data['last_name'] = $supplier_info->last_name;
$data['supplier_email'] = $supplier_info->email;
$data['supplier_address'] = $supplier_info->address_1;
if (!empty($supplier_info->zip) or !empty($supplier_info->city)) {
if (! empty($supplier_info->zip) || ! empty($supplier_info->city)) {
$data['supplier_location'] = $supplier_info->zip . ' ' . $supplier_info->city;
} else {
$data['supplier_location'] = '';
@@ -424,44 +412,40 @@ class Receivings extends Secure_Controller
$data['print_after_sale'] = false;
echo view("receivings/receipt", $data);
echo view('receivings/receipt', $data);
$this->receiving_lib->clear_all();
}
/**
* @param array $data
* @return void
*/
private function _reload(array $data = []): void // TODO: Hungarian notation
{
$data['cart'] = $this->receiving_lib->get_cart();
$data['modes'] = ['receive' => lang('Receivings.receiving'), 'return' => lang('Receivings.return')];
$data['mode'] = $this->receiving_lib->get_mode();
$data['stock_locations'] = $this->stock_location->get_allowed_locations('receivings');
$data['cart'] = $this->receiving_lib->get_cart();
$data['modes'] = ['receive' => lang('Receivings.receiving'), 'return' => lang('Receivings.return')];
$data['mode'] = $this->receiving_lib->get_mode();
$data['stock_locations'] = $this->stock_location->get_allowed_locations('receivings');
$data['show_stock_locations'] = count($data['stock_locations']) > 1;
if ($data['show_stock_locations']) {
$data['modes']['requisition'] = lang('Receivings.requisition');
$data['stock_source'] = $this->receiving_lib->get_stock_source();
$data['stock_destination'] = $this->receiving_lib->get_stock_destination();
$data['stock_source'] = $this->receiving_lib->get_stock_source();
$data['stock_destination'] = $this->receiving_lib->get_stock_destination();
}
$data['total'] = $this->receiving_lib->get_total();
$data['total'] = $this->receiving_lib->get_total();
$data['items_module_allowed'] = $this->employee->has_grant('items', $this->employee->get_logged_in_employee_info()->person_id);
$data['comment'] = $this->receiving_lib->get_comment();
$data['reference'] = $this->receiving_lib->get_reference();
$data['payment_options'] = $this->receiving->get_payment_options();
$data['comment'] = $this->receiving_lib->get_comment();
$data['reference'] = $this->receiving_lib->get_reference();
$data['payment_options'] = $this->receiving->get_payment_options();
$supplier_id = $this->receiving_lib->get_supplier();
if ($supplier_id != -1) { // TODO: Duplicated Code... replace -1 with a constant
$supplier_info = $this->supplier->get_info($supplier_id);
$data['supplier'] = $supplier_info->company_name;
$data['first_name'] = $supplier_info->first_name;
$data['last_name'] = $supplier_info->last_name;
$data['supplier_email'] = $supplier_info->email;
if ($supplier_id !== -1) { // TODO: Duplicated Code... replace -1 with a constant
$supplier_info = $this->supplier->get_info($supplier_id);
$data['supplier'] = $supplier_info->company_name;
$data['first_name'] = $supplier_info->first_name;
$data['last_name'] = $supplier_info->last_name;
$data['supplier_email'] = $supplier_info->email;
$data['supplier_address'] = $supplier_info->address_1;
if (!empty($supplier_info->zip) or !empty($supplier_info->city)) {
if (! empty($supplier_info->zip) || ! empty($supplier_info->city)) {
$data['supplier_location'] = $supplier_info->zip . ' ' . $supplier_info->city;
} else {
$data['supplier_location'] = '';
@@ -470,7 +454,7 @@ class Receivings extends Secure_Controller
$data['print_after_sale'] = $this->receiving_lib->is_print_after_sale();
echo view("receivings/receiving", $data);
echo view('receivings/receiving', $data);
}
/**
@@ -488,7 +472,7 @@ class Receivings extends Secure_Controller
'supplier_id' => $this->request->getPost('supplier_id') ? $this->request->getPost('supplier_id', FILTER_SANITIZE_NUMBER_INT) : null,
'employee_id' => $this->request->getPost('employee_id', FILTER_SANITIZE_NUMBER_INT),
'comment' => $this->request->getPost('comment', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
'reference' => $this->request->getPost('reference') != '' ? $this->request->getPost('reference', FILTER_SANITIZE_FULL_SPECIAL_CHARS) : null
'reference' => $this->request->getPost('reference') !== '' ? $this->request->getPost('reference', FILTER_SANITIZE_FULL_SPECIAL_CHARS) : null,
];
$this->inventory->update('RECV ' . $receiving_id, ['trans_date' => $receiving_time]);
@@ -496,13 +480,13 @@ class Receivings extends Secure_Controller
echo json_encode([
'success' => true,
'message' => lang('Receivings.successfully_updated'),
'id' => $receiving_id
'id' => $receiving_id,
]);
} else {
echo json_encode([
'success' => false,
'message' => lang('Receivings.unsuccessfully_updated'),
'id' => $receiving_id
'id' => $receiving_id,
]);
}
}
@@ -510,7 +494,6 @@ class Receivings extends Secure_Controller
/**
* Cancel an in-process receiving. Used in app/Views/receivings/receiving.php
*
* @return void
* @noinspection PhpUnused
*/
public function postCancelReceiving(): void

View File

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because it is too large Load Diff

View File

@@ -4,8 +4,6 @@ namespace App\Controllers;
use App\Models\Employee;
use App\Models\Module;
use CodeIgniter\Model;
use CodeIgniter\Session\Session;
use Config\OSPOS;
use Config\Services;
@@ -14,11 +12,10 @@ use Config\Services;
* Controllers that are considered secure extend Secure_Controller, optionally a $module_id can
* be set to also check if a user can access a particular module in the system.
*
* @property employee employee
* @property module module
* @property array global_view_data
* @property session session
*
* @property Employee employee
* @property Module module
* @property Session session
*/
class Secure_Controller extends BaseController
{
@@ -27,45 +24,43 @@ class Secure_Controller extends BaseController
protected Module $module;
protected Session $session;
/**
* @param string $module_id
* @param string|null $submodule_id
* @param string|null $menu_group
*/
public function __construct(string $module_id = '', ?string $submodule_id = null, ?string $menu_group = null)
{
$this->employee = model(Employee::class);
$this->module = model(Module::class);
$config = config(OSPOS::class)->settings;
$validation = Services::validation();
$this->module = model(Module::class);
$config = config(OSPOS::class)->settings;
$validation = Services::validation();
if (! $this->employee->is_logged_in()) {
header('Location:' . base_url('login'));
if (!$this->employee->is_logged_in()) {
header("Location:" . base_url('login'));
exit();
}
$logged_in_employee_info = $this->employee->get_logged_in_employee_info();
if (
!$this->employee->has_module_grant($module_id, $logged_in_employee_info->person_id)
|| (isset($submodule_id) && !$this->employee->has_module_grant($submodule_id, $logged_in_employee_info->person_id))
! $this->employee->has_module_grant($module_id, $logged_in_employee_info->person_id)
|| (isset($submodule_id) && ! $this->employee->has_module_grant($submodule_id, $logged_in_employee_info->person_id))
) {
header("Location:" . base_url("no_access/$module_id/$submodule_id"));
header('Location:' . base_url("no_access/{$module_id}/{$submodule_id}"));
exit();
}
// Load up global global_view_data visible to all the loaded views
$this->session = session();
if ($menu_group == null) {
if ($menu_group === null) {
$menu_group = $this->session->get('menu_group');
} else {
$this->session->set('menu_group', $menu_group);
}
$allowed_modules = $menu_group == 'home'
$allowed_modules = $menu_group === 'home'
? $this->module->get_allowed_home_modules($logged_in_employee_info->person_id)
: $this->module->get_allowed_office_modules($logged_in_employee_info->person_id);
$this->global_view_data = [];
foreach ($allowed_modules->getResult() as $module) {
$this->global_view_data['allowed_modules'][] = $module;
}
@@ -73,19 +68,19 @@ class Secure_Controller extends BaseController
$this->global_view_data += [
'user_info' => $logged_in_employee_info,
'controller_name' => $module_id,
'config' => $config
'config' => $config,
];
view('viewData', $this->global_view_data);
}
public function sanitizeSortColumn($headers, $field, $default): string
{
return $field != null && in_array($field, array_keys(array_merge(...$headers))) ? $field : $default;
return $field !== null && in_array($field, array_keys(array_merge(...$headers)), true) ? $field : $default;
}
/**
* AJAX function used to confirm whether values sent in the request are numeric
* @return void
*
* @noinspection PhpUnused
*/
public function getCheckNumeric(): void
@@ -93,6 +88,7 @@ class Secure_Controller extends BaseController
foreach ($this->request->getGet() as $value) {
if (parse_decimals($value) === false) {
echo 'false';
return;
}
}
@@ -100,7 +96,8 @@ class Secure_Controller extends BaseController
}
/**
* @param $key
* @param mixed $key
*
* @return mixed|void
*/
public function getConfig($key)
@@ -135,7 +132,6 @@ class Secure_Controller extends BaseController
}
/**
* @param int $data_item_id
* @return false
*/
public function getView(int $data_item_id = -1)
@@ -144,7 +140,6 @@ class Secure_Controller extends BaseController
}
/**
* @param int $data_item_id
* @return false
*/
public function postSave(int $data_item_id = -1)

View File

@@ -3,7 +3,6 @@
namespace App\Controllers;
use App\Models\Supplier;
use Config\Services;
class Suppliers extends Persons
{
@@ -16,9 +15,6 @@ class Suppliers extends Persons
$this->supplier = model(Supplier::class);
}
/**
* @return void
*/
public function getIndex(): void
{
$data['table_headers'] = get_suppliers_manage_table_headers();
@@ -28,12 +24,12 @@ class Suppliers extends Persons
/**
* Gets one row for a supplier manage table. This is called using AJAX to update one row.
* @param $row_id
* @return void
*
* @param mixed $row_id
*/
public function getRow($row_id): void
{
$data_row = get_supplier_data_row($this->supplier->get_info($row_id));
$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);
@@ -41,25 +37,24 @@ class Suppliers extends Persons
/**
* Returns Supplier table data rows. This will be called with AJAX.
* @return void
**/
*/
public function getSearch(): void
{
$search = $this->request->getGet('search');
$limit = $this->request->getGet('limit', FILTER_SANITIZE_NUMBER_INT);
$limit = $this->request->getGet('limit', FILTER_SANITIZE_NUMBER_INT);
$offset = $this->request->getGet('offset', FILTER_SANITIZE_NUMBER_INT);
$sort = $this->sanitizeSortColumn(supplier_headers(), $this->request->getGet('sort', FILTER_SANITIZE_FULL_SPECIAL_CHARS), 'people.person_id');
$order = $this->request->getGet('order', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$sort = $this->sanitizeSortColumn(supplier_headers(), $this->request->getGet('sort', FILTER_SANITIZE_FULL_SPECIAL_CHARS), 'people.person_id');
$order = $this->request->getGet('order', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$suppliers = $this->supplier->search($search, $limit, $offset, $sort, $order);
$suppliers = $this->supplier->search($search, $limit, $offset, $sort, $order);
$total_rows = $this->supplier->get_found_rows($search);
$data_rows = [];
foreach ($suppliers->getResult() as $supplier) {
$row = get_supplier_data_row($supplier);
$row = get_supplier_data_row($supplier);
$row['category'] = $this->supplier->get_category_name($row['category']);
$data_rows[] = $row;
$data_rows[] = $row;
}
echo json_encode(['total' => $total_rows, 'rows' => $data_rows]);
@@ -67,21 +62,18 @@ class Suppliers extends Persons
/**
* Gives search suggestions based on what is being searched for
**/
*/
public function getSuggest(): void
{
$search = $this->request->getGet('term');
$search = $this->request->getGet('term');
$suggestions = $this->supplier->get_search_suggestions($search, true);
echo json_encode($suggestions);
}
/**
* @return void
*/
public function suggest_search(): void
{
$search = $this->request->getPost('term');
$search = $this->request->getPost('term');
$suggestions = $this->supplier->get_search_suggestions($search, false);
echo json_encode($suggestions);
@@ -89,37 +81,32 @@ class Suppliers extends Persons
/**
* Loads the supplier edit form
*
* @param int $supplier_id
* @return void
*/
public function getView(int $supplier_id = NEW_ENTRY): void
{
$info = $this->supplier->get_info($supplier_id);
foreach (get_object_vars($info) as $property => $value) {
$info->$property = $value;
$info->{$property} = $value;
}
$data['person_info'] = $info;
$data['categories'] = $this->supplier->get_categories();
$data['categories'] = $this->supplier->get_categories();
echo view("suppliers/form", $data);
echo view('suppliers/form', $data);
}
/**
* Inserts/updates a supplier
*
* @param int $supplier_id
* @return void
*/
public function postSave(int $supplier_id = NEW_ENTRY): void
{
$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);
$email = strtolower($this->request->getPost('email', FILTER_SANITIZE_EMAIL));
$last_name = $this->request->getPost('last_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$email = strtolower($this->request->getPost('email', FILTER_SANITIZE_EMAIL));
// Format first and last name properly
$first_name = $this->nameize($first_name);
$last_name = $this->nameize($last_name);
$last_name = $this->nameize($last_name);
$person_data = [
'first_name' => $first_name,
@@ -133,46 +120,43 @@ class Suppliers extends Persons
'state' => $this->request->getPost('state', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
'zip' => $this->request->getPost('zip', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
'country' => $this->request->getPost('country', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
'comments' => $this->request->getPost('comments', FILTER_SANITIZE_FULL_SPECIAL_CHARS)
'comments' => $this->request->getPost('comments', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
];
$supplier_data = [
'company_name' => $this->request->getPost('company_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
'agency_name' => $this->request->getPost('agency_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
'category' => $this->request->getPost('category', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
'account_number' => $this->request->getPost('account_number') == '' ? null : $this->request->getPost('account_number', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
'tax_id' => $this->request->getPost('tax_id', FILTER_SANITIZE_NUMBER_INT)
'account_number' => $this->request->getPost('account_number') === '' ? null : $this->request->getPost('account_number', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
'tax_id' => $this->request->getPost('tax_id', FILTER_SANITIZE_NUMBER_INT),
];
if ($this->supplier->save_supplier($person_data, $supplier_data, $supplier_id)) {
// New supplier
if ($supplier_id == NEW_ENTRY) {
if ($supplier_id === NEW_ENTRY) {
echo json_encode([
'success' => true,
'message' => lang('Suppliers.successful_adding') . ' ' . $supplier_data['company_name'],
'id' => $supplier_data['person_id']
'id' => $supplier_data['person_id'],
]);
} else { // Existing supplier
echo json_encode([
'success' => true,
'message' => lang('Suppliers.successful_updating') . ' ' . $supplier_data['company_name'],
'id' => $supplier_id
'id' => $supplier_id,
]);
}
} else { // Failure
echo json_encode([
'success' => false,
'message' => lang('Suppliers.error_adding_updating') . ' ' . $supplier_data['company_name'],
'id' => NEW_ENTRY
'message' => lang('Suppliers.error_adding_updating') . ' ' . $supplier_data['company_name'],
'id' => NEW_ENTRY,
]);
}
}
/**
* This deletes suppliers from the suppliers table
*
* @return void
*/
public function postDelete(): void
{
@@ -181,7 +165,7 @@ class Suppliers extends Persons
if ($this->supplier->delete_list($suppliers_to_delete)) {
echo json_encode([
'success' => true,
'message' => lang('Suppliers.successful_deleted') . ' ' . count($suppliers_to_delete) . ' ' . lang('Suppliers.one_or_multiple')
'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')]);

View File

@@ -3,10 +3,9 @@
namespace App\Controllers;
use App\Models\Tax_category;
use Config\Services;
/**
* @property tax_category tax_category
* @property Tax_category tax_category
*/
class Tax_categories extends Secure_Controller
{
@@ -19,9 +18,6 @@ class Tax_categories extends Secure_Controller
$this->tax_category = model(Tax_category::class);
}
/**
* @return void
*/
public function getIndex(): void
{
$data['tax_categories_table_headers'] = get_tax_categories_table_headers();
@@ -31,8 +27,6 @@ class Tax_categories extends Secure_Controller
/**
* Returns tax_category table data rows. This will be called with AJAX.
*
* @return void
*/
public function getSearch(): void
{
@@ -43,9 +37,10 @@ class Tax_categories extends Secure_Controller
$order = $this->request->getGet('order', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$tax_categories = $this->tax_category->search($search, $limit, $offset, $sort, $order);
$total_rows = $this->tax_category->get_found_rows($search);
$total_rows = $this->tax_category->get_found_rows($search);
$data_rows = [];
foreach ($tax_categories->getResult() as $tax_category) {
$data_rows[] = get_tax_categories_data_row($tax_category);
}
@@ -53,10 +48,6 @@ class Tax_categories extends Secure_Controller
echo json_encode(['total' => $total_rows, 'rows' => $data_rows]);
}
/**
* @param $row_id
* @return void
*/
public function getRow($row_id): void
{
$data_row = get_tax_categories_data_row($this->tax_category->get_info($row_id));
@@ -64,57 +55,45 @@ class Tax_categories extends Secure_Controller
echo json_encode($data_row);
}
/**
* @param int $tax_category_id
* @return void
*/
public function getView(int $tax_category_id = NEW_ENTRY): void
{
$data['tax_category_info'] = $this->tax_category->get_info($tax_category_id);
echo view("taxes/tax_category_form", $data);
echo view('taxes/tax_category_form', $data);
}
/**
* @param int $tax_category_id
* @return void
*/
public function postSave(int $tax_category_id = NEW_ENTRY): void
{
$tax_category_data = [
'tax_category' => $this->request->getPost('tax_category', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
'tax_category_code' => $this->request->getPost('tax_category_code', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
'tax_group_sequence' => $this->request->getPost('tax_group_sequence', FILTER_SANITIZE_NUMBER_INT)
'tax_group_sequence' => $this->request->getPost('tax_group_sequence', FILTER_SANITIZE_NUMBER_INT),
];
if ($this->tax_category->save_value($tax_category_data, $tax_category_id)) {
// New tax_category_id
if ($tax_category_id == NEW_ENTRY) {
if ($tax_category_id === NEW_ENTRY) {
echo json_encode([
'success' => true,
'message' => lang('Tax_categories.successful_adding'),
'id' => $tax_category_data['tax_category_id']
'id' => $tax_category_data['tax_category_id'],
]);
} else {
echo json_encode([
'success' => true,
'message' => lang('Tax_categories.successful_updating'),
'id' => $tax_category_id
'id' => $tax_category_id,
]);
}
} else {
echo json_encode([
'success' => false,
'message' => lang('Tax_categories.error_adding_updating') . ' ' . $tax_category_data['tax_category'],
'id' => NEW_ENTRY
'id' => NEW_ENTRY,
]);
}
}
/**
* @return void
*/
public function postDelete(): void
{
$tax_categories_to_delete = $this->request->getPost('ids', FILTER_SANITIZE_NUMBER_INT);
@@ -122,7 +101,7 @@ class Tax_categories extends Secure_Controller
if ($this->tax_category->delete_list($tax_categories_to_delete)) {
echo json_encode([
'success' => true,
'message' => lang('Tax_categories.successful_deleted') . ' ' . count($tax_categories_to_delete) . ' ' . lang('Tax_categories.one_or_multiple')
'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')]);

View File

@@ -3,10 +3,9 @@
namespace App\Controllers;
use App\Models\Tax_code;
use Config\Services;
/**
* @property tax_code tax_code
* @property Tax_code tax_code
*/
class Tax_codes extends Secure_Controller
{
@@ -20,29 +19,20 @@ class Tax_codes extends Secure_Controller
helper('tax_helper');
}
/**
* @return void
*/
public function getIndex(): void
{
echo view('taxes/tax_codes', $this->get_data());
}
/**
* @return array
*/
public function get_data(): array
{
$data['table_headers'] = get_tax_code_table_headers();
return $data;
}
/**
* Returns tax_category table data rows. This will be called with AJAX.
*
* @return void
*/
public function getSearch(): void
{
@@ -52,7 +42,7 @@ class Tax_codes extends Secure_Controller
$sort = $this->request->getGet('sort', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$order = $this->request->getGet('order', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$tax_codes = $this->tax_code->search($search, $limit, $offset, $sort, $order);
$tax_codes = $this->tax_code->search($search, $limit, $offset, $sort, $order);
$total_rows = $this->tax_code->get_found_rows($search);
$data_rows = [];
@@ -64,10 +54,6 @@ class Tax_codes extends Secure_Controller
echo json_encode(['total' => $total_rows, 'rows' => $data_rows]);
}
/**
* @param int $row_id
* @return void
*/
public function getRow(int $row_id): void
{
$data_row = get_tax_code_data_row($this->tax_code->get_info($row_id));
@@ -75,57 +61,45 @@ class Tax_codes extends Secure_Controller
echo json_encode($data_row);
}
/**
* @param int $tax_code_id
* @return void
*/
public function getView(int $tax_code_id = NEW_ENTRY): void
{
$data['tax_code_info'] = $this->tax_code->get_info($tax_code_id);
echo view("taxes/tax_code_form", $data);
echo view('taxes/tax_code_form', $data);
}
/**
* @param int $tax_code_id
* @return void
*/
public function postSave(int $tax_code_id = NEW_ENTRY): void
{
$tax_code_data = [
'tax_code' => $this->request->getPost('tax_code', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
'tax_code_name' => $this->request->getPost('tax_code_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
'city' => $this->request->getPost('city', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
'state' => $this->request->getPost('state', FILTER_SANITIZE_FULL_SPECIAL_CHARS)
'state' => $this->request->getPost('state', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
];
if ($this->tax_code->save($tax_code_data)) {
if ($tax_code_id == NEW_ENTRY) {
if ($tax_code_id === NEW_ENTRY) {
echo json_encode([
'success' => true,
'message' => lang('Tax_codes.successful_adding'),
'id' => $tax_code_data['tax_code_id']
'id' => $tax_code_data['tax_code_id'],
]);
} else {
echo json_encode([
'success' => true,
'message' => lang('Tax_codes.successful_updating'),
'id' => $tax_code_id
'id' => $tax_code_id,
]);
}
} else {
echo json_encode([
'success' => false,
'message' => lang('Tax_codes.error_adding_updating') . ' ' . $tax_code_data['tax_code_id'],
'id' => NEW_ENTRY
'id' => NEW_ENTRY,
]);
}
}
/**
* @return void
*/
public function postDelete(): void
{
$tax_codes_to_delete = $this->request->getPost('ids', FILTER_SANITIZE_NUMBER_INT);
@@ -133,7 +107,7 @@ class Tax_codes extends Secure_Controller
if ($this->tax_code->delete_list($tax_codes_to_delete)) {
echo json_encode([
'success' => true,
'message' => lang('Tax_codes.successful_deleted') . ' ' . count($tax_codes_to_delete) . ' ' . lang('Tax_codes.one_or_multiple')
'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')]);

View File

@@ -3,10 +3,9 @@
namespace App\Controllers;
use App\Models\Tax_jurisdiction;
use Config\Services;
/**
* @property tax_jurisdiction tax_jurisdiction
* @property Tax_jurisdiction tax_jurisdiction
*/
class Tax_jurisdictions extends Secure_Controller
{
@@ -21,10 +20,6 @@ class Tax_jurisdictions extends Secure_Controller
helper('tax_helper');
}
/**
* @return void
*/
public function getIndex(): void
{
$data['table_headers'] = get_tax_jurisdictions_table_headers();
@@ -34,8 +29,6 @@ class Tax_jurisdictions extends Secure_Controller
/**
* Returns tax_category table data rows. This will be called with AJAX.
*
* @return void
*/
public function getSearch(): void
{
@@ -46,9 +39,10 @@ class Tax_jurisdictions extends Secure_Controller
$order = $this->request->getGet('order', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$tax_jurisdictions = $this->tax_jurisdiction->search($search, $limit, $offset, $sort, $order);
$total_rows = $this->tax_jurisdiction->get_found_rows($search);
$total_rows = $this->tax_jurisdiction->get_found_rows($search);
$data_rows = [];
foreach ($tax_jurisdictions->getResult() as $tax_jurisdiction) {
$data_rows[] = get_tax_jurisdictions_data_row($tax_jurisdiction);
}
@@ -56,10 +50,6 @@ class Tax_jurisdictions extends Secure_Controller
echo json_encode(['total' => $total_rows, 'rows' => $data_rows]);
}
/**
* @param int $row_id
* @return void
*/
public function getRow(int $row_id): void
{
$data_row = get_tax_jurisdictions_data_row($this->tax_jurisdiction->get_info($row_id));
@@ -67,55 +57,43 @@ class Tax_jurisdictions extends Secure_Controller
echo json_encode($data_row);
}
/**
* @param int $tax_jurisdiction_id
* @return void
*/
public function getView(int $tax_jurisdiction_id = NEW_ENTRY): void
{
$data['tax_jurisdiction_info'] = $this->tax_jurisdiction->get_info($tax_jurisdiction_id);
echo view("taxes/tax_jurisdiction_form", $data);
echo view('taxes/tax_jurisdiction_form', $data);
}
/**
* @param int $jurisdiction_id
* @return void
*/
public function postSave(int $jurisdiction_id = NEW_ENTRY): void
{
$tax_jurisdiction_data = [
'jurisdiction_name' => $this->request->getPost('jurisdiction_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
'reporting_authority' => $this->request->getPost('reporting_authority', FILTER_SANITIZE_FULL_SPECIAL_CHARS)
'reporting_authority' => $this->request->getPost('reporting_authority', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
];
if ($this->tax_jurisdiction->save_value($tax_jurisdiction_data)) {
if ($jurisdiction_id == NEW_ENTRY) {
if ($jurisdiction_id === NEW_ENTRY) {
echo json_encode([
'success' => true,
'message' => lang('Tax_jurisdictions.successful_adding'),
'id' => $tax_jurisdiction_data['jurisdiction_id']
'id' => $tax_jurisdiction_data['jurisdiction_id'],
]);
} else {
echo json_encode([
'success' => true,
'message' => lang('Tax_jurisdictions.successful_updating'),
'id' => $jurisdiction_id
'id' => $jurisdiction_id,
]);
}
} else {
echo json_encode([
'success' => false,
'message' => lang('Tax_jurisdictions.error_adding_updating') . ' ' . $tax_jurisdiction_data['jurisdiction_name'],
'id' => NEW_ENTRY
'id' => NEW_ENTRY,
]);
}
}
/**
* @return void
*/
public function postDelete(): void
{
$tax_jurisdictions_to_delete = $this->request->getPost('ids', FILTER_SANITIZE_NUMBER_INT);
@@ -123,7 +101,7 @@ class Tax_jurisdictions extends Secure_Controller
if ($this->tax_jurisdiction->delete_list($tax_jurisdictions_to_delete)) {
echo json_encode([
'success' => true,
'message' => lang('Tax_jurisdictions.successful_deleted') . ' ' . count($tax_jurisdictions_to_delete) . ' ' . lang('Tax_jurisdictions.one_or_multiple')
'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')]);

View File

@@ -3,13 +3,12 @@
namespace App\Controllers;
use App\Libraries\Tax_lib;
use App\Models\Enums\Rounding_mode;
use App\Models\enums\Rounding_mode;
use App\Models\Tax;
use App\Models\Tax_category;
use App\Models\Tax_code;
use App\Models\Tax_jurisdiction;
use Config\OSPOS;
use Config\Services;
class Taxes extends Secure_Controller
{
@@ -24,40 +23,37 @@ class Taxes extends Secure_Controller
{
parent::__construct('taxes');
$this->tax = model(Tax::class);
$this->tax_category = model(Tax_category::class);
$this->tax_code = model(Tax_code::class);
$this->tax = model(Tax::class);
$this->tax_category = model(Tax_category::class);
$this->tax_code = model(Tax_code::class);
$this->tax_jurisdiction = model(Tax_jurisdiction::class);
$this->tax_lib = new Tax_lib();
$this->config = config(OSPOS::class)->settings;
$this->config = config(OSPOS::class)->settings;
helper('tax_helper');
}
/**
* @return void
*/
public function getIndex(): void
{
$data['tax_codes'] = $this->tax_code->get_all()->getResultArray();
if (count($data['tax_codes']) == 0) {
if (count($data['tax_codes']) === 0) {
$data['tax_codes'] = $this->tax_code->get_empty_row();
}
$data['tax_categories'] = $this->tax_category->get_all()->getResultArray();
if (count($data['tax_categories']) == 0) {
if (count($data['tax_categories']) === 0) {
$data['tax_categories'] = $this->tax_category->get_empty_row();
}
$data['tax_jurisdictions'] = $this->tax_jurisdiction->get_all()->getResultArray();
if (count($data['tax_jurisdictions']) == 0) {
if (count($data['tax_jurisdictions']) === 0) {
$data['tax_jurisdictions'] = $this->tax_jurisdiction->get_empty_row();
}
$data['tax_rate_table_headers'] = get_tax_rates_manage_table_headers();
$data['tax_rate_table_headers'] = get_tax_rates_manage_table_headers();
$data['tax_categories_table_headers'] = get_tax_categories_table_headers();
$data['tax_types'] = $this->tax_lib->get_tax_types();
$data['tax_types'] = $this->tax_lib->get_tax_types();
if ($this->config['tax_included']) {
$data['default_tax_type'] = Tax_lib::TAX_TYPE_INCLUDED;
@@ -72,22 +68,21 @@ class Taxes extends Secure_Controller
/**
* Returns tax_codes table data rows. This will be called with AJAX.
*
* @return void
*/
public function getSearch(): void
{
$search = $this->request->getGet('search');
$limit = $this->request->getGet('limit', FILTER_SANITIZE_NUMBER_INT);
$limit = $this->request->getGet('limit', FILTER_SANITIZE_NUMBER_INT);
$offset = $this->request->getGet('offset', FILTER_SANITIZE_NUMBER_INT);
$sort = $this->request->getGet('sort', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$order = $this->request->getGet('order', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$sort = $this->request->getGet('sort', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$order = $this->request->getGet('order', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$tax_rates = $this->tax->search($search, $limit, $offset, $sort, $order);
$total_rows = $this->tax->get_found_rows($search);
$data_rows = [];
foreach ($tax_rates->getResult() as $tax_rate_row) {
$data_rows[] = get_tax_rates_data_row($tax_rate_row);
}
@@ -100,7 +95,7 @@ class Taxes extends Secure_Controller
*/
public function suggest_search(): void
{
$search = $this->request->getPost('term');
$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);
@@ -108,22 +103,15 @@ class Taxes extends Secure_Controller
/**
* Provides list of tax categories to select from
*
* @return void
*/
public function suggest_tax_categories(): void
{
$search = $this->request->getPost('term');
$search = $this->request->getPost('term');
$suggestions = $this->tax_category->get_tax_category_suggestions($search);
echo json_encode($suggestions);
}
/**
* @param int $row_id
* @return void
*/
public function getRow(int $row_id): void
{
$data_row = get_tax_rates_data_row($this->tax->get_info($row_id));
@@ -131,16 +119,12 @@ class Taxes extends Secure_Controller
echo json_encode($data_row);
}
/**
* @param int $tax_code
* @return void
*/
public function getView_tax_codes(int $tax_code = NEW_ENTRY): void
{
$tax_code_info = $this->tax->get_info($tax_code);
$default_tax_category_id = 1; // Tax category id is always the default tax category // TODO: Replace 1 with constant
$default_tax_category = $this->tax->get_tax_category($default_tax_category_id); // TODO: this variable is never used in the code.
$default_tax_category = $this->tax->get_tax_category($default_tax_category_id); // TODO: this variable is never used in the code.
$tax_rate_info = $this->tax->get_rate_info($tax_code, $default_tax_category_id);
@@ -150,42 +134,43 @@ class Taxes extends Secure_Controller
$data['default_tax_type'] = Tax_lib::TAX_TYPE_EXCLUDED;
}
$data['rounding_options'] = Rounding_mode::get_rounding_options();
$data['rounding_options'] = Rounding_mode::get_rounding_options();
$data['html_rounding_options'] = $this->get_html_rounding_options();
if ($tax_code == NEW_ENTRY) { // TODO: Duplicated code
$data['tax_code'] = '';
$data['tax_code_name'] = '';
$data['tax_code_type'] = '0';
$data['city'] = '';
$data['state'] = '';
$data['tax_rate'] = '0.0000';
$data['rate_tax_code'] = '';
if ($tax_code === NEW_ENTRY) { // TODO: Duplicated code
$data['tax_code'] = '';
$data['tax_code_name'] = '';
$data['tax_code_type'] = '0';
$data['city'] = '';
$data['state'] = '';
$data['tax_rate'] = '0.0000';
$data['rate_tax_code'] = '';
$data['rate_tax_category_id'] = 1;
$data['tax_category'] = '';
$data['add_tax_category'] = '';
$data['rounding_code'] = '0';
$data['tax_category'] = '';
$data['add_tax_category'] = '';
$data['rounding_code'] = '0';
} else {
$data['tax_code'] = $tax_code;
$data['tax_code_name'] = $tax_code_info->tax_code_name;
$data['tax_code_type'] = $tax_code_info->tax_code_type;
$data['city'] = $tax_code_info->city;
$data['state'] = $tax_code_info->state;
$data['rate_tax_code'] = $tax_code_info->rate_tax_code;
$data['tax_code'] = $tax_code;
$data['tax_code_name'] = $tax_code_info->tax_code_name;
$data['tax_code_type'] = $tax_code_info->tax_code_type;
$data['city'] = $tax_code_info->city;
$data['state'] = $tax_code_info->state;
$data['rate_tax_code'] = $tax_code_info->rate_tax_code;
$data['rate_tax_category_id'] = $tax_code_info->rate_tax_category_id;
$data['tax_category'] = $tax_code_info->tax_category;
$data['add_tax_category'] = '';
$data['tax_rate'] = $tax_rate_info->tax_rate;
$data['rounding_code'] = $tax_rate_info->rounding_code;
$data['tax_category'] = $tax_code_info->tax_category;
$data['add_tax_category'] = '';
$data['tax_rate'] = $tax_rate_info->tax_rate;
$data['rounding_code'] = $tax_rate_info->rounding_code;
}
$tax_rates = [];
foreach ($this->tax->get_tax_code_rate_exceptions($tax_code) as $tax_code_rate) { // TODO: get_tax_code_rate_exceptions doesn't exist. This was deleted by @steveireland in https://github.com/opensourcepos/opensourcepos/commit/32204698379c230f2a6756655f40334308023de9#diff-e746bab6720cf5dbf855de6cda68f7aca9ecea7ddd5a39bb852e9b9047a7a838L435 but it's unclear if that was on purpose or accidental.
$tax_rate_row = [];
$tax_rate_row = [];
$tax_rate_row['rate_tax_category_id'] = $tax_code_rate['rate_tax_category_id'];
$tax_rate_row['tax_category'] = $tax_code_rate['tax_category'];
$tax_rate_row['tax_rate'] = $tax_code_rate['tax_rate'];
$tax_rate_row['rounding_code'] = $tax_code_rate['rounding_code'];
$tax_rate_row['tax_category'] = $tax_code_rate['tax_category'];
$tax_rate_row['tax_rate'] = $tax_code_rate['tax_rate'];
$tax_rate_row['rounding_code'] = $tax_code_rate['rounding_code'];
$tax_rates[] = $tax_rate_row;
}
@@ -195,54 +180,45 @@ class Taxes extends Secure_Controller
echo view('taxes/tax_code_form', $data);
}
/**
* @param int $tax_rate_id
* @return void
*/
public function getView(int $tax_rate_id = NEW_ENTRY): void
{
$tax_rate_info = $this->tax->get_info($tax_rate_id);
$data['tax_rate_id'] = $tax_rate_id;
$data['tax_rate_id'] = $tax_rate_id;
$data['rounding_options'] = Rounding_mode::get_rounding_options();
$data['tax_code_options'] = $this->tax_lib->get_tax_code_options();
$data['tax_category_options'] = $this->tax_lib->get_tax_category_options();
$data['tax_code_options'] = $this->tax_lib->get_tax_code_options();
$data['tax_category_options'] = $this->tax_lib->get_tax_category_options();
$data['tax_jurisdiction_options'] = $this->tax_lib->get_tax_jurisdiction_options();
if ($tax_rate_id == NEW_ENTRY) {
$data['rate_tax_code_id'] = $this->config['default_tax_code'];
if ($tax_rate_id === NEW_ENTRY) {
$data['rate_tax_code_id'] = $this->config['default_tax_code'];
$data['rate_tax_category_id'] = $this->config['default_tax_category'];
$data['rate_jurisdiction_id'] = $this->config['default_tax_jurisdiction'];
$data['tax_rounding_code'] = Rounding_mode::HALF_UP;
$data['tax_rate'] = '0.0000';
$data['tax_rounding_code'] = Rounding_mode::HALF_UP;
$data['tax_rate'] = '0.0000';
} else {
$data['rate_tax_code_id'] = $tax_rate_info->rate_tax_code_id;
$data['rate_tax_code'] = $tax_rate_info->tax_code;
$data['rate_tax_code_id'] = $tax_rate_info->rate_tax_code_id;
$data['rate_tax_code'] = $tax_rate_info->tax_code;
$data['rate_tax_category_id'] = $tax_rate_info->rate_tax_category_id;
$data['rate_jurisdiction_id'] = $tax_rate_info->rate_jurisdiction_id;
$data['tax_rounding_code'] = $tax_rate_info->tax_rounding_code;
$data['tax_rate'] = $tax_rate_info->tax_rate;
$data['tax_rounding_code'] = $tax_rate_info->tax_rounding_code;
$data['tax_rate'] = $tax_rate_info->tax_rate;
}
echo view('taxes/tax_rates_form', $data);
}
/**
* @param int $tax_code
* @return void
*/
public function getView_tax_categories(int $tax_code = NEW_ENTRY): void // TODO: This appears to be called no where in the code.
{
$tax_code_info = $this->tax->get_info($tax_code); // TODO: Duplicated Code
$default_tax_category_id = 1; // Tax category id is always the default tax category // TODO: replace with a constant.
$default_tax_category = $this->tax->get_tax_category($default_tax_category_id);
$default_tax_category = $this->tax->get_tax_category($default_tax_category_id);
$tax_rate_info = $this->tax->get_rate_info($tax_code, $default_tax_category_id);
$data['rounding_options'] = Rounding_mode::get_rounding_options();
$data['rounding_options'] = Rounding_mode::get_rounding_options();
$data['html_rounding_options'] = $this->get_html_rounding_options();
if ($this->config['tax_included']) {
@@ -251,39 +227,40 @@ class Taxes extends Secure_Controller
$data['default_tax_type'] = Tax_lib::TAX_TYPE_EXCLUDED;
}
if ($tax_code == NEW_ENTRY) {
$data['tax_code'] = '';
$data['tax_code_name'] = '';
$data['tax_code_type'] = '0';
$data['city'] = '';
$data['state'] = '';
$data['tax_rate'] = '0.0000';
$data['rate_tax_code'] = '';
if ($tax_code === NEW_ENTRY) {
$data['tax_code'] = '';
$data['tax_code_name'] = '';
$data['tax_code_type'] = '0';
$data['city'] = '';
$data['state'] = '';
$data['tax_rate'] = '0.0000';
$data['rate_tax_code'] = '';
$data['rate_tax_category_id'] = 1;
$data['tax_category'] = '';
$data['add_tax_category'] = '';
$data['rounding_code'] = '0';
$data['tax_category'] = '';
$data['add_tax_category'] = '';
$data['rounding_code'] = '0';
} else {
$data['tax_code'] = $tax_code;
$data['tax_code_name'] = $tax_code_info->tax_code_name;
$data['tax_code_type'] = $tax_code_info->tax_code_type;
$data['city'] = $tax_code_info->city;
$data['state'] = $tax_code_info->state;
$data['rate_tax_code'] = $tax_code_info->rate_tax_code;
$data['tax_code'] = $tax_code;
$data['tax_code_name'] = $tax_code_info->tax_code_name;
$data['tax_code_type'] = $tax_code_info->tax_code_type;
$data['city'] = $tax_code_info->city;
$data['state'] = $tax_code_info->state;
$data['rate_tax_code'] = $tax_code_info->rate_tax_code;
$data['rate_tax_category_id'] = $tax_code_info->rate_tax_category_id;
$data['tax_category'] = $tax_code_info->tax_category;
$data['add_tax_category'] = '';
$data['tax_rate'] = $tax_rate_info->tax_rate;
$data['rounding_code'] = $tax_rate_info->rounding_code;
$data['tax_category'] = $tax_code_info->tax_category;
$data['add_tax_category'] = '';
$data['tax_rate'] = $tax_rate_info->tax_rate;
$data['rounding_code'] = $tax_rate_info->rounding_code;
}
$tax_rates = [];
foreach ($this->tax->get_tax_code_rate_exceptions($tax_code) as $tax_code_rate) { // TODO: get_tax_code_rate_exceptions doesn't exist in the tax model
$tax_rate_row = [];
$tax_rate_row = [];
$tax_rate_row['rate_tax_category_id'] = $tax_code_rate['rate_tax_category_id'];
$tax_rate_row['tax_category'] = $tax_code_rate['tax_category'];
$tax_rate_row['tax_rate'] = $tax_code_rate['tax_rate'];
$tax_rate_row['rounding_code'] = $tax_code_rate['rounding_code'];
$tax_rate_row['tax_category'] = $tax_code_rate['tax_category'];
$tax_rate_row['tax_rate'] = $tax_code_rate['tax_rate'];
$tax_rate_row['rounding_code'] = $tax_code_rate['rounding_code'];
$tax_rates[] = $tax_rate_row;
}
@@ -293,20 +270,16 @@ class Taxes extends Secure_Controller
echo view('taxes/tax_category_form', $data);
}
/**
* @param int $tax_code
* @return void
*/
public function getView_tax_jurisdictions(int $tax_code = NEW_ENTRY): void // TODO: This appears to be called no where in the code.
{
$tax_code_info = $this->tax->get_info($tax_code); // TODO: Duplicated code
$default_tax_category_id = 1; // Tax category id is always the default tax category
$default_tax_category = $this->tax->get_tax_category($default_tax_category_id); // TODO: This variable is not used anywhere in the code
$default_tax_category = $this->tax->get_tax_category($default_tax_category_id); // TODO: This variable is not used anywhere in the code
$tax_rate_info = $this->tax->get_rate_info($tax_code, $default_tax_category_id);
$data['rounding_options'] = Rounding_mode::get_rounding_options();
$data['rounding_options'] = Rounding_mode::get_rounding_options();
$data['html_rounding_options'] = $this->get_html_rounding_options();
if ($this->config['tax_included']) {
@@ -315,39 +288,40 @@ class Taxes extends Secure_Controller
$data['default_tax_type'] = Tax_lib::TAX_TYPE_EXCLUDED;
}
if ($tax_code == NEW_ENTRY) {
$data['tax_code'] = '';
$data['tax_code_name'] = '';
$data['tax_code_type'] = '0';
$data['city'] = '';
$data['state'] = '';
$data['tax_rate'] = '0.0000';
$data['rate_tax_code'] = '';
if ($tax_code === NEW_ENTRY) {
$data['tax_code'] = '';
$data['tax_code_name'] = '';
$data['tax_code_type'] = '0';
$data['city'] = '';
$data['state'] = '';
$data['tax_rate'] = '0.0000';
$data['rate_tax_code'] = '';
$data['rate_tax_category_id'] = 1;
$data['tax_category'] = '';
$data['add_tax_category'] = '';
$data['rounding_code'] = '0';
$data['tax_category'] = '';
$data['add_tax_category'] = '';
$data['rounding_code'] = '0';
} else {
$data['tax_code'] = $tax_code;
$data['tax_code_name'] = $tax_code_info->tax_code_name;
$data['tax_code_type'] = $tax_code_info->tax_code_type;
$data['city'] = $tax_code_info->city;
$data['state'] = $tax_code_info->state;
$data['rate_tax_code'] = $tax_code_info->rate_tax_code;
$data['tax_code'] = $tax_code;
$data['tax_code_name'] = $tax_code_info->tax_code_name;
$data['tax_code_type'] = $tax_code_info->tax_code_type;
$data['city'] = $tax_code_info->city;
$data['state'] = $tax_code_info->state;
$data['rate_tax_code'] = $tax_code_info->rate_tax_code;
$data['rate_tax_category_id'] = $tax_code_info->rate_tax_category_id;
$data['tax_category'] = $tax_code_info->tax_category;
$data['add_tax_category'] = '';
$data['tax_rate'] = $tax_rate_info->tax_rate;
$data['rounding_code'] = $tax_rate_info->rounding_code;
$data['tax_category'] = $tax_code_info->tax_category;
$data['add_tax_category'] = '';
$data['tax_rate'] = $tax_rate_info->tax_rate;
$data['rounding_code'] = $tax_rate_info->rounding_code;
}
$tax_rates = [];
foreach ($this->tax->get_tax_code_rate_exceptions($tax_code) as $tax_code_rate) { // TODO: get_tax_code_rate_exceptions doesn't exist in the tax model
$tax_rate_row = [];
$tax_rate_row = [];
$tax_rate_row['rate_tax_category_id'] = $tax_code_rate['rate_tax_category_id'];
$tax_rate_row['tax_category'] = $tax_code_rate['tax_category'];
$tax_rate_row['tax_rate'] = $tax_code_rate['tax_rate'];
$tax_rate_row['rounding_code'] = $tax_code_rate['rounding_code'];
$tax_rate_row['tax_category'] = $tax_code_rate['tax_category'];
$tax_rate_row['tax_rate'] = $tax_code_rate['tax_rate'];
$tax_rate_row['rounding_code'] = $tax_code_rate['rounding_code'];
$tax_rates[] = $tax_rate_row;
}
@@ -357,24 +331,17 @@ class Taxes extends Secure_Controller
echo view('taxes/tax_jurisdiction_form', $data);
}
/**
* @return string
*/
public static function get_html_rounding_options(): string
{
return Rounding_mode::get_html_rounding_options();
}
/**
* @param int $tax_rate_id
* @return void
*/
public function postSave(int $tax_rate_id = NEW_ENTRY): void
{
$tax_category_id = $this->request->getPost('rate_tax_category_id', FILTER_SANITIZE_NUMBER_INT);
$tax_rate = parse_tax($this->request->getPost('tax_rate'));
$tax_rate = parse_tax($this->request->getPost('tax_rate'));
if ($tax_rate == 0) { // TODO: Replace 0 with constant?
if ($tax_rate === 0) { // TODO: Replace 0 with constant?
$tax_category_info = $this->tax_category->get_info($tax_category_id); // TODO: this variable is not used anywhere in the code
}
@@ -383,11 +350,11 @@ class Taxes extends Secure_Controller
'rate_tax_category_id' => $tax_category_id,
'rate_jurisdiction_id' => $this->request->getPost('rate_jurisdiction_id', FILTER_SANITIZE_NUMBER_INT),
'tax_rate' => $tax_rate,
'tax_rounding_code' => $this->request->getPost('tax_rounding_code', FILTER_SANITIZE_NUMBER_INT)
'tax_rounding_code' => $this->request->getPost('tax_rounding_code', FILTER_SANITIZE_NUMBER_INT),
];
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
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')]);
} else { // Existing tax_code
echo json_encode(['success' => true, 'message' => lang('Taxes.tax_rate_successful_updated')]);
@@ -397,9 +364,6 @@ class Taxes extends Secure_Controller
}
}
/**
* @return void
*/
public function postDelete(): void
{
$tax_codes_to_delete = $this->request->getPost('ids', FILTER_SANITIZE_NUMBER_INT);
@@ -414,12 +378,11 @@ class Taxes extends Secure_Controller
/**
* Get search suggestions for tax codes. Used in app/Views/customers/form.php
*
* @return void
* @noinspection PhpUnused
*/
public function getSuggestTaxCodes(): void
{
$search = $this->request->getPostGet('term');
$search = $this->request->getPostGet('term');
$suggestions = $this->tax_code->get_tax_codes_search_suggestions($search);
echo json_encode($suggestions);
@@ -428,25 +391,25 @@ class Taxes extends Secure_Controller
/**
* Saves Tax Codes. Used in app/Views/taxes/tax_codes.php
*
* @return void
* @noinspection PhpUnused
*/
public function postSave_tax_codes(): void
public function save_tax_codes(): void
{
$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);
$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);
$tax_code_name = $this->request->getPost('tax_code_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$city = $this->request->getPost('city', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$state = $this->request->getPost('state', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$city = $this->request->getPost('city', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$state = $this->request->getPost('state', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$array_save = []; // TODO: the naming of this variable is not good.
foreach ($tax_code_id as $key => $val) {
$array_save[] = [
'tax_code_id' => $val,
'tax_code' => $tax_code[$key],
'tax_code_name' => $tax_code_name[$key],
'city' => $city[$key],
'state' => $state[$key]
'state' => $state[$key],
];
}
@@ -454,27 +417,26 @@ class Taxes extends Secure_Controller
echo json_encode([
'success' => $success,
'message' => lang('Taxes.tax_codes_saved_' . ($success ? '' : 'un') . 'successfully')
'message' => lang('Taxes.tax_codes_saved_' . ($success ? '' : 'un') . 'successfully'),
]);
}
/**
* Saves given tax jurisdiction. Used in app/Views/taxes/tax_jurisdictions.php.
*
* @return void
* @noinspection PhpUnused
*/
public function postSave_tax_jurisdictions(): void
public function save_tax_jurisdictions(): void
{
$jurisdiction_id = $this->request->getPost('jurisdiction_id', FILTER_SANITIZE_NUMBER_INT);
$jurisdiction_name = $this->request->getPost('jurisdiction_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$tax_group = $this->request->getPost('tax_group', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$tax_type = $this->request->getPost('tax_type', FILTER_SANITIZE_NUMBER_INT);
$jurisdiction_id = $this->request->getPost('jurisdiction_id', FILTER_SANITIZE_NUMBER_INT);
$jurisdiction_name = $this->request->getPost('jurisdiction_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$tax_group = $this->request->getPost('tax_group', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$tax_type = $this->request->getPost('tax_type', FILTER_SANITIZE_NUMBER_INT);
$reporting_authority = $this->request->getPost('reporting_authority', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$tax_group_sequence = $this->request->getPost('tax_group_sequence', FILTER_SANITIZE_NUMBER_INT);
$cascade_sequence = $this->request->getPost('cascade_sequence', FILTER_SANITIZE_NUMBER_INT);
$tax_group_sequence = $this->request->getPost('tax_group_sequence', FILTER_SANITIZE_NUMBER_INT);
$cascade_sequence = $this->request->getPost('cascade_sequence', FILTER_SANITIZE_NUMBER_INT);
$array_save = [];
$array_save = [];
$unique_tax_groups = [];
foreach ($jurisdiction_id as $key => $val) {
@@ -485,38 +447,37 @@ class Taxes extends Secure_Controller
'tax_type' => $tax_type[$key],
'reporting_authority' => $reporting_authority[$key],
'tax_group_sequence' => $tax_group_sequence[$key],
'cascade_sequence' => $cascade_sequence[$key]
'cascade_sequence' => $cascade_sequence[$key],
];
if (in_array($tax_group[$key], $unique_tax_groups)) { // TODO: This can be replaced with `in_array($tax_group[$key], $unique_tax_groups)`
if (in_array($tax_group[$key], $unique_tax_groups, true)) { // TODO: This can be replaced with `in_array($tax_group[$key], $unique_tax_groups)`
echo json_encode([
'success' => false,
'message' => lang('Taxes.tax_group_not_unique', [$tax_group[$key]])
'message' => lang('Taxes.tax_group_not_unique', [$tax_group[$key]]),
]);
return;
} else {
$unique_tax_groups[] = $tax_group[$key];
}
$unique_tax_groups[] = $tax_group[$key];
}
$success = $this->tax_jurisdiction->save_jurisdictions($array_save);
echo json_encode([
'success' => $success,
'message' => lang('Taxes.tax_jurisdictions_saved_' . ($success ? '' : 'un') . 'successfully')
'message' => lang('Taxes.tax_jurisdictions_saved_' . ($success ? '' : 'un') . 'successfully'),
]);
}
/**
* Saves tax categories. Used in app/Views/taxes/tax_categories.php
*
* @return void
* @noinspection PhpUnused
*/
public function postSave_tax_categories(): void
public function save_tax_categories(): void
{
$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);
$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);
$tax_group_sequence = $this->request->getPost('tax_group_sequence', FILTER_SANITIZE_NUMBER_INT);
$array_save = [];
@@ -525,7 +486,7 @@ class Taxes extends Secure_Controller
$array_save[] = [
'tax_category_id' => $val,
'tax_category' => $tax_category[$key],
'tax_group_sequence' => $tax_group_sequence[$key]
'tax_group_sequence' => $tax_group_sequence[$key],
];
}
@@ -533,17 +494,16 @@ class Taxes extends Secure_Controller
echo json_encode([
'success' => $success,
'message' => lang('Taxes.tax_categories_saved_' . ($success ? '' : 'un') . 'successfully')
'message' => lang('Taxes.tax_categories_saved_' . ($success ? '' : 'un') . 'successfully'),
]);
}
/**
* Gets tax codes partial view. Used in app/Views/taxes/tax_codes.php.
*
* @return void
* @noinspection PhpUnused
*/
public function getAjax_tax_codes(): void
public function ajax_tax_codes(): void
{
$tax_codes = $this->tax_code->get_all()->getResultArray();
@@ -553,10 +513,9 @@ class Taxes extends Secure_Controller
/**
* Gets current tax categories. Used in app/Views/taxes/tax_categories.php
*
* @return void
* @noinspection PhpUnused
*/
public function getAjax_tax_categories(): void
public function ajax_tax_categories(): void
{
$tax_categories = $this->tax_category->get_all()->getResultArray();
@@ -566,10 +525,9 @@ class Taxes extends Secure_Controller
/**
* Gets the tax jurisdiction partial view. Used in app/Views/taxes/tax_jurisdictions.php.
*
* @return void
* @noinspection PhpUnused
*/
public function getAjax_tax_jurisdictions(): void
public function ajax_tax_jurisdictions(): void
{
$tax_jurisdictions = $this->tax_jurisdiction->get_all()->getResultArray();
@@ -584,7 +542,7 @@ class Taxes extends Secure_Controller
echo view('partial/tax_jurisdictions', [
'tax_jurisdictions' => $tax_jurisdictions,
'tax_types' => $tax_types,
'default_tax_type' => $default_tax_type
'default_tax_type' => $default_tax_type,
]);
}
}

View File

@@ -23,5 +23,7 @@ class Migration_Upgrade_To_3_1_1 extends Migration
/**
* Revert a migration step.
*/
public function down(): void {}
public function down(): void
{
}
}

View File

@@ -8,17 +8,18 @@ use CodeIgniter\Database\Migration;
use CodeIgniter\Database\ResultInterface;
/**
* @property tax_lib tax_lib
* @property appconfig appconfig
* @property Appconfig appconfig
* @property Tax_lib tax_lib
*/
class Migration_Sales_Tax_Data extends Migration
{
public const ROUND_UP = 5; // TODO: These need to be moved to constants.php
public const ROUND_UP = 5; // TODO: These need to be moved to constants.php
public const ROUND_DOWN = 6;
public const HALF_FIVE = 7;
public const YES = '1';
public const VAT_TAX = '0';
public const SALES_TAX = '1';
public const HALF_FIVE = 7;
public const YES = '1';
public const VAT_TAX = '0';
public const SALES_TAX = '1';
private Appconfig $appconfig;
public function __construct()
@@ -34,7 +35,7 @@ class Migration_Sales_Tax_Data extends Migration
public function up(): void
{
$number_of_unmigrated = $this->get_count_of_unmigrated();
log_message('info', "Migrating sales tax history. The number of sales that will be migrated is $number_of_unmigrated");
error_log("Migrating sales tax history. The number of sales that will be migrated is {$number_of_unmigrated}");
if ($number_of_unmigrated > 0) {
$unmigrated_invoices = $this->get_unmigrated($number_of_unmigrated)->getResultArray();
@@ -44,22 +45,20 @@ class Migration_Sales_Tax_Data extends Migration
}
}
log_message('info', 'Migrating sales tax history. The number of sales that will be migrated is finished.');
error_log('Migrating sales tax history. The number of sales that will be migrated is finished.');
}
/**
* Revert a migration step.
*/
public function down(): void {}
public function down(): void
{
}
/**
* @param int $sale_id
* @return void
*/
private function upgrade_tax_history_for_sale(int $sale_id): void
{
$tax_decimals = $this->appconfig->get_value('tax_decimals', 2);
$tax_included = $this->appconfig->get_value('tax_included', Migration_Sales_Tax_Data::YES) == Migration_Sales_Tax_Data::YES;
$tax_decimals = $this->appconfig->get_value('tax_decimals', 2);
$tax_included = $this->appconfig->get_value('tax_included', Migration_Sales_Tax_Data::YES) === Migration_Sales_Tax_Data::YES;
$customer_sales_tax_support = false;
if ($tax_included) { // TODO: Convert to ternary notation.
@@ -68,13 +67,13 @@ class Migration_Sales_Tax_Data extends Migration
$tax_type = Migration_Sales_Tax_Data::SALES_TAX;
}
$sales_taxes = [];
$sales_taxes = [];
$tax_group_sequence = 0;
$items = $this->get_sale_items_for_migration($sale_id)->getResultArray();
$items = $this->get_sale_items_for_migration($sale_id)->getResultArray();
foreach ($items as $item) {
// This computes tax for each line item and adds it to the tax type total
$tax_group = (float)$item['percent'] . '% ' . $item['name'];
$tax_group = (float) $item['percent'] . '% ' . $item['name'];
$tax_basis = $this->get_item_total($item['quantity_purchased'], $item['item_unit_price'], $item['discount_percent'], true);
$item_tax_amount = $tax_included
@@ -94,10 +93,6 @@ class Migration_Sales_Tax_Data extends Migration
$this->save_sales_tax($sales_taxes);
}
/**
* @param int $block_count
* @return ResultInterface
*/
private function get_unmigrated(int $block_count): ResultInterface
{
$builder = $this->db->table('sales_items_taxes as SIT');
@@ -113,10 +108,6 @@ class Migration_Sales_Tax_Data extends Migration
return $builder->get();
}
/**
* @param int $sale_id
* @return ResultInterface
*/
private function get_sale_items_for_migration(int $sale_id): ResultInterface
{
$builder = $this->db->table('sales_items as sales_items');
@@ -133,9 +124,6 @@ class Migration_Sales_Tax_Data extends Migration
return $builder->get();
}
/**
* @return int
*/
private function get_count_of_unmigrated(): int
{
$result = $this->db->query('SELECT COUNT(*) FROM(SELECT SIT.sale_id, ST.sale_id as sales_taxes_sale_id FROM '
@@ -145,23 +133,15 @@ class Migration_Sales_Tax_Data extends Migration
. ' as ST ON SIT.sale_id = ST.sale_id WHERE ST.sale_id is null GROUP BY SIT.sale_id, ST.sale_id'
. ' ORDER BY SIT.sale_id) as US')->getResultArray();
if (!$result) {
log_message('info', 'Database error in 20170502221506_sales_tax_data.php related to sales_taxes or sales_items_taxes.');
if (! $result) {
error_log('Database error in 20170502221506_sales_tax_data.php related to sales_taxes or sales_items_taxes.');
return 0;
}
return $result[0]['COUNT(*)'] ?: 0;
}
/**
* @param int $sale_id
* @param int $line
* @param string $name
* @param float $percent
* @param int $tax_type
* @param float $item_tax_amount
* @return void
*/
private function update_sales_items_taxes_amount(int $sale_id, int $line, string $name, float $percent, int $tax_type, float $item_tax_amount): void
{
$builder = $this->db->table('sales_items_taxes');
@@ -172,10 +152,6 @@ class Migration_Sales_Tax_Data extends Migration
$builder->update(['tax_type' => $tax_type, 'item_tax_amount' => $item_tax_amount]);
}
/**
* @param array $sales_taxes
* @return void
*/
private function save_sales_tax(array &$sales_taxes): void
{
$builder = $this->db->Table('sales_taxes');
@@ -185,56 +161,37 @@ class Migration_Sales_Tax_Data extends Migration
}
}
/**
* @param string $quantity
* @param string $price
* @param string $discount_percentage
* @param bool $include_discount
* @return string
*/
public function get_item_total(string $quantity, string $price, string $discount_percentage, bool $include_discount = false): string
{
$total = bcmul($quantity, $price);
if ($include_discount) {
$discount_amount = $this->get_item_discount($quantity, $price, $discount_percentage);
return bcsub($total, $discount_amount);
}
return $total;
}
/**
* @param string $quantity
* @param string $price
* @param string $discount
* @return float
*/
public function get_item_discount(string $quantity, string $price, string $discount): float
{
$total = bcmul($quantity, $price);
$total = bcmul($quantity, $price);
$discount_fraction = bcdiv($discount, 100);
$discount = bcmul($total, $discount_fraction);
$discount = bcmul($total, $discount_fraction);
return round($discount, totals_decimals(), PHP_ROUND_HALF_UP); // TODO: I don't think this is currency safe. Round will cast it's first parameter to a float. It also returns a float.
}
/**
* @param string $quantity
* @param string $price
* @param string $discount_percentage
* @param string $tax_percentage
* @return string
*/
public function get_item_tax(string $quantity, string $price, string $discount_percentage, string $tax_percentage): string
{
$tax_included = $this->appconfig->get_value('tax_included', Migration_Sales_Tax_Data::YES) == Migration_Sales_Tax_Data::YES;
$tax_included = $this->appconfig->get_value('tax_included', Migration_Sales_Tax_Data::YES) === Migration_Sales_Tax_Data::YES;
$price = $this->get_item_total($quantity, $price, $discount_percentage, true);
if ($tax_included) {
$tax_fraction = bcadd('100', $tax_percentage);
$tax_fraction = bcdiv($tax_fraction, '100');
$tax_fraction = bcadd('100', $tax_percentage);
$tax_fraction = bcdiv($tax_fraction, '100');
$price_tax_excl = bcdiv($price, $tax_fraction);
return bcsub($price, $price_tax_excl);
@@ -244,36 +201,23 @@ class Migration_Sales_Tax_Data extends Migration
return bcmul($price, $tax_fraction);
}
/**
* @param string $tax_basis
* @param string $tax_percentage
* @param int $rounding_mode
* @param int $decimals
* @return float
*/
public function get_sales_tax_for_amount(string $tax_basis, string $tax_percentage, int $rounding_mode, int $decimals): float
{
$tax_fraction = bcdiv($tax_percentage, '100');
$tax_amount = bcmul($tax_basis, $tax_fraction);
$tax_amount = bcmul($tax_basis, $tax_fraction);
return $this->round_number($rounding_mode, $tax_amount, $decimals);
}
/**
* @param int $rounding_mode
* @param string $amount
* @param int $decimals
* @return float
*/
public function round_number(int $rounding_mode, string $amount, int $decimals): float
{
if ($rounding_mode == Migration_Sales_Tax_Data::ROUND_UP) {
$fig = pow(10, $decimals);
if ($rounding_mode === Migration_Sales_Tax_Data::ROUND_UP) {
$fig = 10 ** $decimals;
$rounded_total = (ceil($fig * $amount) + ceil($fig * $amount - ceil($fig * $amount))) / $fig;
} elseif ($rounding_mode == Migration_Sales_Tax_Data::ROUND_DOWN) {
$fig = pow(10, $decimals);
} elseif ($rounding_mode === Migration_Sales_Tax_Data::ROUND_DOWN) {
$fig = 10 ** $decimals;
$rounded_total = (floor($fig * $amount) + floor($fig * $amount - floor($fig * $amount))) / $fig;
} elseif ($rounding_mode == Migration_Sales_Tax_Data::HALF_FIVE) {
} elseif ($rounding_mode === Migration_Sales_Tax_Data::HALF_FIVE) {
$rounded_total = round($amount / 5) * 5;
} else {
$rounded_total = round($amount, $decimals, $rounding_mode);
@@ -282,24 +226,10 @@ class Migration_Sales_Tax_Data extends Migration
return $rounded_total; // TODO: I don't think this is currency safe. I think we need to be using bcmath() functions like we are in the rest of the code.
}
/**
* @param array $sales_taxes
* @param string $tax_type
* @param string $tax_group
* @param float $tax_rate
* @param string $tax_basis
* @param string $item_tax_amount
* @param int $tax_group_sequence
* @param int $rounding_code
* @param int $sale_id
* @param string $name
* @param string $tax_code
* @return void
*/
public function update_sales_taxes(array &$sales_taxes, string $tax_type, string $tax_group, float $tax_rate, string $tax_basis, string $item_tax_amount, int $tax_group_sequence, int $rounding_code, int $sale_id, string $name = '', string $tax_code = ''): void
{
$tax_group_index = $this->clean('X' . $tax_group);
if (!array_key_exists($tax_group_index, $sales_taxes)) {
if (! array_key_exists($tax_group_index, $sales_taxes)) {
$insertkey = $tax_group_index; // TODO: $insertkey does not follow naming conventions.
$sales_tax = [
$insertkey => [
@@ -312,23 +242,19 @@ class Migration_Sales_Tax_Data extends Migration
'name' => $name,
'tax_rate' => $tax_rate,
'sales_tax_code' => $tax_code,
'rounding_code' => $rounding_code
]
'rounding_code' => $rounding_code,
],
];
// Add to existing array
$sales_taxes += $sales_tax;
} else {
// Important: the sales amounts are accumulated for the group at the maximum configurable scale value of 4
// but the scale will in reality be the scale specified by the tax_decimal configuration value used for sales_items_taxes
$sales_taxes[$tax_group_index]['sale_tax_basis'] = bcadd($sales_taxes[$tax_group_index]['sale_tax_basis'], $tax_basis, 4);
$sales_taxes[$tax_group_index]['sale_tax_basis'] = bcadd($sales_taxes[$tax_group_index]['sale_tax_basis'], $tax_basis, 4);
$sales_taxes[$tax_group_index]['sale_tax_amount'] = bcadd($sales_taxes[$tax_group_index]['sale_tax_amount'], $item_tax_amount, 4);
}
}
/**
* @param string $string
* @return string
*/
public function clean(string $string): string // TODO: $string is not a good name for this variable
{
$string = str_replace(' ', '-', $string); // Replaces all spaces with hyphens.
@@ -336,13 +262,9 @@ class Migration_Sales_Tax_Data extends Migration
return preg_replace('/[^A-Za-z0-9\-]/', '', $string); // Removes special chars.
}
/**
* @param array $sales_taxes
* @return void
*/
public function apply_invoice_taxing(array &$sales_taxes): void
{
if (!empty($sales_taxes)) { // TODO: Duplicated code
if (! empty($sales_taxes)) { // TODO: Duplicated code
$sort = [];
foreach ($sales_taxes as $key => $value) {
@@ -359,14 +281,11 @@ class Migration_Sales_Tax_Data extends Migration
}
}
/**
* @param array $sales_taxes
* @return void
*/
public function round_sales_taxes(array &$sales_taxes): void
{
if (!empty($sales_taxes)) {
if (! empty($sales_taxes)) {
$sort = [];
foreach ($sales_taxes as $k => $v) {
$sort['print_sequence'][$k] = $v['print_sequence'];
}
@@ -376,24 +295,24 @@ class Migration_Sales_Tax_Data extends Migration
$decimals = totals_decimals();
foreach ($sales_taxes as $row_number => $sales_tax) {
$sale_tax_amount = $sales_tax['sale_tax_amount'];
$rounding_code = $sales_tax['rounding_code'];
$sale_tax_amount = $sales_tax['sale_tax_amount'];
$rounding_code = $sales_tax['rounding_code'];
$rounded_sale_tax_amount = $sale_tax_amount;
if (
$rounding_code == PHP_ROUND_HALF_UP
|| $rounding_code == PHP_ROUND_HALF_DOWN
|| $rounding_code == PHP_ROUND_HALF_EVEN
|| $rounding_code == PHP_ROUND_HALF_ODD
$rounding_code === PHP_ROUND_HALF_UP
|| $rounding_code === PHP_ROUND_HALF_DOWN
|| $rounding_code === PHP_ROUND_HALF_EVEN
|| $rounding_code === PHP_ROUND_HALF_ODD
) {
$rounded_sale_tax_amount = round($sale_tax_amount, $decimals, $rounding_code);
} elseif ($rounding_code == Migration_Sales_Tax_Data::ROUND_UP) {
$fig = (int) str_pad('1', $decimals, '0');
} elseif ($rounding_code === Migration_Sales_Tax_Data::ROUND_UP) {
$fig = (int) str_pad('1', $decimals, '0');
$rounded_sale_tax_amount = (ceil($sale_tax_amount * $fig) / $fig);
} elseif ($rounding_code == Migration_Sales_Tax_Data::ROUND_DOWN) {
$fig = (int) str_pad('1', $decimals, '0');
} elseif ($rounding_code === Migration_Sales_Tax_Data::ROUND_DOWN) {
$fig = (int) str_pad('1', $decimals, '0');
$rounded_sale_tax_amount = (floor($sale_tax_amount * $fig) / $fig);
} elseif ($rounding_code == Migration_Sales_Tax_Data::HALF_FIVE) {
} elseif ($rounding_code === Migration_Sales_Tax_Data::HALF_FIVE) {
$rounded_sale_tax_amount = round($sale_tax_amount / 5) * 5;
}

View File

@@ -18,5 +18,7 @@ class Migration_Upgrade_To_3_2_0 extends Migration
/**
* Revert a migration step.
*/
public function down(): void {}
public function down(): void
{
}
}

View File

@@ -18,5 +18,7 @@ class Migration_Upgrade_To_3_2_1 extends Migration
/**
* Revert a migration step.
*/
public function down(): void {}
public function down(): void
{
}
}

View File

@@ -18,5 +18,7 @@ class Migration_Attributes extends Migration
/**
* Revert a migration step.
*/
public function down(): void {}
public function down(): void
{
}
}

View File

@@ -18,5 +18,7 @@ class Migration_Upgrade_To_3_3_0 extends Migration
/**
* Revert a migration step.
*/
public function down(): void {}
public function down(): void
{
}
}

View File

@@ -11,7 +11,7 @@ class Migration_IndiaGST extends Migration
*/
public function up(): void
{
if (!$this->db->fieldExists('sales_tax_code', 'customers')) {
if (! $this->db->fieldExists('sales_tax_code', 'customers')) {
return;
}
@@ -19,6 +19,8 @@ class Migration_IndiaGST extends Migration
helper('migration');
execute_script(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_indiagst.sql');
error_log('Migrating tax configuration');
$count_of_tax_codes = $this->get_count_of_tax_code_entries();
if ($count_of_tax_codes > 0) {
@@ -40,16 +42,17 @@ class Migration_IndiaGST extends Migration
}
$this->drop_backups();
error_log('Migrating tax configuration completed');
}
/**
* Revert a migration step.
*/
public function down(): void {}
public function down(): void
{
}
/**
* @return int
*/
private function get_count_of_tax_code_entries(): int
{
$builder = $this->db->table('tax_codes_backup');
@@ -58,9 +61,6 @@ class Migration_IndiaGST extends Migration
return $builder->get()->getRow()->count;
}
/**
* @return int
*/
private function get_count_of_sales_taxes_entries(): int
{
$builder = $this->db->table('sales_taxes_backup');
@@ -69,9 +69,6 @@ class Migration_IndiaGST extends Migration
return $builder->get()->getRow()->count;
}
/**
* @return int
*/
private function get_count_of_rate_entries(): int
{
$builder = $this->db->table('tax_code_rates_backup');
@@ -84,8 +81,6 @@ class Migration_IndiaGST extends Migration
* This copies the old tax code configuration into the new tax code configuration
* assigning a tax_code_id id to the entry This only needs to be done if there are
* tax codes in the table.
*
* @return void
*/
private function migrate_tax_code_data(): void
{
@@ -98,8 +93,6 @@ class Migration_IndiaGST extends Migration
* This will assign a tax code id using the tax code field that was left in place on the customer table.
* After it is complete then it will drop the old customer tax code.
* This MUST run so that the old tax code is dropped
*
* @return void
*/
private function migrate_customer_tax_codes(): void
{
@@ -132,9 +125,6 @@ class Migration_IndiaGST extends Migration
. 'order by sale_id');
}
/**
* @return void
*/
private function migrate_tax_rates(): void
{
// Create a dummy jurisdiction record and retrieve the jurisdiction rate id
@@ -152,9 +142,6 @@ class Migration_IndiaGST extends Migration
. ' ON tax_code = rate_tax_code');
}
/**
* @return void
*/
private function drop_backups(): void
{
$this->db->query('DROP TABLE IF EXISTS ' . $this->db->prefixTable('tax_codes_backup'));

View File

@@ -13,10 +13,16 @@ class Migration_IndiaGST1 extends Migration
{
helper('migration');
execute_script(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_indiagst1.sql');
error_log('Fix definition of Supplier.Tax Id');
error_log('Definition of Supplier.Tax Id corrected');
}
/**
* Revert a migration step.
*/
public function down(): void {}
public function down(): void
{
}
}

View File

@@ -18,5 +18,7 @@ class Migration_IndiaGST2 extends Migration
/**
* Revert a migration step.
*/
public function down(): void {}
public function down(): void
{
}
}

View File

@@ -18,5 +18,7 @@ class Migration_decimal_attribute_type extends Migration
/**
* Revert a migration step.
*/
public function down(): void {}
public function down(): void
{
}
}

View File

@@ -18,5 +18,7 @@ class Migration_add_iso_4217 extends Migration
/**
* Revert a migration step.
*/
public function down(): void {}
public function down(): void
{
}
}

View File

@@ -18,5 +18,7 @@ class Migration_PaymentTracking extends Migration
/**
* Revert a migration step.
*/
public function down(): void {}
public function down(): void
{
}
}

View File

@@ -33,7 +33,7 @@ class Migration_RefundTracking extends Migration
ON sales.sale_id = sales_taxes.sale_id
WHERE sales.sale_status = \'' . COMPLETED . '\' AND sales_taxes.tax_type = \'1\'
GROUP BY sale_id
)'
)',
);
$this->db->query(
@@ -47,7 +47,7 @@ class Migration_RefundTracking extends Migration
. 'LEFT OUTER JOIN ' . $this->db->prefixTable('migrate_taxes') . ' AS sumpay_taxes '
. 'ON sales.sale_id = sumpay_taxes.sale_id '
. 'WHERE sales.sale_status = \'' . COMPLETED . '\' GROUP BY sale_id
)'
)',
);
$this->db->query('UPDATE ' . $this->db->prefixTable('migrate_sales') . ' AS sumpay_items '
@@ -64,7 +64,7 @@ class Migration_RefundTracking extends Migration
LEFT OUTER JOIN ' . $this->db->prefixTable('sales_payments') . ' AS sales_payments
ON sales.sale_id = sales_payments.sale_id
WHERE sales.sale_status = \'' . COMPLETED . '\' GROUP BY sale_id
)'
)',
);
// You may be asking yourself why the following is not creating a temporary table.
@@ -78,7 +78,7 @@ class Migration_RefundTracking extends Migration
FROM ' . $this->db->prefixTable('migrate_sales') . ' AS a
JOIN ' . $this->db->prefixTable('migrate_payments') . ' AS b ON a.sale_id = b.sale_id
WHERE total_payments > trans_amount AND number_payments = 1
)'
)',
);
// Update existing cash transactions with refund amount
@@ -91,7 +91,7 @@ class Migration_RefundTracking extends Migration
WHERE EXISTS
(SELECT b.refund_amount
FROM ' . $this->db->prefixTable('migrate_refund') . ' AS b
WHERE a.sale_id = b.sale_id AND a.payment_type = \'' . $cash_payment . ' \')'
WHERE a.sale_id = b.sale_id AND a.payment_type = \'' . $cash_payment . ' \')',
);
// Insert new cash refund transactions for non-cash payments
@@ -102,7 +102,7 @@ class Migration_RefundTracking extends Migration
FROM ' . $this->db->prefixTable('migrate_refund') . ' AS r
JOIN ' . $this->db->prefixTable('sales_payments') . ' AS p ON r.sale_id = p.sale_id
JOIN ' . $this->db->prefixTable('migrate_sales') . ' AS s ON r.sale_id = s.sale_id
WHERE p.payment_type != \'' . $cash_payment . '\''
WHERE p.payment_type != \'' . $cash_payment . '\'',
);
// Post migration cleanup
@@ -112,5 +112,7 @@ class Migration_RefundTracking extends Migration
/**
* Revert a migration step.
*/
public function down(): void {}
public function down(): void
{
}
}

View File

@@ -18,5 +18,7 @@ class Migration_DBFix extends Migration
/**
* Revert a migration step.
*/
public function down(): void {}
public function down(): void
{
}
}

View File

@@ -18,5 +18,7 @@ class Migration_fix_attribute_datetime extends Migration
/**
* Revert a migration step.
*/
public function down(): void {}
public function down(): void
{
}
}

View File

@@ -11,8 +11,6 @@ class Migration_fix_empty_reports extends Migration
*/
public function up(): void
{
log_message('info', 'Starting migration: Fix empty reports.');
$builder = $this->db->table('stock_locations');
$builder->select('location_name');
$builder->where('location_id', 1);
@@ -20,17 +18,17 @@ class Migration_fix_empty_reports extends Migration
$location_name = $builder->get()->getResultArray()[0]['location_name'];
$location_name = str_replace(' ', '_', $location_name);
$builder = $this->db->table('permissions');
$builder = $this->db->table('permissions');
$builder->set('location_id', 1);
$builder->where('permission_id', 'receivings_' . $location_name);
$builder->orWhere('permission_id', 'sales_' . $location_name);
$builder->update();
log_message('info', 'Finished migration: Fix empty reports.');
}
/**
* Revert a migration step.
*/
public function down(): void {}
public function down(): void
{
}
}

View File

@@ -11,7 +11,6 @@ class Migration_receipttaxindicator extends Migration
*/
public function up(): void
{
log_message('info', 'Migrating receipt tax indicator.');
$this->db->query('INSERT INTO ' . $this->db->prefixTable('app_config') . ' (`key`, `value`)
VALUES (\'receipt_show_tax_ind\', \'0\')');
}

View File

@@ -18,5 +18,7 @@ class Migration_PaymentDateFix extends Migration
/**
* Revert a migration step.
*/
public function down(): void {}
public function down(): void
{
}
}

View File

@@ -18,5 +18,7 @@ class Migration_SalesChangePrice extends Migration
/**
* Revert a migration step.
*/
public function down(): void {}
public function down(): void
{
}
}

View File

@@ -2,25 +2,24 @@
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
use App\Libraries\Tax_lib;
use App\Models\Appconfig;
use CodeIgniter\Database\Migration;
use CodeIgniter\Database\ResultInterface;
/**
*
*
* @property appconfig appconfig
* @property tax_lib tax_lib
* @property Appconfig appconfig
* @property Tax_lib tax_lib
*/
class Migration_TaxAmount extends Migration
{
public const ROUND_UP = 5;
public const ROUND_UP = 5;
public const ROUND_DOWN = 6;
public const HALF_FIVE = 7;
public const YES = '1';
public const VAT_TAX = '0';
public const SALES_TAX = '1'; // TODO: It appears that this constant is never used
public const HALF_FIVE = 7;
public const YES = '1';
public const VAT_TAX = '0';
public const SALES_TAX = '1'; // TODO: It appears that this constant is never used
private Appconfig $appconfig;
public function __construct()
@@ -35,13 +34,13 @@ class Migration_TaxAmount extends Migration
*/
public function up(): void
{
$tax_included = ($this->appconfig->get_value('tax_included', Migration_TaxAmount::YES) == Migration_TaxAmount::YES);
$tax_included = ($this->appconfig->get_value('tax_included', Migration_TaxAmount::YES) === Migration_TaxAmount::YES);
if ($tax_included) {
$tax_decimals = $this->appconfig->get_value('tax_decimals', 2);
$tax_decimals = $this->appconfig->get_value('tax_decimals', 2);
$number_of_unmigrated = $this->get_count_of_unmigrated();
log_message('info', 'Migrating sales tax fixing. The number of sales that will be migrated is ' . $number_of_unmigrated);
error_log('Migrating sales tax fixing. The number of sales that will be migrated is ' . $number_of_unmigrated);
if ($number_of_unmigrated > 0) {
$unmigrated_invoices = $this->get_unmigrated($number_of_unmigrated)->getResultArray();
@@ -54,37 +53,33 @@ class Migration_TaxAmount extends Migration
$this->db->query('DROP TABLE ' . $this->db->prefixTable('sales_taxes_backup'));
}
log_message('info', 'Migrating sales tax fixing. The number of sales that will be migrated is finished.');
error_log('Migrating sales tax fixing. The number of sales that will be migrated is finished.');
}
}
/**
* Revert a migration step.
*/
public function down(): void {}
public function down(): void
{
}
/**
* @param int $sale_id
* @param string $tax_decimals
* @param bool $tax_included
* @return void
*/
private function upgrade_tax_history_for_sale(int $sale_id, string $tax_decimals, bool $tax_included): void // TODO: $tax_included is passed as a parameter but never used in the function body.
{
$customer_sales_tax_support = false;
$tax_type = Migration_TaxAmount::VAT_TAX;
$sales_taxes = [];
$tax_group_sequence = 0;
$items = $this->get_sale_items_for_migration($sale_id)->getResultArray();
$tax_type = Migration_TaxAmount::VAT_TAX;
$sales_taxes = [];
$tax_group_sequence = 0;
$items = $this->get_sale_items_for_migration($sale_id)->getResultArray();
foreach ($items as $item) {
// This computes tax for each line item and adds it to the tax type total
$tax_group = (float)$item['percent'] . '% ' . $item['name'];
$tax_basis = $this->get_item_total($item['quantity_purchased'], $item['item_unit_price'], $item['discount'], true);
$tax_group = (float) $item['percent'] . '% ' . $item['name'];
$tax_basis = $this->get_item_total($item['quantity_purchased'], $item['item_unit_price'], $item['discount'], true);
$item_tax_amount = $this->get_item_tax($tax_basis, $item['percent'], PHP_ROUND_HALF_UP, $tax_decimals);
$this->update_sales_items_taxes_amount($sale_id, $item['line'], $item['name'], $item['percent'], $tax_type, $item_tax_amount);
$this->update_sales_taxes($sales_taxes, $tax_type, $tax_group, $item['percent'], $tax_basis, $item_tax_amount, $tax_group_sequence, PHP_ROUND_HALF_UP, $sale_id, $item['name']);
$tax_group_sequence += 1;
$tax_group_sequence++;
}
if ($customer_sales_tax_support) { // TODO: This will always evaluate to false.
@@ -95,10 +90,6 @@ class Migration_TaxAmount extends Migration
$this->save_sales_tax($sales_taxes);
}
/**
* @param int $block_count
* @return ResultInterface
*/
private function get_unmigrated(int $block_count): ResultInterface
{
$builder = $this->db->table('sales_items_taxes as SIT');
@@ -113,9 +104,6 @@ class Migration_TaxAmount extends Migration
return $builder->get();
}
/**
* @return int
*/
private function get_count_of_unmigrated(): int
{
$result = $this->db->query('SELECT COUNT(*) FROM(SELECT SIT.sale_id, ST.sale_id as sales_taxes_sale_id FROM '
@@ -125,19 +113,15 @@ class Migration_TaxAmount extends Migration
. ' as ST ON SIT.sale_id = ST.sale_id GROUP BY SIT.sale_id, ST.sale_id'
. ' ORDER BY SIT.sale_id) as US')->getResultArray();
if (!$result) {
log_message('info', 'Database error in 20200202000000_taxamount.php related to sales_taxes or sales_items_taxes.');
if (! $result) {
error_log('Database error in 20200202000000_taxamount.php related to sales_taxes or sales_items_taxes.');
return 0;
}
return $result[0]['COUNT(*)'] ?: 0;
}
/**
* @param int $sale_id
* @return ResultInterface
*/
private function get_sale_items_for_migration(int $sale_id): ResultInterface
{
$builder = $this->db->table('sales_items as sales_items');
@@ -154,15 +138,6 @@ class Migration_TaxAmount extends Migration
return $builder->get();
}
/**
* @param int $sale_id
* @param int $line
* @param string $name
* @param float $percent
* @param int $tax_type
* @param float $item_tax_amount
* @return void
*/
private function update_sales_items_taxes_amount(int $sale_id, int $line, string $name, float $percent, int $tax_type, float $item_tax_amount): void
{
$builder = $this->db->table('sales_items_taxes');
@@ -173,10 +148,6 @@ class Migration_TaxAmount extends Migration
$builder->update(['tax_type' => $tax_type, 'item_tax_amount' => $item_tax_amount]);
}
/**
* @param array $sales_taxes
* @return void
*/
private function save_sales_tax(array &$sales_taxes): void
{
$builder = $this->db->table('sales_taxes');
@@ -186,13 +157,6 @@ class Migration_TaxAmount extends Migration
}
}
/**
* @param string $quantity
* @param string $price
* @param string $discount
* @param bool $include_discount
* @return string
*/
public function get_item_total(string $quantity, string $price, string $discount, bool $include_discount = false): string
{
$total = bcmul($quantity, $price);
@@ -204,52 +168,32 @@ class Migration_TaxAmount extends Migration
return $total;
}
/**
* @param string $tax_basis
* @param string $tax_percentage
* @param int $rounding_mode
* @param int $decimals
* @return float
*/
public function get_item_tax(string $tax_basis, string $tax_percentage, int $rounding_mode, int $decimals): float // TODO: is this currency safe?
{
$tax_fraction = bcdiv(bcadd('100', $tax_percentage), '100');
$tax_fraction = bcdiv(bcadd('100', $tax_percentage), '100');
$price_tax_excl = bcdiv($tax_basis, $tax_fraction);
$tax_amount = bcsub($tax_basis, $price_tax_excl);
$tax_amount = bcsub($tax_basis, $price_tax_excl);
return $this->round_number($rounding_mode, $tax_amount, $decimals);
}
/**
* @param string $tax_basis
* @param string $tax_percentage
* @param int $rounding_mode
* @param int $decimals
* @return float
*/
public function get_sales_tax_for_amount(string $tax_basis, string $tax_percentage, int $rounding_mode, int $decimals): float // TODO: is this currency safe?
{
$tax_fraction = bcdiv($tax_percentage, '100');
$tax_amount = bcmul($tax_basis, $tax_fraction);
$tax_amount = bcmul($tax_basis, $tax_fraction);
return $this->round_number($rounding_mode, $tax_amount, $decimals);
}
/**
* @param int $rounding_mode
* @param string $amount
* @param int $decimals
* @return float
*/
public function round_number(int $rounding_mode, string $amount, int $decimals): float // TODO: is this currency safe?
{ // TODO: This needs to be converted to a switch
if ($rounding_mode == Migration_TaxAmount::ROUND_UP) { // TODO: === ?
$fig = pow(10, $decimals);
if ($rounding_mode === Migration_TaxAmount::ROUND_UP) { // TODO: === ?
$fig = 10 ** $decimals;
$rounded_total = (ceil($fig * $amount) + ceil($fig * $amount - ceil($fig * $amount))) / $fig;
} elseif ($rounding_mode == Migration_TaxAmount::ROUND_DOWN) { // TODO: === ?
$fig = pow(10, $decimals);
} elseif ($rounding_mode === Migration_TaxAmount::ROUND_DOWN) { // TODO: === ?
$fig = 10 ** $decimals;
$rounded_total = (floor($fig * $amount) + floor($fig * $amount - floor($fig * $amount))) / $fig;
} elseif ($rounding_mode == Migration_TaxAmount::HALF_FIVE) { // TODO: === ?
} elseif ($rounding_mode === Migration_TaxAmount::HALF_FIVE) { // TODO: === ?
$rounded_total = round($amount / 5) * 5;
} else {
$rounded_total = round($amount, $decimals, $rounding_mode);
@@ -258,25 +202,11 @@ class Migration_TaxAmount extends Migration
return $rounded_total;
}
/**
* @param array $sales_taxes
* @param int $tax_type
* @param string $tax_group
* @param float $tax_rate
* @param string $tax_basis
* @param string $item_tax_amount
* @param int $tax_group_sequence
* @param int $rounding_code
* @param int $sale_id
* @param string $name
* @param string $tax_code
* @return void
*/
public function update_sales_taxes(array &$sales_taxes, int $tax_type, string $tax_group, float $tax_rate, string $tax_basis, string $item_tax_amount, int $tax_group_sequence, int $rounding_code, int $sale_id, string $name = '', string $tax_code = ''): void
{
$tax_group_index = $this->clean('X' . $tax_group);
if (!array_key_exists($tax_group_index, $sales_taxes)) {
if (! array_key_exists($tax_group_index, $sales_taxes)) {
$insertkey = $tax_group_index;
$sales_tax = [
$insertkey => [
@@ -289,8 +219,8 @@ class Migration_TaxAmount extends Migration
'name' => $name,
'tax_rate' => $tax_rate,
'sales_tax_code_id' => $tax_code,
'rounding_code' => $rounding_code
]
'rounding_code' => $rounding_code,
],
];
// Add to existing array
@@ -298,15 +228,11 @@ class Migration_TaxAmount extends Migration
} else {
// Important: the sales amounts are accumulated for the group at the maximum configurable scale value of 4
// but the scale will in reality be the scale specified by the tax_decimal configuration value used for sales_items_taxes
$sales_taxes[$tax_group_index]['sale_tax_basis'] = bcadd($sales_taxes[$tax_group_index]['sale_tax_basis'], $tax_basis, 4);
$sales_taxes[$tax_group_index]['sale_tax_basis'] = bcadd($sales_taxes[$tax_group_index]['sale_tax_basis'], $tax_basis, 4);
$sales_taxes[$tax_group_index]['sale_tax_amount'] = bcadd($sales_taxes[$tax_group_index]['sale_tax_amount'], $item_tax_amount, 4);
}
}
/**
* @param string $string
* @return string
*/
public function clean(string $string): string // TODO: This can probably go into the migration helper as it's used it more than one migration. Also, $string needs to be refactored to a different name.
{
$string = str_replace(' ', '-', $string); // Replaces all spaces with hyphens.
@@ -314,14 +240,11 @@ class Migration_TaxAmount extends Migration
return preg_replace('/[^A-Za-z0-9\-]/', '', $string); // Removes special chars.
}
/**
* @param array $sales_taxes
* @return void
*/
public function apply_invoice_taxing(array &$sales_taxes): void
{
if (!empty($sales_taxes)) { // TODO: Duplicated code
if (! empty($sales_taxes)) { // TODO: Duplicated code
$sort = [];
foreach ($sales_taxes as $k => $v) {
$sort['print_sequence'][$k] = $v['print_sequence'];
}
@@ -335,13 +258,9 @@ class Migration_TaxAmount extends Migration
}
}
/**
* @param array $sales_taxes
* @return void
*/
public function round_sales_taxes(array &$sales_taxes): void
{
if (!empty($sales_taxes)) {
if (! empty($sales_taxes)) {
$sort = [];
foreach ($sales_taxes as $k => $v) {
@@ -354,24 +273,24 @@ class Migration_TaxAmount extends Migration
$decimals = totals_decimals();
foreach ($sales_taxes as $row_number => $sales_tax) {
$sale_tax_amount = $sales_tax['sale_tax_amount'];
$rounding_code = $sales_tax['rounding_code'];
$sale_tax_amount = $sales_tax['sale_tax_amount'];
$rounding_code = $sales_tax['rounding_code'];
$rounded_sale_tax_amount = $sale_tax_amount;
if (
$rounding_code == PHP_ROUND_HALF_UP // TODO: This block of if/elseif statements can be converted to a switch.
|| $rounding_code == PHP_ROUND_HALF_DOWN
|| $rounding_code == PHP_ROUND_HALF_EVEN
|| $rounding_code == PHP_ROUND_HALF_ODD
$rounding_code === PHP_ROUND_HALF_UP // TODO: This block of if/elseif statements can be converted to a switch.
|| $rounding_code === PHP_ROUND_HALF_DOWN
|| $rounding_code === PHP_ROUND_HALF_EVEN
|| $rounding_code === PHP_ROUND_HALF_ODD
) {
$rounded_sale_tax_amount = round($sale_tax_amount, $decimals, $rounding_code);
} elseif ($rounding_code == Migration_TaxAmount::ROUND_UP) {
$fig = (int) str_pad('1', $decimals, '0');
} elseif ($rounding_code === Migration_TaxAmount::ROUND_UP) {
$fig = (int) str_pad('1', $decimals, '0');
$rounded_sale_tax_amount = (ceil($sale_tax_amount * $fig) / $fig);
} elseif ($rounding_code == Migration_TaxAmount::ROUND_DOWN) {
$fig = (int) str_pad('1', $decimals, '0');
} elseif ($rounding_code === Migration_TaxAmount::ROUND_DOWN) {
$fig = (int) str_pad('1', $decimals, '0');
$rounded_sale_tax_amount = (floor($sale_tax_amount * $fig) / $fig);
} elseif ($rounding_code == Migration_TaxAmount::HALF_FIVE) {
} elseif ($rounding_code === Migration_TaxAmount::HALF_FIVE) {
$rounded_sale_tax_amount = round($sale_tax_amount / 5) * 5;
}

View File

@@ -11,7 +11,6 @@ class Migration_taxgroupconstraint extends Migration
*/
public function up(): void
{
log_message('info', 'Migrating tax group constraints.');
$this->db->query('ALTER TABLE ' . $this->db->prefixTable('tax_jurisdictions') . ' ADD CONSTRAINT tax_jurisdictions_uq1 UNIQUE (tax_group)');
}

View File

@@ -11,12 +11,11 @@ class Migration_image_upload_defaults extends Migration
*/
public function up(): void
{
log_message('info', 'Migrating image upload defaults.');
$image_values = [
['key' => 'image_allowed_types', 'value' => 'gif|jpg|png'],
['key' => 'image_max_height', 'value' => '480'],
['key' => 'image_max_size', 'value' => '128'],
['key' => 'image_max_width', 'value' => '640']
['key' => 'image_max_height', 'value' => '480'],
['key' => 'image_max_size', 'value' => '128'],
['key' => 'image_max_width', 'value' => '640'],
];
$builder = $this->db->table('app_config');

View File

@@ -11,12 +11,18 @@ class Migration_modify_attr_links_constraint extends Migration
*/
public function up(): void
{
error_log('Migrating modify_attr_links_constraint');
helper('migration');
execute_script(APPPATH . 'Database/Migrations/sqlscripts/3.3.2_modify_attr_links_constraint.sql');
error_log('Migrating modify_attr_links_constraint');
}
/**
* Revert a migration step.
*/
public function down(): void {}
public function down(): void
{
}
}

View File

@@ -11,7 +11,6 @@ class Migration_cashrounding extends Migration
*/
public function up(): void
{
log_message('info', 'Migrating cash rounding.');
$this->db->query('ALTER TABLE ' . $this->db->prefixTable('sales_payments') . ' ADD COLUMN `cash_adjustment` tinyint NOT NULL DEFAULT 0 AFTER `cash_refund`');
}

View File

@@ -11,12 +11,18 @@ class Migration_add_item_kit_number extends Migration
*/
public function up(): void
{
error_log('Migrating add_item_kit_number');
helper('migration');
execute_script(APPPATH . 'Database/Migrations/sqlscripts/3.3.3_add_kits_item_number.sql');
error_log('Migrating add_item_kit_number');
}
/**
* Revert a migration step.
*/
public function down(): void {}
public function down(): void
{
}
}

View File

@@ -11,12 +11,18 @@ class Migration_modify_session_datatype extends Migration
*/
public function up(): void
{
error_log('Migrating modify_session_datatype');
helper('migration');
execute_script(APPPATH . 'Database/Migrations/sqlscripts/3.3.4_modify_session_datatype.sql');
error_log('Migrating modify_session_datatype');
}
/**
* Revert a migration step.
*/
public function down(): void {}
public function down(): void
{
}
}

View File

@@ -2,10 +2,9 @@
namespace App\Database\Migrations;
use App\Models\Attribute;
use CodeIgniter\Database\Migration;
use CodeIgniter\Database\ResultInterface;
use App\Models\Attribute;
use Config\Database;
use Config\OSPOS;
use DateTime;
@@ -16,11 +15,11 @@ class Migration_database_optimizations extends Migration
*/
public function up(): void
{
log_message('info', 'Migrating database optimizations.');
error_log('Migrating database_optimizations');
$attribute = model(Attribute::class);
$attribute->deleteOrphanedValues();
$attribute->delete_orphaned_values();
$this->migrate_duplicate_attribute_values(DECIMAL);
$this->migrate_duplicate_attribute_values(DATE);
@@ -52,7 +51,7 @@ class Migration_database_optimizations extends Migration
$attribute_links = $builder->get();
if ($attribute_links) {
$builder = $this->db->table('attribute_links');
$builder = $this->db->table('attribute_links');
$attribute_links = $attribute_links->getResultArray() ?: [];
foreach ($attribute_links->getResultArray() as $attribute_link) {
@@ -64,11 +63,13 @@ class Migration_database_optimizations extends Migration
case DECIMAL:
$value = $attribute_value['attribute_decimal'];
break;
case DATE:
$config = config(OSPOS::class)->settings;
$config = config(OSPOS::class)->settings;
$attribute_date = DateTime::createFromFormat('Y-m-d', $attribute_value['attribute_date']);
$value = $attribute_date->format($config['dateformat']);
$value = $attribute_date->format($config['dateformat']);
break;
default:
$value = $attribute_value['attribute_value'];
break;
@@ -82,11 +83,13 @@ class Migration_database_optimizations extends Migration
helper('migration');
execute_script(APPPATH . 'Database/Migrations/sqlscripts/3.4.0_database_optimizations.sql');
log_message('info', 'Finished migrating database optimizations.');
error_log('Migrating database_optimizations completed');
}
/**
* Given the type of attribute, deletes any duplicates it finds in the attribute_values table and reassigns those
*
* @param mixed $attribute_type
*/
private function migrate_duplicate_attribute_values($attribute_type): void
{
@@ -96,9 +99,9 @@ class Migration_database_optimizations extends Migration
$column = 'attribute_' . strtolower($attribute_type);
$builder = $this->db->table('attribute_values');
$builder->select("$column");
$builder->select("{$column}");
$builder->groupBy($column);
$builder->having("COUNT($column) > 1");
$builder->having("COUNT({$column}) > 1");
$duplicated_values = $builder->get();
foreach ($duplicated_values->getResultArray() as $duplicated_value) {
@@ -110,7 +113,7 @@ class Migration_database_optimizations extends Migration
$builder = $this->db->table('attribute_values');
$builder->select('attribute_id');
$builder->where($column, $duplicated_value[$column]);
$builder->where("attribute_id IN ($subquery)", null, false);
$builder->where("attribute_id IN ({$subquery})", null, false);
$attribute_ids_to_fix = $builder->get();
$this->reassign_duplicate_attribute_values($attribute_ids_to_fix, $duplicated_value);
@@ -123,11 +126,11 @@ class Migration_database_optimizations extends Migration
* Updates the attribute_id in all attribute_link rows with duplicated attribute_ids then deletes unneeded rows from attribute_values
*
* @param ResultInterface $attribute_ids_to_fix All attribute_ids that need to parsed
* @param array $attribute_value The attribute value in question.
* @param array $attribute_value The attribute value in question.
*/
private function reassign_duplicate_attribute_values(ResultInterface $attribute_ids_to_fix, array $attribute_value): void
{
$attribute_ids = $attribute_ids_to_fix->getResultArray();
$attribute_ids = $attribute_ids_to_fix->getResultArray();
$retain_attribute_id = $attribute_ids[0]['attribute_id'];
foreach ($attribute_ids as $attribute_id) {
@@ -147,5 +150,7 @@ class Migration_database_optimizations extends Migration
/**
* Revert a migration step.
*/
public function down(): void {}
public function down(): void
{
}
}

View File

@@ -2,8 +2,8 @@
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
use App\Models\Attribute;
use CodeIgniter\Database\Migration;
class Migration_remove_duplicate_links extends Migration
{
@@ -12,17 +12,17 @@ class Migration_remove_duplicate_links extends Migration
*/
public function up(): void
{
log_message('info', 'Removing duplicate links.');
error_log('Migrating remove_duplicate_links');
$this->migrate_duplicate_attribute_links();
log_message('info', 'Duplicate links removed.');
error_log('Migrating remove_duplicate_links completed');
}
/**
* Given the type of attribute, deletes any duplicates it finds in the attribute_values table and reassigns those
*
* @property attribute $attribute
* @property Attribute $attribute
*/
private function migrate_duplicate_attribute_links(): void
{
@@ -60,5 +60,7 @@ class Migration_remove_duplicate_links extends Migration
/**
* Revert a migration step.
*/
public function down(): void {}
public function down(): void
{
}
}

View File

@@ -11,15 +11,17 @@ class Migration_move_expenses_categories extends Migration
*/
public function up(): void
{
log_message('info', 'Migrating expense categories module');
error_log('Migrating expense categories module');
$this->db->simpleQuery("UPDATE ospos_grants SET menu_group = 'office' WHERE permission_id = 'expenses_categories'");
log_message('info', 'Migrating expense categories module completed');
error_log('Migrating expense categories module completed');
}
/**
* Revert a migration step.
*/
public function down(): void {}
public function down(): void
{
}
}

View File

@@ -5,8 +5,8 @@ namespace App\Database\Migrations;
use App\Models\Appconfig;
use CodeIgniter\Database\Forge;
use CodeIgniter\Database\Migration;
use CodeIgniter\HTTP\RedirectResponse;
use CodeIgniter\HTTP\Exceptions\RedirectException;
use CodeIgniter\HTTP\RedirectResponse;
use Config\Encryption;
use Config\Services;
use ReflectionException;
@@ -27,25 +27,32 @@ class Convert_to_ci4 extends Migration
*/
public function up(): void
{
error_log('Migrating database to CodeIgniter4 formats');
helper('migration');
execute_script(APPPATH . 'Database/Migrations/sqlscripts/3.4.0_ci4_conversion.sql');
if (!empty(config('Encryption')->key)) {
if (! empty(config('Encryption')->key)) {
$this->convert_ci3_encrypted_data();
} else {
check_encryption();
}
remove_backup();
error_log('Migrating to CodeIgniter4 formats completed');
}
/**
* Revert a migration step.
*/
public function down(): void {}
public function down(): void
{
}
/**
* @return RedirectResponse|void
*
* @throws ReflectionException
*/
private function convert_ci3_encrypted_data()
@@ -57,7 +64,7 @@ class Convert_to_ci4 extends Migration
'clcdesq_api_url' => '',
'mailchimp_api_key' => '',
'mailchimp_list_id' => '',
'smtp_pass' => ''
'smtp_pass' => '',
];
foreach ($ci3_encrypted_data as $key => $value) {
@@ -72,9 +79,10 @@ class Convert_to_ci4 extends Migration
$ci4_encrypted_data = $this->encrypt_data($decrypted_data);
$success = empty(array_diff_assoc($decrypted_data, $this->decrypt_data($ci4_encrypted_data)));
if (!$success) {
if (! $success) {
abort_encryption_conversion();
remove_backup();
throw new RedirectException('login');
}
@@ -88,23 +96,25 @@ class Convert_to_ci4 extends Migration
* Decrypts CI3 encrypted data and returns the plaintext values.
*
* @param array $encrypted_data Data encrypted using CI3 methodology.
*
* @return array Plaintext, unencrypted data.
*/
private function decrypt_ci3_data(array $encrypted_data): array
{
$config = new Encryption();
$config->driver = 'OpenSSL';
$config->key = config('Encryption')->key;
$config->cipher = 'AES-128-CBC';
$config->rawData = false;
$config = new Encryption();
$config->driver = 'OpenSSL';
$config->key = config('Encryption')->key;
$config->cipher = 'AES-128-CBC';
$config->rawData = false;
$config->encryptKeyInfo = 'encryption';
$config->authKeyInfo = 'authentication';
$config->authKeyInfo = 'authentication';
$encrypter = Services::encrypter($config);
$decrypted_data = [];
foreach ($encrypted_data as $key => $value) {
$decrypted_data[$key] = !empty($value) ? $encrypter->decrypt($value) : '';
$decrypted_data[$key] = ! empty($value) ? $encrypter->decrypt($value) : '';
}
return $decrypted_data;
@@ -114,6 +124,7 @@ class Convert_to_ci4 extends Migration
* Encrypts data using CI4 algorithms.
*
* @param array $plain_data Data to be encrypted.
*
* @return array Encrypted data.
*/
private function encrypt_data(array $plain_data): array
@@ -121,8 +132,9 @@ class Convert_to_ci4 extends Migration
$encrypter = Services::encrypter();
$encrypted_data = [];
foreach ($plain_data as $key => $value) {
$encrypted_data[$key] = !empty($value) ? $encrypter->encrypt($value) : '';
$encrypted_data[$key] = ! empty($value) ? $encrypter->encrypt($value) : '';
}
return $encrypted_data;
@@ -132,6 +144,7 @@ class Convert_to_ci4 extends Migration
* Decrypts data using CI4 algorithms.
*
* @param array $encrypted_data Data to be decrypted.
*
* @return array Decrypted data.
*/
private function decrypt_data(array $encrypted_data): array
@@ -139,8 +152,9 @@ class Convert_to_ci4 extends Migration
$encrypter = Services::encrypter();
$decrypted_data = [];
foreach ($encrypted_data as $key => $value) {
$decrypted_data[$key] = !empty($value) ? $encrypter->decrypt($value) : '';
$decrypted_data[$key] = ! empty($value) ? $encrypter->decrypt($value) : '';
}
return $decrypted_data;

View File

@@ -11,7 +11,6 @@ class IntToTinyint extends Migration
*/
public function up(): void
{
log_message('info', 'Converting ints to tinyints.');
$this->db->query('ALTER TABLE ' . $this->db->prefixTable('customers') . ' MODIFY `consent` tinyint NOT NULL DEFAULT 0');
$this->db->query('ALTER TABLE ' . $this->db->prefixTable('cash_up') . ' MODIFY `note` tinyint NOT NULL DEFAULT 0');
}
@@ -21,7 +20,6 @@ class IntToTinyint extends Migration
*/
public function down(): void
{
log_message('info', 'Converting tinyints to ints.');
$this->db->query('ALTER TABLE ' . $this->db->prefixTable('customers') . ' MODIFY `consent` int NOT NULL DEFAULT 0');
$this->db->query('ALTER TABLE ' . $this->db->prefixTable('cash_up') . ' MODIFY `note` int NOT NULL DEFAULT 0');
}

View File

@@ -11,16 +11,15 @@ class Migration_add_missing_config extends Migration
*/
public function up(): void
{
log_message('info', 'Adding missing configs.');
$image_values = [
['key' => 'account_number', 'value' => ''], // This has no current maintenance, but it's used in Sales
['key' => 'category_dropdown', 'value' => ''],
['key' => 'smtp_host', 'value' => ''],
['key' => 'smtp_user', 'value' => ''],
['key' => 'smtp_pass', 'value' => ''],
['key' => 'login_form', 'value' => ''],
['key' => 'account_number', 'value' => ''], // This has no current maintenance, but it's used in Sales
['key' => 'category_dropdown', 'value' => ''],
['key' => 'smtp_host', 'value' => ''],
['key' => 'smtp_user', 'value' => ''],
['key' => 'smtp_pass', 'value' => ''],
['key' => 'login_form', 'value' => ''],
['key' => 'receiving_calculate_average_price', 'value' => ''],
['key' => 'payment_message', 'value' => '']
['key' => 'payment_message', 'value' => ''],
];
$this->db->table('app_config')->ignore(true)->insertBatch($image_values);

View File

@@ -11,7 +11,6 @@ class Migration_drop_account_number_index extends Migration
*/
public function up(): void
{
log_message('info', 'Dropping account number index.');
$this->db->query('ALTER TABLE ' . $this->db->prefixTable('customers') . ' DROP INDEX account_number');
$this->db->query('ALTER TABLE ' . $this->db->prefixTable('customers') . ' ADD INDEX account_number (account_number)');
}

View File

@@ -15,7 +15,7 @@ class Migration_Convert_Barcode_Types extends Migration
public function __construct(?Forge $forge = null)
{
$this->appconfig = model(Appconfig::class);
$this->config = config(OSPOS::class)->settings;
$this->config = config(OSPOS::class)->settings;
parent::__construct($forge);
}
@@ -25,19 +25,21 @@ class Migration_Convert_Barcode_Types extends Migration
*/
public function up(): void
{
log_message('info', 'Converting barcode types.');
$old_barcode_type = $this->config['barcode_type'];
switch ($old_barcode_type) {
case 'Code39':
$new_barcode_type = 'C39';
break;
case 'Ean13':
$new_barcode_type = 'EAN13';
break;
case 'Ean8':
$new_barcode_type = 'EAN8';
break;
default:
case 'Code128':
$new_barcode_type = 'C128';
@@ -52,19 +54,21 @@ class Migration_Convert_Barcode_Types extends Migration
*/
public function down(): void
{
log_message('info', 'Converting barcode types.');
$new_barcode_type = $this->config['barcode_type'];
switch ($new_barcode_type) {
case 'C39':
$old_barcode_type = 'Code39';
break;
case 'EAN13':
$old_barcode_type = 'Ean13';
break;
case 'EAN8':
$old_barcode_type = 'Ean8';
break;
default:
case 'C128':
$old_barcode_type = 'Code128';

View File

@@ -12,26 +12,25 @@ class Migration_fix_keys_for_db_upgrade extends Migration
*/
public function up(): void
{
log_message('info', 'Fixing keys for database upgrade.');
helper('migration');
$forge = Database::forge();
$forge = Database::forge();
$fields = [
'deleted' => [
'type' => 'TINYINT',
'type' => 'TINYINT',
'constraint' => 1,
'default' => 0,
'null' => false,
'default' => 0,
'null' => false,
],
];
$forge->modifyColumn('tax_codes', $fields);
if (!indexExists('customers', 'company_name')) {
if (! indexExists('customers', 'company_name')) {
$forge->addKey('company_name', false, false, 'company_name');
$forge->processIndexes('customers');
}
$checkSql = "SELECT CONSTRAINT_NAME FROM information_schema.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND TABLE_NAME = '" . $this->db->prefixTable('sales_items_taxes') . "' AND CONSTRAINT_NAME = 'ospos_sales_items_taxes_ibfk_1'";
$checkSql = "SELECT CONSTRAINT_NAME FROM information_schema.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND TABLE_NAME = '" . $this->db->prefixTable('sales_items_taxes') . "' AND CONSTRAINT_NAME = 'ospos_sales_items_taxes_ibfk_1'";
$foreignKeyExists = $this->db->query($checkSql)->getRow();
if ($foreignKeyExists) {
@@ -52,7 +51,7 @@ class Migration_fix_keys_for_db_upgrade extends Migration
*/
public function down(): void
{
$checkSql = "SELECT CONSTRAINT_NAME FROM information_schema.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND TABLE_NAME = '" . $this->db->prefixTable('sales_items_taxes') . "' AND CONSTRAINT_NAME = 'ospos_sales_items_taxes_ibfk_1'";
$checkSql = "SELECT CONSTRAINT_NAME FROM information_schema.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = DATABASE() AND TABLE_NAME = '" . $this->db->prefixTable('sales_items_taxes') . "' AND CONSTRAINT_NAME = 'ospos_sales_items_taxes_ibfk_1'";
$foreignKeyExists = $this->db->query($checkSql)->getRow();
if ($foreignKeyExists) {

View File

@@ -2,8 +2,8 @@
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
use App\Models\Attribute;
use CodeIgniter\Database\Migration;
use CodeIgniter\Database\ResultInterface;
class fix_duplicate_attributes extends Migration
@@ -23,7 +23,7 @@ class fix_duplicate_attributes extends Migration
'ospos_attribute_links_ibfk_2',
'ospos_attribute_links_ibfk_3',
'ospos_attribute_links_ibfk_4',
'ospos_attribute_links_ibfk_5'
'ospos_attribute_links_ibfk_5',
];
dropForeignKeyConstraints($foreignKeys, 'attribute_links');
@@ -46,6 +46,7 @@ class fix_duplicate_attributes extends Migration
$builder->where('item_id IS NOT NULL');
$builder->groupBy('item_id, definition_id');
$builder->having('COUNT(attribute_id) > 1');
return $builder->get();
}
@@ -53,20 +54,21 @@ class fix_duplicate_attributes extends Migration
* Removes the duplicate attributes from the database.
*
* @param ResultInterface $rows_to_keep A multidimensional associative array containing item_id, definition_id and attribute_id in each row which should be kept in the database.
* @return void
*/
private function remove_duplicate_attributes(ResultInterface $rows_to_keep): void
{
$attribute = model(Attribute::class);
foreach ($rows_to_keep->getResult() as $row) {
$attribute->deleteAttributeLinks($row->item_id, $row->definition_id); // Deletes all attribute links for the item_id/definition_id combination
$attribute->saveAttributeLink($row->item_id, $row->definition_id, $row->attribute_id);
}
}
/**
* Revert a migration step.
*/
public function down(): void {}
public function down(): void
{
}
}

View File

@@ -3,8 +3,6 @@
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
use App\Models\Attribute;
use CodeIgniter\Database\ResultInterface;
class Migration_Attributes_fix_cascading_delete extends Migration
{
@@ -13,20 +11,21 @@ class Migration_Attributes_fix_cascading_delete extends Migration
*/
public function up(): void
{
log_message('info', 'Fixing cascading deletes.');
helper('migration');
$this->db->query("ALTER TABLE `ospos_attribute_links` DROP INDEX `attribute_links_uq3`");
$this->db->query("ALTER TABLE `ospos_attribute_links` DROP COLUMN `generated_unique_column`");
$this->db->query('ALTER TABLE `ospos_attribute_links` DROP INDEX `attribute_links_uq3`');
$this->db->query('ALTER TABLE `ospos_attribute_links` DROP COLUMN `generated_unique_column`');
dropForeignKeyConstraints(['ospos_attribute_links_ibfk_1', 'ospos_attribute_links_ibfk_2'], 'attribute_links');
$this->db->query("ALTER TABLE `ospos_attribute_links` ADD CONSTRAINT `ospos_attribute_links_ibfk_1` FOREIGN KEY (`definition_id`) REFERENCES `ospos_attribute_definitions` (`definition_id`) ON DELETE CASCADE;");
$this->db->query("ALTER TABLE `ospos_attribute_links` ADD CONSTRAINT `ospos_attribute_links_ibfk_2` FOREIGN KEY (`attribute_id`) REFERENCES `ospos_attribute_values` (`attribute_id`) ON DELETE CASCADE;");
$this->db->query('ALTER TABLE `ospos_attribute_links` ADD CONSTRAINT `ospos_attribute_links_ibfk_1` FOREIGN KEY (`definition_id`) REFERENCES `ospos_attribute_definitions` (`definition_id`) ON DELETE CASCADE;');
$this->db->query('ALTER TABLE `ospos_attribute_links` ADD CONSTRAINT `ospos_attribute_links_ibfk_2` FOREIGN KEY (`attribute_id`) REFERENCES `ospos_attribute_values` (`attribute_id`) ON DELETE CASCADE;');
}
/**
* Revert a migration step.
*/
public function down(): void {}
public function down(): void
{
}
}

View File

@@ -11,8 +11,12 @@ class Migration_sessions_migration extends Migration
*/
public function up(): void
{
error_log('Migrating sessions table');
helper('migration');
execute_script(APPPATH . 'Database/Migrations/sqlscripts/3.4.1_migrate_sessions_table.sql');
error_log('Migrating sessions table');
}
/**

View File

@@ -12,27 +12,29 @@ class MigrationOptimizationIndices extends Migration
*/
public function up(): void
{
log_message('info', 'Migrating Optimization Indices');
error_log('Migrating Optimization Indices');
helper('migration');
$forge = Database::forge();
if (!indexExists('attribute_links', 'attribute_links_uq2')) {
if (! indexExists('attribute_links', 'attribute_links_uq2')) {
$columns = [
'item_id',
'receiving_id',
'sale_id',
'definition_id',
'attribute_id'
'attribute_id',
];
$forge->addKey($columns, false, true, 'attribute_links_uq2');
$forge->processIndexes('attribute_links');
}
if (!indexExists('inventory', 'trans_items_trans_date')) {
if (! indexExists('inventory', 'trans_items_trans_date')) {
$forge->addKey(['trans_items', 'trans_date'], false, false, 'trans_items_trans_date');
$forge->processIndexes('inventory');
}
error_log('Migrating Optimization Indices');
}
/**

View File

@@ -3,7 +3,6 @@
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
use Config\Database;
class AttributeLinksUniqueConstraint extends Migration
{
@@ -12,14 +11,7 @@ class AttributeLinksUniqueConstraint extends Migration
*/
public function up(): void
{
helper('migration');
$foreignKeys = [
'ospos_attribute_links_ibfk_1',
'ospos_attribute_links_ibfk_2',
];
dropForeignKeyConstraints($foreignKeys, 'attribute_links');
dropColumnIfExists('ospos_attribute_links', 'generated_unique_column');
error_log('Migrating attribute_links unique constraint started');
execute_script(APPPATH . 'Database/Migrations/sqlscripts/3.4.1_attribute_links_unique_constraint.sql');
}

View File

@@ -1,24 +0,0 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class Migration_MissingConfigKeys extends Migration
{
/**
* Perform a migration step.
*/
public function up(): void
{
helper('migration');
executeScriptWithTransaction(APPPATH . 'Database/Migrations/sqlscripts/3.4.2_missing_config_keys.sql');
}
/**
* Revert a migration step.
*/
public function down(): void
{
}
}

View File

@@ -1,24 +0,0 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class Migration_NullableTaxCategoryId extends Migration
{
/**
* Perform a migration step.
*/
public function up(): void
{
helper('migration');
execute_script(APPPATH . 'Database/Migrations/sqlscripts/3.4.2_nullable_tax_category_id.sql');
}
/**
* Revert a migration step.
*/
public function down(): void
{
}
}

View File

@@ -1,6 +1,8 @@
ALTER TABLE `ospos_attribute_links` DROP CONSTRAINT `ospos_attribute_links_ibfk_1`;
ALTER TABLE `ospos_attribute_links` DROP CONSTRAINT `ospos_attribute_links_ibfk_2`;
# Prevents duplicate attribute links with the same definition_id and item_id.
# This accounts for dropdown rows (null item_id) and rows associated with sales or receivings.
ALTER TABLE `ospos_attribute_links`
ADD COLUMN `generated_unique_column` VARCHAR(255) GENERATED ALWAYS AS (
CASE

View File

@@ -1,11 +0,0 @@
INSERT IGNORE INTO ospos_app_config (`key`, `value`)
VALUES
('msg_msg', ''),
('msg_pwd', ''),
('msg_uid', ''),
('msg_src', ''),
('smtp_timeout', 5000),
('smtp_crypto', 'tls'),
('smtp_port', 587),
('mailpath', '/usr/bin/sendmail'),
('protocol', 'sendmail');

View File

@@ -1,3 +0,0 @@
-- Migration to make tax_category_id nullable in ospos_items
ALTER TABLE ospos_items
MODIFY COLUMN tax_category_id INT NULL;

View File

@@ -2,26 +2,23 @@
namespace App\Events;
use Config\Database;
use Config\App;
use Config\Database;
class Db_log
{
private App $config;
/**
* @return void
*/
public function db_log_queries(): void
{
$this->config = config('App');
if ($this->config->db_log_enabled) {
$filepath = WRITEPATH . 'logs/Query-log-' . date('Y-m-d') . '.log';
$handle = fopen($filepath, "a+");
$message = $this->generate_message();
$handle = fopen($filepath, 'a+b');
$message = $this->generate_message();
if (strlen($message) > 0) {
if ($message !== '') {
fwrite($handle, $message . "\n\n");
}
@@ -30,19 +27,16 @@ class Db_log
}
}
/**
* @return string
*/
private function generate_message(): string
{
$db = Database::connect();
$last_query = $db->getLastQuery();
$affected_rows = $db->affectedRows();
$db = Database::connect();
$last_query = $db->getLastQuery();
$affected_rows = $db->affectedRows();
$execution_time = $this->convert_time($last_query->getDuration());
$message = '*** Query: ' . date('Y-m-d H:i:s T') . ' *******************'
. "\n" . $last_query->getQuery()
. "\n Affected rows: $affected_rows"
. "\n Affected rows: {$affected_rows}"
. "\n Execution Time: " . $execution_time['time'] . ' ' . $execution_time['unit'];
$long_query = ($execution_time['unit'] === 's') && ($execution_time['time'] > 0.5);
@@ -50,22 +44,18 @@ class Db_log
$message .= ' [LONG RUNNING QUERY]';
}
return $this->config->db_log_only_long && !$long_query ? '' : $message;
return $this->config->db_log_only_long && ! $long_query ? '' : $message;
}
/**
* @param float $time
* @return array
*/
private function convert_time(float $time): array
{
$unit = 's';
if ($time <= 0.1 && $time > 0.0001) {
$time = $time * 1000;
$time *= 1000;
$unit = 'ms';
} elseif ($time <= 0.0001) {
$time = $time * 1000000;
$time *= 1000000;
$unit = 'µs';
}

View File

@@ -9,11 +9,11 @@ use Config\OSPOS;
use Config\Services;
/**
* @property my_migration migration;
* @property session session;
* @property appconfig appconfig;
* @property mixed $migration_config
* @property Appconfig appconfig;
* @property MY_Migration migration;
* @property Session session;
* @property mixed $config
* @property mixed $migration_config
*/
class Load_config
{
@@ -26,22 +26,22 @@ class Load_config
{
// Migrations
$migration_config = config('Migrations');
$migration = new MY_Migration($migration_config);
$migration = new MY_Migration($migration_config);
$this->session = session();
// Database Configuration
$config = config(OSPOS::class);
if (!$migration->is_latest()) {
if (! $migration->is_latest()) {
$this->session->destroy();
}
// Language
$language_exists = file_exists('../app/Language/' . current_language_code());
if (current_language_code() == null || current_language() == null || !$language_exists) { // TODO: current_language() is undefined
$config->settings['language'] = 'english';
if (current_language_code() === null || current_language() === null || ! $language_exists) { // TODO: current_language() is undefined
$config->settings['language'] = 'english';
$config->settings['language_code'] = 'en';
}

View File

@@ -4,18 +4,16 @@ namespace App\Events;
class Method
{
/**
* @return void
*/
public static function validate_method(): void
{
$url = $_SERVER['REQUEST_URI'];
$post_required = preg_match('/\/(save|delete*|remove*)\/?\d*?/', $url);
if ($post_required && $_SERVER["REQUEST_METHOD"] != "POST" && empty($_POST)) {
echo "Method not allowed";
die;
if ($post_required && $_SERVER['REQUEST_METHOD'] !== 'POST' && empty($_POST)) {
echo 'Method not allowed';
exit;
}
}
}

View File

@@ -1,33 +0,0 @@
<?php
/**
* Translates the attribute type to the corresponding database column name.
*
* Maps attribute type constants to their corresponding attribute_values table columns.
* Defaults to 'attribute_value' for TEXT, DROPDOWN and CHECKBOX attribute types.
*
* @param string $input The attribute type constant (DATE, DECIMAL, etc.)
* @return string The database column name for storing this attribute type
*/
function getAttributeDataType(string $input): string
{
$columnMap = [
DATE => 'attribute_date',
DECIMAL => 'attribute_decimal',
];
return $columnMap[$input] ?? 'attribute_value';
}
/**
* Validates that the provided data type is an allowed attribute value type.
*
* @param string $dataType
* @return void
*/
function validateAttributeValueType(string $dataType): void
{
if (!in_array($dataType, ATTRIBUTE_VALUE_TYPES, true)) {
throw new InvalidArgumentException('Invalid data type');
}
}

View File

@@ -10,7 +10,7 @@ function create_pdf(string $html, string $filename = ''): string
$dompdf->loadHtml(str_replace(['\n', '\r'], '', $html));
$dompdf->render();
if ($filename != '') {
if ($filename !== '') {
$dompdf->stream($filename . '.pdf');
} else { // TODO: Not all paths return a value.
return $dompdf->output();

View File

@@ -1,13 +1,8 @@
<?php
/**
* @param array $stock_locations
* @param array $attributes
* @return string
*/
function generate_import_items_csv(array $stock_locations, array $attributes): string
{
$csv_headers = pack('CCC', 0xef, 0xbb, 0xbf); // Encode the Byte-Order Mark (BOM) so that UTF-8 File headers display properly in Microsoft Excel
$csv_headers = pack('CCC', 0xEF, 0xBB, 0xBF); // Encode the Byte-Order Mark (BOM) so that UTF-8 File headers display properly in Microsoft Excel
$csv_headers .= 'Id,Barcode,"Item Name",Category,"Supplier ID","Cost Price","Unit Price","Tax 1 Name","Tax 1 Percent","Tax 2 Name","Tax 2 Percent","Reorder Level",Description,"Allow Alt Description","Item has Serial Number",Image,HSN';
$csv_headers .= generate_stock_location_headers($stock_locations);
$csv_headers .= generate_attribute_headers($attributes);
@@ -15,10 +10,6 @@ function generate_import_items_csv(array $stock_locations, array $attributes): s
return $csv_headers;
}
/**
* @param array $locations
* @return string
*/
function generate_stock_location_headers(array $locations): string
{
$location_headers = '';
@@ -30,10 +21,6 @@ function generate_stock_location_headers(array $locations): string
return $location_headers;
}
/**
* @param array $attribute_names
* @return string
*/
function generate_attribute_headers(array $attribute_names): string
{
$attribute_headers = '';
@@ -48,14 +35,14 @@ function generate_attribute_headers(array $attribute_names): string
/**
* Processes a CSV file and returns it.
* @param string $file_name
*
* @return array A multidimensional array of rows found within the file and their associative key/value pairs.
*/
function get_csv_file(string $file_name): array
{
$csv_rows = false;
if (($csv_file = fopen($file_name, 'r')) !== false) {
if (($csv_file = fopen($file_name, 'rb')) !== false) {
helper('security');
$csv_rows = [];
@@ -79,18 +66,14 @@ function get_csv_file(string $file_name): array
return $csv_rows;
}
/**
* @param $file_handle
* @return bool
*/
function bom_exists(&$file_handle): bool
{
$result = false;
$candidate = fread($file_handle, 3);
$result = false;
$candidate = fread($file_handle, 3);
rewind($file_handle);
$bom = pack('CCC', 0xef, 0xbb, 0xbf);
$bom = pack('CCC', 0xEF, 0xBB, 0xBF);
if (0 === strncmp($candidate, $bom, 3)) {
$result = true;

View File

@@ -7,17 +7,18 @@ use Config\OSPOS;
* Returns the currently configured language code.
*
* @param bool $load_system_language When true, the system language is returned.
*
* @return string Returns the default language code if a language code is not configured.
*/
function current_language_code(bool $load_system_language = false): string
{
$employee = model(Employee::class);
$config = config(OSPOS::class)->settings;
$config = config(OSPOS::class)->settings;
if ($employee->is_logged_in() && !$load_system_language) {
if ($employee->is_logged_in() && ! $load_system_language) {
$employee_info = $employee->get_logged_in_employee_info();
if (property_exists($employee_info, 'language_code') && !empty($employee_info->language_code)) {
if (property_exists($employee_info, 'language_code') && ! empty($employee_info->language_code)) {
return $employee_info->language_code;
}
}
@@ -27,20 +28,16 @@ function current_language_code(bool $load_system_language = false): string
return empty($language_code) ? DEFAULT_LANGUAGE_CODE : $language_code;
}
/**
* @param bool $load_system_language
* @return string
*/
function current_language(bool $load_system_language = false): string
{
$employee = model(Employee::class);
$config = config(OSPOS::class)->settings;
$config = config(OSPOS::class)->settings;
// Returns the language of the employee if set or system language if not
if ($employee->is_logged_in() && !$load_system_language) {
if ($employee->is_logged_in() && ! $load_system_language) {
$employee_info = $employee->get_logged_in_employee_info();
if (property_exists($employee_info, 'language') && !empty($employee_info->language)) {
if (property_exists($employee_info, 'language') && ! empty($employee_info->language)) {
return $employee_info->language;
}
}
@@ -51,7 +48,7 @@ function current_language(bool $load_system_language = false): string
}
/**
* @return string[]
* @return list<string>
*/
function get_languages(): array
{
@@ -98,14 +95,15 @@ function get_languages(): array
'ur:urdu' => 'Urdu',
'vi:vietnamese' => 'Vietnamese',
'zh-Hans:simplified-chinese' => 'Chinese (Simplified)',
'zh-Hant:traditional-chinese' => 'Chinese (Traditional)'
'zh-Hant:traditional-chinese' => 'Chinese (Traditional)',
];
asort($languages);
return $languages;
}
/**
* @return string[]
* @return list<string>
*/
function get_timezones(): array
{
@@ -202,12 +200,12 @@ function get_timezones(): array
'Etc/GMT-12' => '(GMT+12:00) Fiji, Kamchatka, Marshall Is.',
'Pacific/Chatham' => '(GMT+12:45) Chatham Islands',
'Pacific/Tongatapu' => '(GMT+13:00) Nuku\'alofa',
'Pacific/Kiritimati' => '(GMT+14:00) Kiritimati'
'Pacific/Kiritimati' => '(GMT+14:00) Kiritimati',
];
}
/**
* @return string[]
* @return list<string>
*/
function get_dateformats(): array
{
@@ -218,55 +216,54 @@ function get_dateformats(): array
'Y/m/d' => 'yyyy/mm/dd',
'd/m/y' => 'dd/mm/yy',
'm/d/y' => 'mm/dd/yy',
'y/m/d' => 'yy/mm/dd'
'y/m/d' => 'yy/mm/dd',
];
}
/**
* @return string[]
* @return list<string>
*/
function get_timeformats(): array
{
return [
'H:i:s' => 'hh:mm:ss (24h)',
'h:i:s a' => 'hh:mm:ss am/pm',
'h:i:s A' => 'hh:mm:ss AM/PM'
'h:i:s A' => 'hh:mm:ss AM/PM',
];
}
/**
* Gets the payment options
*/
function get_payment_options(): array
{
$payments = [];
$config = config(OSPOS::class)->settings;
$config = config(OSPOS::class)->settings;
// TODO: This needs to be switched to a switch statement
if ($config['payment_options_order'] == 'debitcreditcash') { // TODO: ===
$payments[lang('Sales.debit')] = lang('Sales.debit');
if ($config['payment_options_order'] === 'debitcreditcash') { // TODO: ===
$payments[lang('Sales.debit')] = lang('Sales.debit');
$payments[lang('Sales.credit')] = lang('Sales.credit');
$payments[lang('Sales.cash')] = lang('Sales.cash');
} elseif ($config['payment_options_order'] == 'debitcashcredit') { // TODO: ===
$payments[lang('Sales.debit')] = lang('Sales.debit');
$payments[lang('Sales.cash')] = lang('Sales.cash');
$payments[lang('Sales.cash')] = lang('Sales.cash');
} elseif ($config['payment_options_order'] === 'debitcashcredit') { // TODO: ===
$payments[lang('Sales.debit')] = lang('Sales.debit');
$payments[lang('Sales.cash')] = lang('Sales.cash');
$payments[lang('Sales.credit')] = lang('Sales.credit');
} elseif ($config['payment_options_order'] == 'creditdebitcash') { // TODO: ===
} elseif ($config['payment_options_order'] === 'creditdebitcash') { // TODO: ===
$payments[lang('Sales.credit')] = lang('Sales.credit');
$payments[lang('Sales.debit')] = lang('Sales.debit');
$payments[lang('Sales.cash')] = lang('Sales.cash');
} elseif ($config['payment_options_order'] == 'creditcashdebit') { // TODO: ===
$payments[lang('Sales.debit')] = lang('Sales.debit');
$payments[lang('Sales.cash')] = lang('Sales.cash');
} elseif ($config['payment_options_order'] === 'creditcashdebit') { // TODO: ===
$payments[lang('Sales.credit')] = lang('Sales.credit');
$payments[lang('Sales.cash')] = lang('Sales.cash');
$payments[lang('Sales.debit')] = lang('Sales.debit');
$payments[lang('Sales.cash')] = lang('Sales.cash');
$payments[lang('Sales.debit')] = lang('Sales.debit');
} else { // Default: if ($config['payment_options_order == 'cashdebitcredit')
$payments[lang('Sales.cash')] = lang('Sales.cash');
$payments[lang('Sales.debit')] = lang('Sales.debit');
$payments[lang('Sales.cash')] = lang('Sales.cash');
$payments[lang('Sales.debit')] = lang('Sales.debit');
$payments[lang('Sales.credit')] = lang('Sales.credit');
}
$payments[lang('Sales.due')] = lang('Sales.due');
$payments[lang('Sales.due')] = lang('Sales.due');
$payments[lang('Sales.check')] = lang('Sales.check');
// If India (list of country codes include India) then include Unified Payment Interface
@@ -285,10 +282,10 @@ function get_payment_options(): array
function is_right_side_currency_symbol(): bool
{
$config = config(OSPOS::class)->settings;
$fmt = new NumberFormatter($config['number_locale'], NumberFormatter::CURRENCY);
$fmt = new NumberFormatter($config['number_locale'], NumberFormatter::CURRENCY);
$fmt->setSymbol(NumberFormatter::CURRENCY_SYMBOL, $config['currency_symbol']);
return !preg_match('/^¤/', $fmt->getPattern());
return ! preg_match('/^¤/', $fmt->getPattern());
}
/**
@@ -299,93 +296,66 @@ function is_right_side_currency_symbol(): bool
function quantity_decimals(): int
{
$config = config(OSPOS::class)->settings;
return $config['quantity_decimals'] ?? 0;
}
/**
* @return int
*/
function totals_decimals(): int
{
$config = config(OSPOS::class)->settings;
return $config['currency_decimals'] ?? 0;
}
/**
* @return int
*/
function cash_decimals(): int
{
$config = config(OSPOS::class)->settings;
return $config['cash_decimals'] ?? 0;
}
/**
* @return int
*/
function tax_decimals(): int
{
$config = config(OSPOS::class)->settings;
return $config['tax_decimals'] ?? 0;
}
/**
* @param int $date
* @return string
*/
function to_date(int $date = DEFAULT_DATE): string
{
$config = config(OSPOS::class)->settings;
return date($config['dateformat'], $date);
}
/**
* @param int $datetime
* @return string
*/
function to_datetime(int $datetime = DEFAULT_DATETIME): string
{
$config = config(OSPOS::class)->settings;
return date($config['dateformat'] . ' ' . $config['timeformat'], $datetime);
}
/**
* @param string|null $number
* @return string
*/
function to_currency(?string $number): string
{
return to_decimals($number, 'currency_decimals', NumberFormatter::CURRENCY);
}
/**
* @param string|null $number
* @return string
*/
function to_currency_no_money(?string $number): string
{
return to_decimals($number, 'currency_decimals');
}
/**
* @param string|null $number
* @return string
*/
function to_currency_tax(?string $number): string
{
$config = config(OSPOS::class)->settings;
if ($config['tax_included']) { // TODO: ternary notation
return to_decimals($number, 'tax_decimals', NumberFormatter::CURRENCY);
} else {
return to_decimals($number, 'currency_decimals', NumberFormatter::CURRENCY);
}
return to_decimals($number, 'currency_decimals', NumberFormatter::CURRENCY);
}
/**
* @param $number
* @return string
*/
function to_tax_decimals($number): string
{
// TODO: When the tax array is empty the value passed in is an empty string, For now I "untyped" it to get past
@@ -402,10 +372,6 @@ function to_tax_decimals($number): string
return to_decimals($number, 'tax_decimals');
}
/**
* @param string|null $number
* @return string
*/
function to_quantity_decimals(?string $number): string
{
return to_decimals($number, 'quantity_decimals');
@@ -413,19 +379,15 @@ function to_quantity_decimals(?string $number): string
/**
* Converts a string to locale-specific number format for display.
*
* @param string|null $decimals
* @param int $type
* @return string
*/
function to_decimals(?string $number, ?string $decimals = null, int $type = NumberFormatter::DECIMAL): string
{
if (!isset($number)) {
if (! isset($number)) {
return '';
}
$config = config(OSPOS::class)->settings;
$fmt = new NumberFormatter($config['number_locale'], $type);
$fmt = new NumberFormatter($config['number_locale'], $type);
$fmt->setAttribute(NumberFormatter::MIN_FRACTION_DIGITS, empty($decimals) ? DEFAULT_PRECISION : $config[$decimals]);
$fmt->setAttribute(NumberFormatter::MAX_FRACTION_DIGITS, empty($decimals) ? DEFAULT_PRECISION : $config[$decimals]);
@@ -438,7 +400,6 @@ function to_decimals(?string $number, ?string $decimals = null, int $type = Numb
}
/**
* @param string $number
* @return false|float|int|mixed|string
*/
function parse_quantity(string $number): mixed
@@ -447,7 +408,6 @@ function parse_quantity(string $number): mixed
}
/**
* @param string $number
* @return false|float|int|mixed|string
*/
function parse_tax(string $number): mixed
@@ -456,8 +416,6 @@ function parse_tax(string $number): mixed
}
/**
* @param string $number
* @param int|null $decimals
* @return false|float|int|mixed|string
*/
function parse_decimals(string $number, ?int $decimals = null): mixed
@@ -466,13 +424,12 @@ function parse_decimals(string $number, ?int $decimals = null): mixed
return $number;
}
$config = config(OSPOS::class)->settings;
$fmt = new NumberFormatter($config['number_locale'], NumberFormatter::DECIMAL);
if (!$decimals) {
$decimals = intVal($config['currency_decimals']);
if (! $decimals) {
$decimals = (int) ($config['currency_decimals']);
$fmt->setAttribute(NumberFormatter::FRACTION_DIGITS, $decimals);
}
@@ -539,18 +496,15 @@ function dateformat_momentjs(string $php_format): string
'Z' => '', // No equivalent
'c' => '', // No equivalent
'r' => '', // No equivalent
'U' => 'X'
'U' => 'X',
];
return strtr($php_format, $SYMBOLS_MATCHING);
}
/**
* @return string
*/
function dateformat_mysql(): string
{
$config = config(OSPOS::class)->settings;
$config = config(OSPOS::class)->settings;
$php_format = $config['dateformat'];
$SYMBOLS_MATCHING = [
@@ -586,16 +540,12 @@ function dateformat_mysql(): string
'H' => '%k',
'i' => '%i',
's' => '%S',
'u' => '%f'
'u' => '%f',
];
return strtr($php_format, $SYMBOLS_MATCHING);
}
/**
* @param string $php_format
* @return string
*/
function dateformat_bootstrap(string $php_format): string
{
$SYMBOLS_MATCHING = [
@@ -631,51 +581,36 @@ function dateformat_bootstrap(string $php_format): string
'H' => 'hh',
'i' => 'ii',
's' => 'ss',
'u' => ''
'u' => '',
];
return strtr($php_format, $SYMBOLS_MATCHING);
}
/**
* @param string $date
* @return bool
*/
function valid_date(string $date): bool // TODO: need a better name for $date. Perhaps $candidate. Also the function name would be better as is_valid_date()
{
$config = config(OSPOS::class)->settings;
return (DateTime::createFromFormat($config['dateformat'], $date));
return DateTime::createFromFormat($config['dateformat'], $date);
}
/**
* @param string $decimal
* @return bool
*/
function valid_decimal(string $decimal): bool // TODO: need a better name for $decimal. Perhaps $candidate. Also the function name would be better as is_valid_decimal()
{
return (preg_match('/^(\d*\.)?\d+$/', $decimal) === 1);
return preg_match('/^(\d*\.)?\d+$/', $decimal) === 1;
}
/**
* @param array $data
* @return array
*/
function encode_array(array $data): array
{
array_walk($data, function (&$value, $key) {
array_walk($data, static function (&$value, $key) {
$value = rawurlencode($value);
});
return $data;
}
/**
* @param array $data
* @return array
*/
function decode_array(array $data): array
{
array_walk($data, function (&$value, $key) {
array_walk($data, static function (&$value, $key) {
$value = rawurldecode($value);
});

Some files were not shown because too many files have changed in this diff Show More