Compare commits

...

55 Commits

Author SHA1 Message Date
jekkos
09191b9af7 feat: Add OpenAPI 3.1 specification for REST API
Add comprehensive OpenAPI specification for OSPOS REST API including:

- Customers API (CRUD operations)
- Suppliers API (CRUD operations)
- Items API (CRUD operations with inventory quantities)
- Inventory API (stock adjustments)
- Sales API (read-only queries)
- Receivings API (read-only queries)

Features:
- API Key authentication via X-API-Key header
- Pagination with offset/limit parameters
- Soft delete support for customers, suppliers, items
- Batch operations for delete and update
- Search/suggest endpoints for autocomplete
- Comprehensive schema definitions based on existing models

Includes documentation with:
- Endpoint reference tables
- Schema field descriptions
- Implementation notes and discussion topics
- HTTP status codes and response formats

This is a design proposal for discussion before implementation.
2026-03-06 10:27:11 +00:00
jekkos
19eb43270a Fix broken object-level authorization in Employees controller (CVE-worthy) (#4391)
- Non-admin employees can no longer view/modify admin accounts
- Non-admin employees can no longer delete admin accounts
- Non-admin employees can only grant permissions they themselves have
- Added is_admin() and can_modify_employee() methods to Employee model
- Prevents privilege escalation via permission grants

Add tests for BOLA fix and permission delegation

- EmployeeTest: Unit tests for is_admin() and can_modify_employee() methods
- EmployeesControllerTest: Test cases for authorization checks (integration tests require DB)
- ReportsControllerTest: Test validating the constructor redirect fix pattern

Fix return type error in Employees controller

Use $this->response->setJSON() instead of echo json_encode() + return
to properly satisfy the ResponseInterface return type.
2026-03-05 19:46:39 +01:00
jekkos
df4549bb0b Fix Docker image upload by replacing slashes in TAG 2026-03-05 14:46:45 +00:00
jekkos
bdc965be23 Fix: Refresh session language for employee after update. (#4245) 2026-03-04 22:43:52 +01:00
Lucas Lyimo
5c8905aa1b Language Array Key Typo Fix (#4371)
* Fix typo in stock location translation

* Fix typo in stock location key

* Fix typo in Language Receivings files stock_location

* Add Swahili-TZ Language Files

* Add Swahili-KE Language Files
2026-03-04 22:06:17 +01:00
jekkos
690f43578d Use Content-Type application/json for AJAX responses (#4357)
Complete Content-Type application/json fix for all AJAX responses

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

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

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

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

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

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

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

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

Fix critical password validation bypass and add unit tests

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

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

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

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

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

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

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

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

Add GitHub Actions workflow to run PHPUnit tests

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

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

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

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

Fix remaining return type declarations for Sales controller

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

All methods now return ResponseInterface|string to match _reload() signature.
This resolves PHP TypeError errors.
2026-03-04 21:42:35 +01:00
jekkos
0858a1c23c Fix permission bypass in Reports submodule access control (#4389)
The redirect() in constructor returned a RedirectResponse that was never executed, allowing unauthorized access to report submodules. Replaced with header() + exit() to enforce permission checks.
2026-03-04 21:18:42 +01:00
jekkos
3c217bbddd Fix XSS vulnerabilities in invoice_email.php view 2026-03-04 17:54:01 +00:00
jekkos
87a0606141 Fix XSS vulnerability in register (#3965) 2026-03-03 22:40:50 +01:00
jekkos
b6a90f7880 Fix XSS vulnerability in register (#3965) 2026-03-03 22:37:08 +01:00
jekkos
b93359bcaf Fix XSS vulnerability in attributes (#3965) 2026-03-03 22:28:32 +01:00
jekkos
79427481b3 Fix XSS vulnerabilities in invoices + receipts (#3965) (#4363) 2026-02-23 20:14:55 +01:00
dependabot[bot]
b23351a45c Bump jspdf and jspdf-autotable (#4373)
Bumps [jspdf](https://github.com/parallax/jsPDF) and [jspdf-autotable](https://github.com/simonbengtsson/jsPDF-AutoTable). These dependencies needed to be updated together.

Updates `jspdf` from 3.0.2 to 4.1.0
- [Release notes](https://github.com/parallax/jsPDF/releases)
- [Changelog](https://github.com/parallax/jsPDF/blob/master/RELEASE.md)
- [Commits](https://github.com/parallax/jsPDF/compare/v3.0.2...v4.1.0)

Updates `jspdf-autotable` from 5.0.2 to 5.0.7
- [Release notes](https://github.com/simonbengtsson/jsPDF-AutoTable/releases)
- [Commits](https://github.com/simonbengtsson/jsPDF-AutoTable/compare/v5.0.2...v5.0.7)

---
updated-dependencies:
- dependency-name: jspdf
  dependency-version: 4.1.0
  dependency-type: direct:production
- dependency-name: jspdf-autotable
  dependency-version: 5.0.7
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-07 11:46:11 +00:00
dependabot[bot]
bee0c8e364 Bump lodash from 4.17.21 to 4.17.23 (#4369)
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.21 to 4.17.23.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.21...4.17.23)

---
updated-dependencies:
- dependency-name: lodash
  dependency-version: 4.17.23
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-22 20:51:03 +01:00
jekkos
849439c71e Fix multiple XSS vulnerabilities (#3965) (#4356) 2025-12-22 17:21:49 +01:00
Chathura Dilushanka
25680f05db Add equals as permitted URI character (#4329)
This should resolve the 400 error when deleting payments with base64 encoded IDs containing `=`.
2025-12-21 22:41:36 +01:00
jekkos
a11fb099e2 Fix travis build after merge (#4130) 2025-12-21 19:51:21 +01:00
BhojKamal
aee5f31cf5 Add show/hide cost price & profit feature - in reports #4130 (#4350)
* Add show/hide cost price & profit feature

* .env should be ignored.

* js code formatted. .vscode folder ignore for vscode user settings.json

* style is replaced with bootstrap class, formatted and .env.example

* toggle button on table to like in other

* comment corrected.

* class re-factored

* minor refactor

* formatted with 4 space

---------

Co-authored-by: Lotussoft Youngtech <lotussoftyoungtech@gmail.com>
2025-12-21 15:23:39 +05:45
jekkos
643b0ac499 Fix for detailed suppliers report (#4351) 2025-12-17 22:46:59 +01:00
jekkos
3e844f2f89 Escape return_policy in receipt + invoice (#4349)
* Escape return_policy in receipt + invoice

* Enable CSRF using session token (#3632)
2025-12-17 20:39:58 +01:00
jekkos
2acdec431f Fix wrong migration script location (#4285) 2025-12-08 23:06:48 +01:00
jekkos
f245f585da Fix creation of date attribute value (#4310) (#4344)
Fix type hints in case search string is empty in sales
2025-12-02 07:19:14 +01:00
jekkos
e48ab45094 Fix toast notifications in config (#4341) (#4343) 2025-11-28 09:01:07 +01:00
jekkos
46e31b1c16 Allow anonymous giftcard creation (#4278)
* Allow giftcard without person (#4276)

* Update giftcard form validation (#4276)
2025-11-24 22:54:52 +01:00
jekkos
bea69c7aa1 Add DOMPurify to JS includes (#4341) 2025-11-23 22:20:40 +01:00
jekkos
30da69a382 Fix attachment cid (#4314)
* Add attachment cid when sending emails (#4308)

Also check if an encryption key is set before decrypting the SMTP
password.

* Upgrade to CI 4.6.3 (#4308)

* Fix for changing invoice id in email (#4308)
2025-11-23 21:37:32 +01:00
jekkos
6dd5a9162f Add DOMpurify + fix XSS (#4341) 2025-11-23 21:35:47 +01:00
jekkos
26a398f7d2 Add recent releases to issue template (#4317) 2025-11-21 23:55:24 +01:00
jekkos
ce73d9bb31 Add env variable to disallow pwd change (#4325) 2025-11-21 23:46:48 +01:00
jekkos
83af580d40 Add server side validation for password (#4335) 2025-11-21 23:45:47 +01:00
jekkos
ca7adf76c1 Update SECURITY.md contact (#4335) 2025-11-21 23:22:39 +01:00
jekkos
832db664e5 Fix tax configuration pages (#4331) 2025-11-21 22:13:35 +01:00
jekkos
36e73a84af Clean up docker compose setup (#4308) 2025-10-27 21:57:12 +01:00
Joe Williams
bcddf482fe [Feature] Add logging to migrations (#4327)
* `execute_script()` now returns a boolean for error handling.

* Added transaction to `Migration_MissingConfigKeys.up()`.

* Added logging to various migrations.

* Added transaction to `Migration_MissingConfigKeys.up()`.

* Added logging to various migrations.

* Formatting and function call fixes

Fixed a minor formatting issue in the migration helper.
Replaced a few remaining error_log() calls.
Updated executeScriptWithTransaction() to use log_message()

* Function call fix

Replaced the last error_log() calls with log_message().

---------

Co-authored-by: Joe Williams <hey-there-joe@outlook.com>
2025-10-19 22:10:28 -07:00
Joe Williams
759356288b Add transactions to missing config keys migration. (#4318)
* `execute_script()` now returns a boolean for error handling.

* Added transaction to `Migration_MissingConfigKeys.up()`.

* Added `executeScriptWithTransaction()` to migration helpers.

* Many changes for testing; also minor formatting fixes.

* Removed test code and pointed the `NullableTaxCategoryId` migration at the right SQL file.

* Fixed header.php

* Code cleanup from code review:
- Added IGNORE to SQL scripts.
- Added try-catch to executeScriptWithTransaction().
- Various comment changes.

* Fixed naming issue

Nullable tax category ID migration now runs the correct script.

* Updated SQL

Replaced INSERT WHERE NOT EXISTS in missing config keys sql script to use a single INSERT IGNORE.

* Updated migration helper

Updated executeScriptWithTransaction to use transRollback

---------

Co-authored-by: Joe Williams <hey-there-joe@outlook.com>
2025-10-15 22:53:14 -07:00
j2272850861-pixel
d1e5575ac1 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (8 of 8 strings)

Translation: opensourcepos/bootstrap_tables
Translate-URL: https://translate.opensourcepos.org/projects/opensourcepos/bootstrap_tables/pt_BR/
2025-10-10 12:58:48 +02:00
j2272850861-pixel
b3f67a5e0f Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (85 of 85 strings)

Translation: opensourcepos/common
Translate-URL: https://translate.opensourcepos.org/projects/opensourcepos/common/pt_BR/
2025-10-10 12:58:48 +02:00
j2272850861-pixel
41b349134a Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (12 of 12 strings)

Translation: opensourcepos/login
Translate-URL: https://translate.opensourcepos.org/projects/opensourcepos/login/pt_BR/
2025-10-10 12:58:48 +02:00
jekkos
b1f6ae6d35 Fix mount path for uploads (#4308)
Remove duplicated compose sections in nginx version.  We will include
parts of the main file instead of duplicating it here.
2025-08-29 09:12:02 +02:00
dependabot[bot]
4153c69ccd Bump jspdf from 3.0.1 to 3.0.2 (#4309)
Bumps [jspdf](https://github.com/parallax/jsPDF) from 3.0.1 to 3.0.2.
- [Release notes](https://github.com/parallax/jsPDF/releases)
- [Changelog](https://github.com/parallax/jsPDF/blob/master/RELEASE.md)
- [Commits](https://github.com/parallax/jsPDF/compare/v3.0.1...v3.0.2)

---
updated-dependencies:
- dependency-name: jspdf
  dependency-version: 3.0.2
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-29 07:32:54 +02:00
jekkos
87fbd72478 Add generic try/catch in import (#4302) 2025-08-28 00:05:58 +02:00
jekkos
a4ac42b4ad Fix reference to uploads folder (#4270) (#4286) 2025-08-18 21:19:36 +02:00
jekkos
2eff79a8b6 Fix for suspended sales (#4283) (#4303) 2025-08-15 23:12:35 +02:00
Aril Apria Susanto
880fb8faef Translated using Weblate (Indonesian)
Currently translated at 100.0% (327 of 327 strings)

Translation: opensourcepos/config
Translate-URL: https://translate.opensourcepos.org/projects/opensourcepos/config/id/
2025-08-11 10:27:22 +02:00
Aril Apria Susanto
4d2347173b Translated using Weblate (Indonesian)
Currently translated at 100.0% (85 of 85 strings)

Translation: opensourcepos/common
Translate-URL: https://translate.opensourcepos.org/projects/opensourcepos/common/id/
2025-08-11 10:27:22 +02:00
Aril Apria Susanto
82d36d01fb Translated using Weblate (Indonesian)
Currently translated at 100.0% (45 of 45 strings)

Translation: opensourcepos/module
Translate-URL: https://translate.opensourcepos.org/projects/opensourcepos/module/id/
2025-08-11 10:27:22 +02:00
Aril Apria Susanto
13314b7da1 Translated using Weblate (Indonesian)
Currently translated at 100.0% (53 of 53 strings)

Translation: opensourcepos/customers
Translate-URL: https://translate.opensourcepos.org/projects/opensourcepos/customers/id/
2025-08-11 10:27:22 +02:00
jekkos
43808c5970 Revert toast message sanitization (#4302) 2025-08-07 23:49:54 +02:00
jekkos
1615ef3832 Set release version to 3.4.2 2025-08-07 21:06:11 +02:00
jekkos
e089dc5e2c Fix item kits update (#4294) 2025-08-06 23:40:00 +02:00
jekkos
4cf70a95e6 Fix security incident email address (#4298) 2025-07-30 08:05:58 +02:00
jekkos
e08367aaae Allow empty tax category id (#4285) (#4288) 2025-07-29 23:59:23 +02:00
jekkos
9cd2f685ff Fix barcode generation in items (#4270) 2025-07-29 23:56:50 +02:00
jekkos
6800f338e7 Upgrade to ci 4.6.2 (#4296) (#4298) 2025-07-29 23:20:24 +02:00
jekkos
d4ab56b742 Fix migration 20250522000000 (#4284)
* Fix migration errors

Add dropColumnIfExists to migration_helper

* Add config key/values if missing (#4282)
2025-07-16 23:28:24 +02:00
225 changed files with 9497 additions and 5593 deletions

87
.env
View File

@@ -1,87 +0,0 @@
#--------------------------------------------------------------------
# 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,10 +42,12 @@ body:
label: OpensourcePOS Version label: OpensourcePOS Version
description: What version of our software are you running? description: What version of our software are you running?
options: options:
- development (unreleased)
- opensourcepos 3.4.1
- opensourcepos 3.4.0
- opensourcepos 3.3.9 - opensourcepos 3.3.9
- opensourcepos 3.3.8 - opensourcepos 3.3.8
- opensourcepos 3.3.7 - opensourcepos 3.3.7
- development (unreleased)
default: 0 default: 0
validations: validations:
required: true required: true

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

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

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

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

1
.gitignore vendored
View File

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

View File

@@ -15,7 +15,7 @@ script:
- echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin - echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
- docker run --rm -u $(id -u) -v $(pwd):/app opensourcepos/composer:ci4 composer install - 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") - version=$(grep application_version app/Config/App.php | sed "s/.*=\s'\(.*\)';/\1/g")
- sed -i 's/production/development/g' .env - cp .env.example .env && sed -i 's/production/development/g' .env
- sed -i "s/commit_sha1 = 'dev'/commit_sha1 = '$rev'/g" app/Config/OSPOS.php - sed -i "s/commit_sha1 = 'dev'/commit_sha1 = '$rev'/g" app/Config/OSPOS.php
- echo "$version-$branch-$rev" - echo "$version-$branch-$rev"
- npm version "$version-$branch-$rev" --force || true - npm version "$version-$branch-$rev" --force || true
@@ -28,7 +28,7 @@ script:
env: env:
global: global:
- BRANCH=$(echo ${TRAVIS_BRANCH} | sed s/feature\\///) - BRANCH=$(echo ${TRAVIS_BRANCH} | sed s/feature\\///)
- TAG=${TRAVIS_TAG:-$BRANCH} - TAG=$(echo "${TRAVIS_TAG:-$BRANCH}" | tr '/' '-')
- date=`date +%Y%m%d%H%M%S` && branch=${TRAVIS_BRANCH} && rev=`git rev-parse --short=6 HEAD` - date=`date +%Y%m%d%H%M%S` && branch=${TRAVIS_BRANCH} && rev=`git rev-parse --short=6 HEAD`
after_success: after_success:
- docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD" && docker tag "ospos:latest" - docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD" && docker tag "ospos:latest"

295
API.md Normal file
View File

@@ -0,0 +1,295 @@
# OSPOS REST API Design
This document describes the proposed REST API for Open Source Point of Sale (OSPOS).
## Overview
The OSPOS REST API provides programmatic access to:
- **Customers** - Full CRUD operations
- **Suppliers** - Full CRUD operations
- **Items** - Full CRUD operations
- **Inventory** - Stock adjustments (update only)
- **Sales** - Read-only queries
- **Receivings** - Read-only queries
## Authentication
All API endpoints require authentication via an API Key passed in the `X-API-Key` header.
```
X-API-Key: your-api-key-here
```
> **Note:** API Key authentication implementation will be added in a subsequent phase. The spec documents the intended authentication mechanism.
## Base URL
All API endpoints are relative to `/api/v1`.
```
https://your-domain.com/api/v1/customers
```
## Pagination
List endpoints support pagination using `offset` and `limit` query parameters:
| Parameter | Type | Default | Maximum | Description |
|-----------|---------|---------|---------|------------------------------|
| `offset` | integer | 0 | - | Number of records to skip |
| `limit` | integer | 25 | 100 | Number of records to return |
**Example Request:**
```
GET /api/v1/customers?offset=0&limit=25
```
**Example Response:**
```json
{
"total": 150,
"offset": 0,
"limit": 25,
"rows": [
{ "person_id": 1, "first_name": "John", ... },
{ "person_id": 2, "first_name": "Jane", ... }
]
}
```
## Response Format
### Success Response
```json
{
"success": true,
"message": "Customer created successfully",
"id": 42
}
```
### Error Response
```json
{
"success": false,
"message": "Error description here"
}
```
### HTTP Status Codes
| Status Code | Description |
|-------------|--------------------------------------------------|
| 200 | Success |
| 201 | Resource created successfully |
| 400 | Bad request / Invalid input |
| 401 | Unauthorized / Invalid API key |
| 404 | Resource not found |
| 409 | Conflict (e.g., duplicate unique field) |
| 500 | Internal server error |
## Endpoints Summary
### Customers
| Method | Endpoint | Description | Access |
|--------|-------------------------------|--------------------------------|---------|
| GET | `/customers` | List customers | Read |
| POST | `/customers` | Create customer | Write |
| GET | `/customers/{id}` | Get customer by ID | Read |
| PUT | `/customers/{id}` | Update customer | Write |
| DELETE | `/customers/{id}` | Delete customer (soft delete) | Write |
| POST | `/customers/batch-delete` | Delete multiple customers | Write |
| GET | `/customers/suggest` | Autocomplete suggestions | Read |
### Suppliers
| Method | Endpoint | Description | Access |
|--------|-------------------------------|--------------------------------|---------|
| GET | `/suppliers` | List suppliers | Read |
| POST | `/suppliers` | Create supplier | Write |
| GET | `/suppliers/{id}` | Get supplier by ID | Read |
| PUT | `/suppliers/{id}` | Update supplier | Write |
| DELETE | `/suppliers/{id}` | Delete supplier (soft delete) | Write |
| POST | `/suppliers/batch-delete` | Delete multiple suppliers | Write |
| GET | `/suppliers/suggest` | Autocomplete suggestions | Read |
### Items
| Method | Endpoint | Description | Access |
|--------|-------------------------------|--------------------------------|---------|
| GET | `/items` | List items | Read |
| POST | `/items` | Create item | Write |
| GET | `/items/{id}` | Get item by ID | Read |
| PUT | `/items/{id}` | Update item | Write |
| DELETE | `/items/{id}` | Delete item (soft delete) | Write |
| POST | `/items/batch-delete` | Delete multiple items | Write |
| POST | `/items/batch-update` | Update multiple items | Write |
| GET | `/items/suggest` | Autocomplete suggestions | Read |
| GET | `/items/{id}/quantities` | Get stock quantities | Read |
### Inventory
| Method | Endpoint | Description | Access |
|--------|-------------------------------|--------------------------------|---------|
| GET | `/inventory` | List inventory transactions | Read |
| POST | `/inventory` | Create inventory adjustment | Write |
| POST | `/inventory/bulk` | Bulk inventory adjustments | Write |
### Sales (Read-Only)
| Method | Endpoint | Description | Access |
|--------|-------------------------------|--------------------------------|---------|
| GET | `/sales` | List sales | Read |
| GET | `/sales/{id}` | Get sale details | Read |
| GET | `/sales/{id}/items` | Get sale items | Read |
| GET | `/sales/{id}/payments` | Get sale payments | Read |
### Receivings (Read-Only)
| Method | Endpoint | Description | Access |
|--------|-------------------------------|--------------------------------|---------|
| GET | `/receivings` | List receivings | Read |
| GET | `/receivings/{id}` | Get receiving details | Read |
| GET | `/receivings/{id}/items` | Get receiving items | Read |
## Schema Reference
### Common Fields
#### Person Fields (base for Customer, Supplier)
| Field | Type | Description |
|---------------|-----------|------------------------------|
| `first_name` | string | First name (required) |
| `last_name` | string | Last name (required) |
| `gender` | integer | Gender (0=male, 1=female) |
| `phone_number`| string | Phone number |
| `email` | string | Email address |
| `address_1` | string | Address line 1 |
| `address_2` | string | Address line 2 |
| `city` | string | City |
| `state` | string | State/Province |
| `zip` | string | Postal/ZIP code |
| `country` | string | Country |
| `comments` | string | Additional notes |
### Customer Fields
Extends Person fields with:
| Field | Type | Description |
|--------------------|-----------|------------------------------------|
| `person_id` | integer | Unique identifier (read-only) |
| `account_number` | string | Customer account number |
| `taxable` | integer | Taxable status (0/1) |
| `tax_id` | string | Tax identification number |
| `sales_tax_code_id`| integer | Sales tax code ID |
| `discount` | decimal | Discount percentage/amount |
| `discount_type` | integer | Discount type (0=percent, 1=fixed) |
| `company_name` | string | Company name |
| `package_id` | integer | Rewards package ID |
| `points` | integer | Rewards points balance |
| `consent` | integer | Consent status (0/1) |
### Supplier Fields
Extends Person fields with:
| Field | Type | Description |
|-----------------|-----------|-------------------------------------|
| `person_id` | integer | Unique identifier (read-only) |
| `company_name` | string | Company name |
| `account_number`| string | Supplier account number |
| `tax_id` | string | Tax identification number |
| `agency_name` | string | Agency name |
| `category` | integer | Category (0=goods, 1=cost) |
### Item Fields
| Field | Type | Required | Description |
|----------------------|-----------|----------|--------------------------------------|
| `item_id` | integer | auto | Unique identifier (read-only) |
| `name` | string | yes | Item name |
| `category` | string | yes | Item category |
| `supplier_id` | integer | no | Supplier ID |
| `item_number` | string | no | Barcode/SKU |
| `description` | string | no | Item description |
| `cost_price` | decimal | no | Cost price |
| `unit_price` | decimal | yes | Selling price |
| `reorder_level` | decimal | no | Reorder threshold |
| `receiving_quantity` | decimal | no | Receiving quantity (default 1) |
| `allow_alt_description`| integer | no | Allow alt description (0/1) |
| `is_serialized` | integer | no | Has serial number (0/1) |
| `stock_type` | integer | no | Stock type (0=stocked, 1=non-stocked)|
| `item_type` | integer | no | Item type (0=standard, 1=kit, 2=temp)|
| `tax_category_id` | integer | no | Tax category ID |
| `qty_per_pack` | decimal | no | Quantity per pack |
| `pack_name` | string | no | Pack name |
| `hsn_code` | string | no | HSN code |
### Inventory Adjustment
| Field | Type | Required | Description |
|------------------|-----------|----------|--------------------------------------|
| `item_id` | integer | yes | Item ID to adjust |
| `trans_inventory`| decimal | yes | Quantity change (+ add, - remove) |
| `trans_location` | integer | no | Stock location ID |
| `trans_comment` | string | no | Reason for adjustment |
## OpenAPI Specification
The complete OpenAPI 3.1.0 specification is available at:
- **YAML format:** `/public/api/openapi.yaml`
This specification can be used with:
- [Swagger UI](https://swagger.io/tools/swagger-ui/) for interactive documentation
- [Swagger Codegen](https://swagger.io/tools/swagger-codegen/) to generate client SDKs
- [OpenAPI Generator](https://openapi-generator.tech/) for code generation
- API testing tools like Postman or Insomnia
## Implementation Notes
### Phase 1: Core Endpoints (Proposed)
1. Customers API (full CRUD)
2. Suppliers API (full CRUD)
3. Items API (full CRUD)
4. Inventory adjustments API (create only)
### Phase 2: Read-Only Endpoints (Proposed)
1. Sales API (read-only)
2. Receivings API (read-only)
### Phase 3: Extended Features (Future)
1. Batch operations for all endpoints
2. Search/filter capabilities
3. Authorization/permissions integration
4. Rate limiting
5. API key management interface
## Discussion Topics
The following aspects of the API design are open for discussion:
1. **Field naming conventions**: Currently following existing database column names. Should we use camelCase for JSON?
2. **Batch operations**: Current design separates batch-delete and batch-update. Should we consolidate?
3. **Date formats**: Using ISO 8601 (date-time). Is timezone handling needed?
4. **Error response structure**: Current format uses `{success, message}`. Should we include error codes?
5. **Relationship representations**: Should nested resources (e.g., sale items) always be included?
6. **Inventory adjustments**: Should we support setting absolute quantities vs. relative changes?
7. **Authorization integration**: How should API access integrate with existing employee permissions?
8. **Stock locations**: Multiple locations per item - do we need location-specific endpoints?

View File

@@ -1,4 +1,5 @@
[unreleased]: https://github.com/opensourcepos/opensourcepos/compare/3.4.0...HEAD [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.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.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 [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. 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. 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. 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. 5. Open `.env` file and modify credentials to connect to your database if needed. (First copy .env.example to .env and update)
7. Go to your install `public` dir via the browser. 7. Go to your install `public` dir via the browser.
8. Log in using 8. Log in using
- Username: admin - Username: admin

View File

@@ -18,7 +18,8 @@ We release patches for security vulnerabilities. Which versions are eligible to
| --------- | -------------------------------------------------- | | --------- | -------------------------------------------------- |
| 7.3 | 3.3.5 | | 7.3 | 3.3.5 |
| 9.8 | 3.3.6 | | 9.8 | 3.3.6 |
| 6.8 | 3.4.2 |
## Reporting a Vulnerability ## Reporting a Vulnerability
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. 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.

View File

@@ -12,7 +12,7 @@ class App extends BaseConfig
* *
* @var string * @var string
*/ */
public string $application_version = '3.4.1'; public string $application_version = '3.4.2';
/** /**
* This is the commit hash for the version you are currently using. * This is the commit hash for the version you are currently using.
@@ -117,7 +117,7 @@ class App extends BaseConfig
| DO NOT CHANGE THIS UNLESS YOU FULLY UNDERSTAND THE REPERCUSSIONS!! | DO NOT CHANGE THIS UNLESS YOU FULLY UNDERSTAND THE REPERCUSSIONS!!
| |
*/ */
public string $permittedURIChars = 'a-z 0-9~%.:_\-'; public string $permittedURIChars = 'a-z 0-9~%.:_\-=';
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------

View File

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

View File

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

View File

@@ -13,9 +13,9 @@ class Security extends BaseConfig
* *
* Protection Method for Cross Site Request Forgery protection. * Protection Method for Cross Site Request Forgery protection.
* *
* @var string 'cookie' or 'session' * @var string|false 'cookie', 'session', or false
*/ */
public string $csrfProtection = 'cookie'; public string|false $csrfProtection = 'session';
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
@@ -71,7 +71,7 @@ class Security extends BaseConfig
* *
* Regenerate CSRF Token on every submission. * Regenerate CSRF Token on every submission.
*/ */
public bool $regenerate = true; public bool $regenerate = false;
/** /**
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------

View File

@@ -2,11 +2,12 @@
namespace Config; namespace Config;
use CodeIgniter\Config\BaseService; use Locale;
use CodeIgniter\HTTP\IncomingRequest;
use Config\Services as AppServices;
use HTMLPurifier; use HTMLPurifier;
use HTMLPurifier_Config; use HTMLPurifier_Config;
use CodeIgniter\Config\BaseService;
use Config\Services as AppServices;
use CodeIgniter\HTTP\IncomingRequest;
/** /**
* Services Configuration file. * Services Configuration file.

View File

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

View File

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

View File

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

View File

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

View File

@@ -3,6 +3,7 @@
namespace App\Controllers; namespace App\Controllers;
use App\Models\Module; use App\Models\Module;
use CodeIgniter\HTTP\ResponseInterface;
use Config\Services; use Config\Services;
/** /**
@@ -25,7 +26,7 @@ class Employees extends Persons
* *
* @return void * @return void
*/ */
public function getSearch(): void public function getSearch(): ResponseInterface
{ {
$search = $this->request->getGet('search'); $search = $this->request->getGet('search');
$limit = $this->request->getGet('limit', FILTER_SANITIZE_NUMBER_INT); $limit = $this->request->getGet('limit', FILTER_SANITIZE_NUMBER_INT);
@@ -41,39 +42,47 @@ class Employees extends Persons
$data_rows[] = get_person_data_row($person); $data_rows[] = get_person_data_row($person);
} }
echo json_encode(['total' => $total_rows, 'rows' => $data_rows]); return $this->response->setJSON(['total' => $total_rows, 'rows' => $data_rows]);
} }
/** /**
* AJAX called function gives search suggestions based on what is being searched for. * AJAX called function gives search suggestions based on what is being searched for.
* *
* @return void * @return ResponseInterface
*/ */
public function getSuggest(): void public function getSuggest(): ResponseInterface
{ {
$search = $this->request->getGet('term'); $search = $this->request->getGet('term');
$suggestions = $this->employee->get_search_suggestions($search, 25, true); $suggestions = $this->employee->get_search_suggestions($search, 25, true);
echo json_encode($suggestions); return $this->response->setJSON($suggestions);
} }
/** /**
* @return void * @return ResponseInterface
*/ */
public function suggest_search(): void public function suggest_search(): ResponseInterface
{ {
$search = $this->request->getPost('term'); $search = $this->request->getPost('term');
$suggestions = $this->employee->get_search_suggestions($search); $suggestions = $this->employee->get_search_suggestions($search);
echo json_encode($suggestions); return $this->response->setJSON($suggestions);
} }
/** /**
* Loads the employee edit form * Loads the employee edit form
* @return string
*/ */
public function getView(int $employee_id = NEW_ENTRY): void public function getView(int $employee_id = NEW_ENTRY): string
{ {
$person_info = $this->employee->get_info($employee_id); $person_info = $this->employee->get_info($employee_id);
$current_user = $this->employee->get_logged_in_employee_info();
if ($employee_id != NEW_ENTRY && !$this->employee->can_modify_employee($person_info->person_id, $current_user->person_id)) {
header('Location: ' . base_url('no_access/employees/employees'));
exit();
}
foreach (get_object_vars($person_info) as $property => $value) { foreach (get_object_vars($person_info) as $property => $value) {
$person_info->$property = $value; $person_info->$property = $value;
} }
@@ -98,14 +107,28 @@ class Employees extends Persons
} }
$data['all_subpermissions'] = $permissions; $data['all_subpermissions'] = $permissions;
echo view('employees/form', $data); return view('employees/form', $data);
} }
/** /**
* Inserts/updates an employee * Inserts/updates an employee
* @return ResponseInterface
*/ */
public function postSave(int $employee_id = NEW_ENTRY): void public function postSave(int $employee_id = NEW_ENTRY): ResponseInterface
{ {
$current_user = $this->employee->get_logged_in_employee_info();
if ($employee_id != NEW_ENTRY) {
$target_employee = $this->employee->get_info($employee_id);
if (!$this->employee->can_modify_employee($target_employee->person_id, $current_user->person_id)) {
return $this->response->setJSON([
'success' => false,
'message' => lang('Employees.error_updating_admin'),
'id' => NEW_ENTRY
]);
}
}
$first_name = $this->request->getPost('first_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS); // TODO: duplicated code $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); $last_name = $this->request->getPost('last_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$email = strtolower($this->request->getPost('email', FILTER_SANITIZE_EMAIL)); $email = strtolower($this->request->getPost('email', FILTER_SANITIZE_EMAIL));
@@ -130,11 +153,16 @@ class Employees extends Persons
]; ];
$grants_array = []; $grants_array = [];
$is_admin = $this->employee->is_admin($current_user->person_id);
foreach ($this->module->get_all_permissions()->getResult() as $permission) { foreach ($this->module->get_all_permissions()->getResult() as $permission) {
$grants = []; $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) {
if (!$is_admin && !$this->employee->has_grant($permission->permission_id, $current_user->person_id)) {
continue;
}
$grants['permission_id'] = $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['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_array[] = $grants;
@@ -163,20 +191,25 @@ class Employees extends Persons
if ($this->employee->save_employee($person_data, $employee_data, $grants_array, $employee_id)) { if ($this->employee->save_employee($person_data, $employee_data, $grants_array, $employee_id)) {
// New employee // New employee
if ($employee_id == NEW_ENTRY) { if ($employee_id == NEW_ENTRY) {
echo json_encode([ return $this->response->setJSON([
'success' => true, 'success' => true,
'message' => lang('Employees.successful_adding') . ' ' . $first_name . ' ' . $last_name, 'message' => lang('Employees.successful_adding') . ' ' . $first_name . ' ' . $last_name,
'id' => $employee_data['person_id'] 'id' => $employee_data['person_id']
]); ]);
} else { // Existing employee } else { // Existing employee
echo json_encode([ $logged_in_employee_id = session()->get('person_id');
if ($employee_id == $logged_in_employee_id) {
session()->set('language_code', $employee_data['language_code']);
session()->set('language', $employee_data['language']);
}
return $this->response->setJSON([
'success' => true, 'success' => true,
'message' => lang('Employees.successful_updating') . ' ' . $first_name . ' ' . $last_name, 'message' => lang('Employees.successful_updating') . ' ' . $first_name . ' ' . $last_name,
'id' => $employee_id 'id' => $employee_id
]); ]);
} }
} else { // Failure } else { // Failure
echo json_encode([ return $this->response->setJSON([
'success' => false, 'success' => false,
'message' => lang('Employees.error_adding_updating') . ' ' . $first_name . ' ' . $last_name, 'message' => lang('Employees.error_adding_updating') . ' ' . $first_name . ' ' . $last_name,
'id' => NEW_ENTRY 'id' => NEW_ENTRY
@@ -186,18 +219,28 @@ class Employees extends Persons
/** /**
* This deletes employees from the employees table * This deletes employees from the employees table
* @return ResponseInterface
*/ */
public function postDelete(): void public function postDelete(): ResponseInterface
{ {
$employees_to_delete = $this->request->getPost('ids', FILTER_SANITIZE_FULL_SPECIAL_CHARS); $employees_to_delete = $this->request->getPost('ids', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
$current_user = $this->employee->get_logged_in_employee_info();
if (!$this->employee->is_admin($current_user->person_id)) {
foreach ($employees_to_delete as $emp_id) {
if ($this->employee->is_admin((int)$emp_id)) {
return $this->response->setJSON(['success' => false, 'message' => lang('Employees.error_deleting_admin')]);
}
}
}
if ($this->employee->delete_list($employees_to_delete)) { // TODO: this is passing a string, but delete_list expects an array if ($this->employee->delete_list($employees_to_delete)) { // TODO: this is passing a string, but delete_list expects an array
echo json_encode([ return $this->response->setJSON([
'success' => true, '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 { } else {
echo json_encode(['success' => false, 'message' => lang('Employees.cannot_be_deleted')]); return $this->response->setJSON(['success' => false, 'message' => lang('Employees.cannot_be_deleted')]);
} }
} }
@@ -205,12 +248,12 @@ class Employees extends Persons
* Checks an employee username against the database. Used in app\Views\employees\form.php * Checks an employee username against the database. Used in app\Views\employees\form.php
* *
* @param $employee_id * @param $employee_id
* @return void * @return ResponseInterface
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function getCheckUsername($employee_id): void public function getCheckUsername($employee_id): ResponseInterface
{ {
$exists = $this->employee->username_exists($employee_id, $this->request->getGet('username')); $exists = $this->employee->username_exists($employee_id, $this->request->getGet('username'));
echo !$exists ? 'true' : 'false'; return $this->response->setJSON(!$exists ? 'true' : 'false');
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -15,10 +15,12 @@ use App\Models\Stock_location;
use App\Models\Supplier; use App\Models\Supplier;
use App\Models\Tax_category; use App\Models\Tax_category;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Images\Handlers\BaseHandler; use CodeIgniter\Images\Handlers\BaseHandler;
use CodeIgniter\HTTP\DownloadResponse; use CodeIgniter\HTTP\DownloadResponse;
use Config\OSPOS; use Config\OSPOS;
use Config\Services; use Config\Services;
use Exception;
use ReflectionException; use ReflectionException;
require_once('Secure_Controller.php'); require_once('Secure_Controller.php');
@@ -64,9 +66,9 @@ class Items extends Secure_Controller
} }
/** /**
* @return void * @return string
*/ */
public function getIndex(): void public function getIndex(): string
{ {
$this->session->set('allow_temp_items', 0); $this->session->set('allow_temp_items', 0);
@@ -85,14 +87,14 @@ class Items extends Secure_Controller
'temporary' => lang('Items.temp') 'temporary' => lang('Items.temp')
]; ];
echo view('items/manage', $data); return view('items/manage', $data);
} }
/** /**
* Returns Items table data rows. This will be called with AJAX. * Returns Items table data rows. This will be called with AJAX.
* @noinspection PhpUnused * @noinspection PhpUnused
**/ **/
public function getSearch(): void public function getSearch(): ResponseInterface
{ {
$search = $this->request->getGet('search'); $search = $this->request->getGet('search');
$limit = $this->request->getGet('limit', FILTER_SANITIZE_NUMBER_INT); $limit = $this->request->getGet('limit', FILTER_SANITIZE_NUMBER_INT);
@@ -133,16 +135,16 @@ class Items extends Secure_Controller
} }
} }
echo json_encode(['total' => $total_rows, 'rows' => $data_rows]); return $this->response->setJSON(['total' => $total_rows, 'rows' => $data_rows]);
} }
/** /**
* AJAX function. Processes thumbnail of image. Called via tabular_helper * AJAX function. Processes thumbnail of image. Called via tabular_helper
* @param string $pic_filename * @param string $pic_filename
* @return void * @return ResponseInterface
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function getPicThumb(string $pic_filename): void public function getPicThumb(string $pic_filename): ResponseInterface
{ {
helper('file'); helper('file');
@@ -163,15 +165,17 @@ class Items extends Secure_Controller
$this->response->setContentType(mime_content_type($thumb_path)); $this->response->setContentType(mime_content_type($thumb_path));
$this->response->setBody(file_get_contents($thumb_path)); $this->response->setBody(file_get_contents($thumb_path));
$this->response->send();
} }
return $this->response;
} }
/** /**
* Gives search suggestions based on what is being searched for * Gives search suggestions based on what is being searched for
* @return ResponseInterface
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function suggest_search(): void public function suggest_search(): ResponseInterface
{ {
$options = [ $options = [
'search_custom' => $this->request->getPost('search_custom'), 'search_custom' => $this->request->getPost('search_custom'),
@@ -181,71 +185,73 @@ class Items extends Secure_Controller
$search = $this->request->getPost('term'); $search = $this->request->getPost('term');
$suggestions = $this->item->get_search_suggestions($search, $options); $suggestions = $this->item->get_search_suggestions($search, $options);
echo json_encode($suggestions); return $this->response->setJSON($suggestions);
} }
/** /**
* AJAX Function used to get search suggestions from the model and return them in JSON format * AJAX Function used to get search suggestions from the model and return them in JSON format
* @return void * @return ResponseInterface
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function getSuggest(): void public function getSuggest(): ResponseInterface
{ {
$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 = $this->item->get_search_suggestions($search, ['search_custom' => false, 'is_deleted' => false], true);
echo json_encode($suggestions); return $this->response->setJSON($suggestions);
} }
/** /**
* @return void * @return ResponseInterface
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function getSuggestLowSell(): void public function getSuggestLowSell(): ResponseInterface
{ {
$suggestions = $this->item->get_low_sell_suggestions($this->request->getPostGet('name')); $suggestions = $this->item->get_low_sell_suggestions($this->request->getPostGet('name'));
echo json_encode($suggestions); return $this->response->setJSON($suggestions);
} }
/** /**
* @return void * @return ResponseInterface
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function getSuggestKits(): void public function getSuggestKits(): ResponseInterface
{ {
$suggestions = $this->item->get_kit_search_suggestions($this->request->getGet('term'), ['search_custom' => false, 'is_deleted' => false], true); $suggestions = $this->item->get_kit_search_suggestions($this->request->getGet('term'), ['search_custom' => false, 'is_deleted' => false], true);
echo json_encode($suggestions); return $this->response->setJSON($suggestions);
} }
/** /**
* Gives search suggestions based on what is being searched for. Called from the view. * Gives search suggestions based on what is being searched for. Called from the view.
* @return ResponseInterface
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function getSuggestCategory(): void public function getSuggestCategory(): ResponseInterface
{ {
$suggestions = $this->item->get_category_suggestions($this->request->getGet('term')); $suggestions = $this->item->get_category_suggestions($this->request->getGet('term'));
echo json_encode($suggestions); return $this->response->setJSON($suggestions);
} }
/** /**
* Gives search suggestions based on what is being searched for. * Gives search suggestions based on what is being searched for.
* @return ResponseInterface
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function getSuggestLocation(): void public function getSuggestLocation(): ResponseInterface
{ {
$suggestions = $this->item->get_location_suggestions($this->request->getGet('term')); $suggestions = $this->item->get_location_suggestions($this->request->getGet('term'));
echo json_encode($suggestions); return $this->response->setJSON($suggestions);
} }
/** /**
* @param string $item_ids * @param string $item_ids
* @return void * @return ResponseInterface
*/ */
public function getRow(string $item_ids): void // TODO: An array would be better for parameter. public function getRow(string $item_ids): ResponseInterface // TODO: An array would be better for parameter.
{ {
$item_infos = $this->item->get_multiple_info(explode(':', $item_ids), $this->item_lib->get_item_location()); $item_infos = $this->item->get_multiple_info(explode(':', $item_ids), $this->item_lib->get_item_location());
@@ -255,14 +261,14 @@ class Items extends Secure_Controller
$result[$item_info->item_id] = get_item_data_row($item_info); $result[$item_info->item_id] = get_item_data_row($item_info);
} }
echo json_encode($result); return $this->response->setJSON($result);
} }
/** /**
* @param int $item_id * @param int $item_id
* @return void * @return string
*/ */
public function getView(int $item_id = NEW_ENTRY): void // TODO: Long function. Perhaps we need to refactor out some methods. public function getView(int $item_id = NEW_ENTRY): string // TODO: Long function. Perhaps we need to refactor out some methods.
{ {
$item_id ??= NEW_ENTRY; $item_id ??= NEW_ENTRY;
@@ -394,17 +400,17 @@ class Items extends Secure_Controller
$data['selected_low_sell_item'] = ''; $data['selected_low_sell_item'] = '';
} }
echo view('items/form', $data); return view('items/form', $data);
} }
/** /**
* AJAX called function which returns the update inventory form view for an item * AJAX called function which returns the update inventory form view for an item
* *
* @param int $item_id * @param int $item_id
* @return void * @return string
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function getInventory(int $item_id = NEW_ENTRY): void public function getInventory(int $item_id = NEW_ENTRY): string
{ {
$item_info = $this->item->get_info($item_id); // TODO: Duplicate code $item_info = $this->item->get_info($item_id); // TODO: Duplicate code
@@ -423,15 +429,15 @@ class Items extends Secure_Controller
$data['item_quantities'][$location['location_id']] = $quantity; $data['item_quantities'][$location['location_id']] = $quantity;
} }
echo view('items/form_inventory', $data); return view('items/form_inventory', $data);
} }
/** /**
* @param int $item_id * @param int $item_id
* @return void * @return string
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function getCountDetails(int $item_id = NEW_ENTRY): void public function getCountDetails(int $item_id = NEW_ENTRY): string
{ {
$item_info = $this->item->get_info($item_id); // TODO: Duplicate code $item_info = $this->item->get_info($item_id); // TODO: Duplicate code
@@ -450,17 +456,17 @@ class Items extends Secure_Controller
$data['item_quantities'][$location['location_id']] = $quantity; $data['item_quantities'][$location['location_id']] = $quantity;
} }
echo view('items/form_count_details', $data); return view('items/form_count_details', $data);
} }
/** /**
* AJAX called function that generates barcodes for selected items. * AJAX called function that generates barcodes for selected items.
* *
* @param string $item_ids Colon separated list of item_id values to generate barcodes for. * @param string $item_ids Colon separated list of item_id values to generate barcodes for.
* @return void * @return string
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function getGenerateBarcodes(string $item_ids): void // TODO: Passing these through as a string instead of an array limits the contents of the item_ids. Perhaps a better approach would to serialize as JSON in an array and pass through post variables? public function getGenerateBarcodes(string $item_ids): string // TODO: Passing these through as a string instead of an array limits the contents of the item_ids. Perhaps a better approach would to serialize as JSON in an array and pass through post variables?
{ {
$item_ids = explode(':', $item_ids); $item_ids = explode(':', $item_ids);
$result = $this->item->get_multiple_info($item_ids, $this->item_lib->get_item_location())->getResultArray(); $result = $this->item->get_multiple_info($item_ids, $this->item_lib->get_item_location())->getResultArray();
@@ -476,16 +482,16 @@ class Items extends Secure_Controller
} }
$data['items'] = $result; $data['items'] = $result;
echo view('barcodes/barcode_sheet', $data); return view('barcodes/barcode_sheet', $data);
} }
/** /**
* Gathers attribute value information for an item and returns it in a view. * Gathers attribute value information for an item and returns it in a view.
* *
* @param int $item_id * @param int $item_id
* @return void * @return string
*/ */
public function getAttributes(int $item_id = NEW_ENTRY): void public function getAttributes(int $item_id = NEW_ENTRY): string
{ {
$data['item_id'] = $item_id; $data['item_id'] = $item_id;
$definition_ids = json_decode($this->request->getGet('definition_ids') ?? '', true); $definition_ids = json_decode($this->request->getGet('definition_ids') ?? '', true);
@@ -513,15 +519,15 @@ class Items extends Secure_Controller
unset($data['definition_names'][$definition_id]); unset($data['definition_names'][$definition_id]);
} }
echo view('attributes/item', $data); return view('attributes/item', $data);
} }
/** /**
* @param int $item_id * @param int $item_id
* @return void * @return string
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function postAttributes(int $item_id = NEW_ENTRY): void public function postAttributes(int $item_id = NEW_ENTRY): string
{ {
$data['item_id'] = $item_id; $data['item_id'] = $item_id;
$definition_ids = json_decode($this->request->getPost('definition_ids'), true); $definition_ids = json_decode($this->request->getPost('definition_ids'), true);
@@ -549,16 +555,16 @@ class Items extends Secure_Controller
unset($data['definition_names'][$definition_id]); unset($data['definition_names'][$definition_id]);
} }
echo view('attributes/item', $data); return view('attributes/item', $data);
} }
/** /**
* Edit multiple items. Used in app/Views/items/manage.php * Edit multiple items. Used in app/Views/items/manage.php
* *
* @return void * @return string
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function getBulkEdit(): void public function getBulkEdit(): string
{ {
$suppliers = ['' => lang('Items.none')]; $suppliers = ['' => lang('Items.none')];
@@ -579,14 +585,15 @@ class Items extends Secure_Controller
0 => lang('Items.change_all_to_unserialized') 0 => lang('Items.change_all_to_unserialized')
]; ];
echo view('items/form_bulk', $data); return view('items/form_bulk', $data);
} }
/** /**
* @param int $item_id * @param int $item_id
* @return ResponseInterface
* @throws ReflectionException * @throws ReflectionException
*/ */
public function postSave(int $item_id = NEW_ENTRY): void public function postSave(int $item_id = NEW_ENTRY): ResponseInterface
{ {
$upload_data = $this->upload_image(); $upload_data = $this->upload_image();
$upload_success = empty($upload_data['error']); $upload_success = empty($upload_data['error']);
@@ -635,10 +642,10 @@ class Items extends Secure_Controller
$item_data['reorder_level'] = 0; $item_data['reorder_level'] = 0;
} }
$tax_category_id = intval($this->request->getPost('tax_category_id')); $tax_category_id = $this->request->getPost('tax_category_id');
if (!isset($tax_category_id)) { if (!isset($tax_category_id)) {
$item_data['tax_category_id'] = ''; $item_data['tax_category_id'] = null;
} else { } else {
$item_data['tax_category_id'] = empty($this->request->getPost('tax_category_id')) ? null : intval($this->request->getPost('tax_category_id')); $item_data['tax_category_id'] = empty($this->request->getPost('tax_category_id')) ? null : intval($this->request->getPost('tax_category_id'));
} }
@@ -716,16 +723,16 @@ class Items extends Secure_Controller
if ($success && $upload_success) { if ($success && $upload_success) {
$message = lang('Items.successful_' . ($new_item ? 'adding' : 'updating')) . ' ' . $item_data['name']; $message = lang('Items.successful_' . ($new_item ? 'adding' : 'updating')) . ' ' . $item_data['name'];
echo json_encode(['success' => true, 'message' => $message, 'id' => $item_id]); return $this->response->setJSON(['success' => true, 'message' => $message, 'id' => $item_id]);
} else { } else {
$message = $upload_success ? lang('Items.error_adding_updating') . ' ' . $item_data['name'] : strip_tags($upload_data['error']); $message = $upload_success ? lang('Items.error_adding_updating') . ' ' . $item_data['name'] : strip_tags($upload_data['error']);
echo json_encode(['success' => false, 'message' => $message, 'id' => $item_id]); return $this->response->setJSON(['success' => false, 'message' => $message, 'id' => $item_id]);
} }
} else { } else {
$message = lang('Items.error_adding_updating') . ' ' . $item_data['name']; $message = lang('Items.error_adding_updating') . ' ' . $item_data['name'];
echo json_encode(['success' => false, 'message' => $message, 'id' => NEW_ENTRY]); return $this->response->setJSON(['success' => false, 'message' => $message, 'id' => NEW_ENTRY]);
} }
} }
@@ -776,49 +783,51 @@ class Items extends Secure_Controller
/** /**
* Ajax call to check to see if the item number, a.k.a. barcode, is already used by another item * Ajax call to check to see if the item number, a.k.a. barcode, is already used by another item
* If it exists then that is an error condition so return true for "error found" * If it exists then that is an error condition so return true for "error found"
* @return void * @return ResponseInterface
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function postCheckItemNumber(): void public function postCheckItemNumber(): ResponseInterface
{ {
$exists = $this->item->item_number_exists($this->request->getPost('item_number'), $this->request->getPost('item_id')); $exists = $this->item->item_number_exists($this->request->getPost('item_number'), $this->request->getPost('item_id'));
echo !$exists ? 'true' : 'false'; return $this->response->setJSON(!$exists ? 'true' : 'false');
} }
/** /**
* Checks to see if an item kit with the same name as the item already exists. * Checks to see if an item kit with the same name as the item already exists.
* *
* @return void * @return ResponseInterface
*/ */
public function check_kit_exists(): void // TODO: This function appears to be never called in the code. Need to confirm. public function check_kit_exists(): ResponseInterface // TODO: This function appears to be never called in the code. Need to confirm.
{ {
if ($this->request->getPost('item_number') === NEW_ENTRY) { if ($this->request->getPost('item_number') === NEW_ENTRY) {
$exists = $this->item_kit->item_kit_exists_for_name($this->request->getPost('name')); // TODO: item_kit_exists_for_name doesn't exist in Item_kit. I looked at the blame and it appears to have never existed. $exists = $this->item_kit->item_kit_exists_for_name($this->request->getPost('name')); // TODO: item_kit_exists_for_name doesn't exist in Item_kit. I looked at the blame and it appears to have never existed.
} else { } else {
$exists = false; $exists = false;
} }
echo !$exists ? 'true' : 'false';
return $this->response->setJSON(!$exists ? 'true' : 'false');
} }
/** /**
* @param $item_id * @param $item_id
* @return void * @return ResponseInterface
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function getRemoveLogo($item_id): void public function getRemoveLogo($item_id): ResponseInterface
{ {
$item_data = ['pic_filename' => null]; $item_data = ['pic_filename' => null];
$result = $this->item->save_value($item_data, $item_id); $result = $this->item->save_value($item_data, $item_id);
echo json_encode(['success' => $result]); return $this->response->setJSON(['success' => $result]);
} }
/** /**
* @return ResponseInterface
* @throws ReflectionException * @throws ReflectionException
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function postSaveInventory($item_id = NEW_ENTRY): void public function postSaveInventory($item_id = NEW_ENTRY): ResponseInterface
{ {
$employee_id = $this->employee->get_logged_in_employee_info()->person_id; $employee_id = $this->employee->get_logged_in_employee_info()->person_id;
$cur_item_info = $this->item->get_info($item_id); $cur_item_info = $this->item->get_info($item_id);
@@ -846,19 +855,19 @@ class Items extends Secure_Controller
if ($this->item_quantity->save_value($item_quantity_data, $item_id, $location_id)) { if ($this->item_quantity->save_value($item_quantity_data, $item_id, $location_id)) {
$message = lang('Items.successful_updating') . " $cur_item_info->name"; $message = lang('Items.successful_updating') . " $cur_item_info->name";
echo json_encode(['success' => true, 'message' => $message, 'id' => $item_id]); return $this->response->setJSON(['success' => true, 'message' => $message, 'id' => $item_id]);
} else { } else {
$message = lang('Items.error_adding_updating') . " $cur_item_info->name"; $message = lang('Items.error_adding_updating') . " $cur_item_info->name";
echo json_encode(['success' => false, 'message' => $message, 'id' => NEW_ENTRY]); return $this->response->setJSON(['success' => false, 'message' => $message, 'id' => NEW_ENTRY]);
} }
} }
/** /**
* @return void * @return ResponseInterface
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function postBulkUpdate(): void public function postBulkUpdate(): ResponseInterface
{ {
$items_to_update = $this->request->getPost('item_ids'); $items_to_update = $this->request->getPost('item_ids');
$item_data = []; $item_data = [];
@@ -890,23 +899,24 @@ class Items extends Secure_Controller
$this->item_taxes->save_multiple($items_taxes_data, $items_to_update); $this->item_taxes->save_multiple($items_taxes_data, $items_to_update);
} }
echo json_encode(['success' => true, 'message' => lang('Items.successful_bulk_edit'), 'id' => $items_to_update]); return $this->response->setJSON(['success' => true, 'message' => lang('Items.successful_bulk_edit'), 'id' => $items_to_update]);
} else { } else {
echo json_encode(['success' => false, 'message' => lang('Items.error_updating_multiple')]); return $this->response->setJSON(['success' => false, 'message' => lang('Items.error_updating_multiple')]);
} }
} }
/** /**
* @return ResponseInterface
*/ */
public function postDelete(): void public function postDelete(): ResponseInterface
{ {
$items_to_delete = $this->request->getPost('ids'); $items_to_delete = $this->request->getPost('ids');
if ($this->item->delete_list($items_to_delete)) { if ($this->item->delete_list($items_to_delete)) {
$message = lang('Items.successful_deleted') . ' ' . count($items_to_delete) . ' ' . lang('Items.one_or_multiple'); $message = lang('Items.successful_deleted') . ' ' . count($items_to_delete) . ' ' . lang('Items.one_or_multiple');
echo json_encode(['success' => true, 'message' => $message]); return $this->response->setJSON(['success' => true, 'message' => $message]);
} else { } else {
echo json_encode(['success' => false, 'message' => lang('Items.cannot_be_deleted')]); return $this->response->setJSON(['success' => false, 'message' => lang('Items.cannot_be_deleted')]);
} }
} }
@@ -928,123 +938,129 @@ class Items extends Secure_Controller
} }
/** /**
* @return void * @return string
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function getCsvImport(): void public function getCsvImport(): string
{ {
echo view('items/form_csv_import'); return view('items/form_csv_import');
} }
/** /**
* Imports items from CSV formatted file. * Imports items from CSV formatted file.
* @return ResponseInterface
* @throws ReflectionException * @throws ReflectionException
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function postImportCsvFile(): void public function postImportCsvFile(): ResponseInterface
{ {
helper('importfile_helper'); helper('importfile_helper');
if ($_FILES['file_path']['error'] !== UPLOAD_ERR_OK) { try {
echo json_encode(['success' => false, 'message' => lang('Items.csv_import_failed')]); if ($_FILES['file_path']['error'] !== UPLOAD_ERR_OK) {
} else { return $this->response->setJSON(['success' => false, 'message' => lang('Items.csv_import_failed')]);
if (file_exists($_FILES['file_path']['tmp_name'])) { } else {
set_time_limit(240); if (file_exists($_FILES['file_path']['tmp_name'])) {
set_time_limit(240);
$failCodes = []; $failCodes = [];
$csv_rows = get_csv_file($_FILES['file_path']['tmp_name']); $csv_rows = get_csv_file($_FILES['file_path']['tmp_name']);
$employee_id = $this->employee->get_logged_in_employee_info()->person_id; $employee_id = $this->employee->get_logged_in_employee_info()->person_id;
$allowed_stock_locations = $this->stock_location->get_allowed_locations(); $allowed_stock_locations = $this->stock_location->get_allowed_locations();
$attribute_definition_names = $this->attribute->get_definition_names(); $attribute_definition_names = $this->attribute->get_definition_names();
unset($attribute_definition_names[NEW_ENTRY]); // Removes the common_none_selected_text from the array unset($attribute_definition_names[NEW_ENTRY]); // Removes the common_none_selected_text from the array
$attribute_data = []; $attribute_data = [];
foreach ($attribute_definition_names as $definition_name) { foreach ($attribute_definition_names as $definition_name) {
$attribute_data[$definition_name] = $this->attribute->get_definition_by_name($definition_name)[0]; $attribute_data[$definition_name] = $this->attribute->get_definition_by_name($definition_name)[0];
if ($attribute_data[$definition_name]['definition_type'] === DROPDOWN) { if ($attribute_data[$definition_name]['definition_type'] === DROPDOWN) {
$attribute_data[$definition_name]['dropdown_values'] = $this->attribute->get_definition_values($attribute_data[$definition_name]['definition_id']); $attribute_data[$definition_name]['dropdown_values'] = $this->attribute->get_definition_values($attribute_data[$definition_name]['definition_id']);
}
} }
} $db = db_connect();
$db = db_connect(); $db->transBegin(); // TODO: This section needs to be reworked so that the data array is being created then passed to the Item model because $db doesn't exist in the controller without being instantiated, but database operations should be restricted to the model
$db->transBegin(); // TODO: This section needs to be reworked so that the data array is being created then passed to the Item model because $db doesn't exist in the controller without being instantiated, but database operations should be restricted to the model
foreach ($csv_rows as $key => $row) { foreach ($csv_rows as $key => $row) {
$is_failed_row = false; $is_failed_row = false;
$item_id = (int)$row['Id']; $item_id = (int)$row['Id'];
$is_update = ($item_id > 0); $is_update = ($item_id > 0);
$item_data = [ $item_data = [
'item_id' => $item_id, 'item_id' => $item_id,
'name' => $row['Item Name'], 'name' => $row['Item Name'],
'description' => $row['Description'], 'description' => $row['Description'],
'category' => $row['Category'], 'category' => $row['Category'],
'cost_price' => $row['Cost Price'], 'cost_price' => $row['Cost Price'],
'unit_price' => $row['Unit Price'], 'unit_price' => $row['Unit Price'],
'reorder_level' => $row['Reorder Level'], 'reorder_level' => $row['Reorder Level'],
'deleted' => false, 'deleted' => false,
'hsn_code' => $row['HSN'], 'hsn_code' => $row['HSN'],
'pic_filename' => $row['Image'] 'pic_filename' => $row['Image']
]; ];
if (!empty($row['supplier ID'])) { if (!empty($row['supplier ID'])) {
$item_data['supplier_id'] = $this->supplier->exists($row['Supplier ID']) ? $row['Supplier ID'] : null; $item_data['supplier_id'] = $this->supplier->exists($row['Supplier ID']) ? $row['Supplier ID'] : null;
} }
if ($is_update) {
$item_data['allow_alt_description'] = empty($row['Allow Alt Description']) ? null : $row['Allow Alt Description'];
$item_data['is_serialized'] = empty($row['Item has Serial Number']) ? null : $row['Item has Serial Number'];
} else {
$item_data['allow_alt_description'] = empty($row['Allow Alt Description']) ? '0' : '1';
$item_data['is_serialized'] = empty($row['Item has Serial Number']) ? '0' : '1';
}
if (!empty($row['Barcode']) && !$is_update) {
$item_data['item_number'] = $row['Barcode'];
$is_failed_row = $this->item->item_number_exists($item_data['item_number']);
}
if (!$is_failed_row) {
$is_failed_row = $this->data_error_check($row, $item_data, $allowed_stock_locations, $attribute_definition_names, $attribute_data);
}
// Remove false, null, '' and empty strings but keep 0
$item_data = array_filter($item_data, function ($value) {
return $value !== null && strlen($value);
});
if (!$is_failed_row && $this->item->save_value($item_data, $item_id)) {
$this->save_tax_data($row, $item_data);
$this->save_inventory_quantities($row, $item_data, $allowed_stock_locations, $employee_id);
$is_failed_row = $this->save_attribute_data($row, $item_data, $attribute_data); // TODO: $is_failed_row never gets used after this.
if ($is_update) { if ($is_update) {
$item_data = array_merge($item_data, get_object_vars($this->item->get_info_by_id_or_number($item_id))); $item_data['allow_alt_description'] = empty($row['Allow Alt Description']) ? null : $row['Allow Alt Description'];
$item_data['is_serialized'] = empty($row['Item has Serial Number']) ? null : $row['Item has Serial Number'];
} else {
$item_data['allow_alt_description'] = empty($row['Allow Alt Description']) ? '0' : '1';
$item_data['is_serialized'] = empty($row['Item has Serial Number']) ? '0' : '1';
} }
} else {
$failed_row = $key + 2; if (!empty($row['Barcode']) && !$is_update) {
$failCodes[] = $failed_row; $item_data['item_number'] = $row['Barcode'];
log_message('error', "CSV Item import failed on line $failed_row. This item was not imported."); $is_failed_row = $this->item->item_number_exists($item_data['item_number']);
}
if (!$is_failed_row) {
$is_failed_row = $this->data_error_check($row, $item_data, $allowed_stock_locations, $attribute_definition_names, $attribute_data);
}
// Remove false, null, '' and empty strings but keep 0
$item_data = array_filter($item_data, function ($value) {
return $value !== null && strlen($value);
});
if (!$is_failed_row && $this->item->save_value($item_data, $item_id)) {
$this->save_tax_data($row, $item_data);
$this->save_inventory_quantities($row, $item_data, $allowed_stock_locations, $employee_id);
$is_failed_row = $this->save_attribute_data($row, $item_data, $attribute_data); // TODO: $is_failed_row never gets used after this.
if ($is_update) {
$item_data = array_merge($item_data, get_object_vars($this->item->get_info_by_id_or_number($item_id)));
}
} else {
$failed_row = $key + 2;
$failCodes[] = $failed_row;
log_message('error', "CSV Item import failed on line $failed_row. This item was not imported.");
}
unset($csv_rows[$key]);
} }
unset($csv_rows[$key]); $csv_rows = null;
}
$csv_rows = null; if (count($failCodes) > 0) {
$message = lang('Items.csv_import_partially_failed', [count($failCodes), implode(', ', $failCodes)]);
$db->transRollback();
return $this->response->setJSON(['success' => false, 'message' => $message]);
} else {
$db->transCommit();
if (count($failCodes) > 0) { return $this->response->setJSON(['success' => true, 'message' => lang('Items.csv_import_success')]);
$message = lang('Items.csv_import_partially_failed', [count($failCodes), implode(', ', $failCodes)]); }
$db->transRollback();
echo json_encode(['success' => false, 'message' => $message]);
} else { } else {
$db->transCommit(); return $this->response->setJSON(['success' => false, 'message' => lang('Items.csv_import_nodata_wrongformat')]);
echo json_encode(['success' => true, 'message' => lang('Items.csv_import_success')]);
} }
} else {
echo json_encode(['success' => false, 'message' => lang('Items.csv_import_nodata_wrongformat')]);
} }
} catch (Exception $e) {
return $this->response->setJSON(['success' => false, 'message' => $e->getMessage()]);
} }
} }
/** /**

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -25,6 +25,7 @@ use App\Models\Reports\Summary_sales;
use App\Models\Reports\Summary_sales_taxes; use App\Models\Reports\Summary_sales_taxes;
use App\Models\Reports\Summary_suppliers; use App\Models\Reports\Summary_suppliers;
use App\Models\Reports\Summary_taxes; use App\Models\Reports\Summary_taxes;
use CodeIgniter\HTTP\ResponseInterface;
use Config\OSPOS; use Config\OSPOS;
use Config\Services; use Config\Services;
@@ -84,7 +85,8 @@ class Reports extends Secure_Controller
// Check access to report submodule // Check access to report submodule
if (!$this->employee->has_grant('reports_' . $submodule_id, $this->employee->get_logged_in_employee_info()->person_id)) { if (!$this->employee->has_grant('reports_' . $submodule_id, $this->employee->get_logged_in_employee_info()->person_id)) {
redirect('no_access/reports/reports_' . $submodule_id); header('Location: ' . base_url('no_access/reports/reports_' . $submodule_id));
exit();
} }
} }
@@ -101,8 +103,9 @@ class Reports extends Secure_Controller
/** /**
* Initial Report listing screen * Initial Report listing screen
* @return string
*/ */
public function getIndex(): void public function getIndex(): string
{ {
$person_id = $this->session->get('person_id'); $person_id = $this->session->get('person_id');
$grants = $this->employee->get_employee_grants($this->session->get('person_id')); $grants = $this->employee->get_employee_grants($this->session->get('person_id'));
@@ -114,7 +117,7 @@ class Reports extends Secure_Controller
'permission_ids' => $permissions_ids, 'permission_ids' => $permissions_ids,
]; ];
echo view('reports/listing', $data); return view('reports/listing', $data);
} }
/** /**
@@ -123,9 +126,9 @@ class Reports extends Secure_Controller
* @param string $end_date * @param string $end_date
* @param string $sale_type * @param string $sale_type
* @param string $location_id * @param string $location_id
* @return void * @return string
*/ */
public function summary_sales(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void // TODO: Perhaps these need to be passed as an array? Too many parameters in the signature. public function summary_sales(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string // TODO: Perhaps these need to be passed as an array? Too many parameters in the signature.
{ // TODO: Duplicated code { // TODO: Duplicated code
$this->clearCache(); $this->clearCache();
@@ -161,7 +164,7 @@ class Reports extends Secure_Controller
'summary_data' => $summary 'summary_data' => $summary
]; ];
echo view('reports/tabular', $data); return view('reports/tabular', $data);
} }
/** /**
@@ -170,9 +173,9 @@ class Reports extends Secure_Controller
* @param string $end_date * @param string $end_date
* @param string $sale_type * @param string $sale_type
* @param string $location_id * @param string $location_id
* @return void * @return string
*/ */
public function summary_categories(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void public function summary_categories(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{ // TODO: Duplicated code { // TODO: Duplicated code
$this->clearCache(); $this->clearCache();
@@ -207,7 +210,7 @@ class Reports extends Secure_Controller
'summary_data' => $summary 'summary_data' => $summary
]; ];
echo view('reports/tabular', $data); return view('reports/tabular', $data);
} }
/** /**
@@ -215,9 +218,9 @@ class Reports extends Secure_Controller
* @param string $start_date * @param string $start_date
* @param string $end_date * @param string $end_date
* @param string $sale_type * @param string $sale_type
* @return void * @return string
*/ */
public function summary_expenses_categories(string $start_date, string $end_date, string $sale_type): void public function summary_expenses_categories(string $start_date, string $end_date, string $sale_type): string
{ {
$this->clearCache(); $this->clearCache();
@@ -244,7 +247,7 @@ class Reports extends Secure_Controller
'summary_data' => $summary 'summary_data' => $summary
]; ];
echo view('reports/tabular', $data); return view('reports/tabular', $data);
} }
/** /**
@@ -253,9 +256,9 @@ class Reports extends Secure_Controller
* @param string $end_date * @param string $end_date
* @param string $sale_type * @param string $sale_type
* @param string $location_id * @param string $location_id
* @return void * @return string
*/ */
public function summary_customers(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void public function summary_customers(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{ {
$this->clearCache(); $this->clearCache();
@@ -292,7 +295,7 @@ class Reports extends Secure_Controller
'summary_data' => $summary 'summary_data' => $summary
]; ];
echo view('reports/tabular', $data); return view('reports/tabular', $data);
} }
/** /**
@@ -301,9 +304,9 @@ class Reports extends Secure_Controller
* @param string $end_date * @param string $end_date
* @param string $sale_type * @param string $sale_type
* @param string $location_id * @param string $location_id
* @return void * @return string
*/ */
public function summary_suppliers(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void public function summary_suppliers(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{ // TODO: Duplicated Code { // TODO: Duplicated Code
$this->clearCache(); $this->clearCache();
@@ -338,7 +341,7 @@ class Reports extends Secure_Controller
'summary_data' => $summary 'summary_data' => $summary
]; ];
echo view('reports/tabular', $data); return view('reports/tabular', $data);
} }
/** /**
@@ -347,9 +350,9 @@ class Reports extends Secure_Controller
* @param string $end_date * @param string $end_date
* @param string $sale_type * @param string $sale_type
* @param string $location_id * @param string $location_id
* @return void * @return string
*/ */
public function summary_items(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void public function summary_items(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{ {
$this->clearCache(); $this->clearCache();
@@ -388,7 +391,7 @@ class Reports extends Secure_Controller
'summary_data' => $summary 'summary_data' => $summary
]; ];
echo view('reports/tabular', $data); return view('reports/tabular', $data);
} }
/** /**
@@ -397,9 +400,9 @@ class Reports extends Secure_Controller
* @param string $end_date * @param string $end_date
* @param string $sale_type * @param string $sale_type
* @param string $location_id * @param string $location_id
* @return void * @return string
*/ */
public function summary_employees(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void public function summary_employees(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{ {
$this->clearCache(); $this->clearCache();
@@ -436,7 +439,7 @@ class Reports extends Secure_Controller
'summary_data' => $summary 'summary_data' => $summary
]; ];
echo view('reports/tabular', $data); return view('reports/tabular', $data);
} }
/** /**
@@ -445,9 +448,9 @@ class Reports extends Secure_Controller
* @param string $end_date * @param string $end_date
* @param string $sale_type * @param string $sale_type
* @param string $location_id * @param string $location_id
* @return void * @return string
*/ */
public function summary_taxes(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void public function summary_taxes(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{ // TODO: Duplicate Code { // TODO: Duplicate Code
$this->clearCache(); $this->clearCache();
@@ -482,13 +485,14 @@ class Reports extends Secure_Controller
'summary_data' => $summary 'summary_data' => $summary
]; ];
echo view('reports/tabular', $data); return view('reports/tabular', $data);
} }
/** /**
* Summary Sales Taxes report * Summary Sales Taxes report
* @return string
*/ */
public function summary_sales_taxes(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void public function summary_sales_taxes(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{ // TODO: Duplicated code { // TODO: Duplicated code
$this->clearCache(); $this->clearCache();
@@ -521,16 +525,16 @@ class Reports extends Secure_Controller
'summary_data' => $summary 'summary_data' => $summary
]; ];
echo view('reports/tabular', $data); return view('reports/tabular', $data);
} }
/** /**
* Summary Discounts report input. Used in app/Config/Routes.php * Summary Discounts report input. Used in app/Config/Routes.php
* *
* @return void * @return string
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function summary_discounts_input(): void public function summary_discounts_input(): string
{ {
$this->clearCache(); $this->clearCache();
@@ -541,13 +545,14 @@ class Reports extends Secure_Controller
$data['discount_type_options'] = ['0' => lang('Reports.discount_percent'), '1' => lang('Reports.discount_fixed')]; $data['discount_type_options'] = ['0' => lang('Reports.discount_percent'), '1' => lang('Reports.discount_fixed')];
$data['sale_type_options'] = $this->get_sale_type_options(); $data['sale_type_options'] = $this->get_sale_type_options();
echo view('reports/date_input', $data); return view('reports/date_input', $data);
} }
/** /**
* Summary Discounts report * Summary Discounts report
* @return string
**/ **/
public function summary_discounts(string $start_date, string $end_date, string $sale_type, string $location_id = 'all', int $discount_type = 0): void public function summary_discounts(string $start_date, string $end_date, string $sale_type, string $location_id = 'all', int $discount_type = 0): string
{ // TODO: Duplicated Code { // TODO: Duplicated Code
$this->clearCache(); $this->clearCache();
@@ -579,13 +584,14 @@ class Reports extends Secure_Controller
'summary_data' => $summary 'summary_data' => $summary
]; ];
echo view('reports/tabular', $data); return view('reports/tabular', $data);
} }
/** /**
* Summary Payments report * Summary Payments report
* @return string
*/ */
public function summary_payments(string $start_date, string $end_date): void public function summary_payments(string $start_date, string $end_date): string
{ {
$this->clearCache(); $this->clearCache();
@@ -637,16 +643,16 @@ class Reports extends Secure_Controller
'summary_data' => $summary 'summary_data' => $summary
]; ];
echo view('reports/tabular', $data); return view('reports/tabular', $data);
} }
/** /**
* Input for reports that require only a date range. Used in app/Config/Routes.php * Input for reports that require only a date range. Used in app/Config/Routes.php
* *
* @return void * @return string
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function date_input(): void public function date_input(): string
{ // TODO: Duplicated Code { // TODO: Duplicated Code
$this->clearCache(); $this->clearCache();
@@ -656,30 +662,30 @@ class Reports extends Secure_Controller
$data['mode'] = 'sale'; $data['mode'] = 'sale';
$data['sale_type_options'] = $this->get_sale_type_options(); $data['sale_type_options'] = $this->get_sale_type_options();
echo view('reports/date_input', $data); return view('reports/date_input', $data);
} }
/** /**
* Input for reports that require only a date range. Used in app/Config/Routes.php * Input for reports that require only a date range. Used in app/Config/Routes.php
* *
* @return void * @return string
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function date_input_only(): void public function date_input_only(): string
{ {
$this->clearCache(); $this->clearCache();
$data = []; $data = [];
echo view('reports/date_input', $data); return view('reports/date_input', $data);
} }
/** /**
* Input for reports that require only a date range. Used in app/Config/Routes.php * Input for reports that require only a date range. Used in app/Config/Routes.php
* *
* @return void * @return string
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function date_input_sales(): void public function date_input_sales(): string
{ // TODO: Duplicated Code { // TODO: Duplicated Code
$this->clearCache(); $this->clearCache();
@@ -689,23 +695,23 @@ class Reports extends Secure_Controller
$data['mode'] = 'sale'; $data['mode'] = 'sale';
$data['sale_type_options'] = $this->get_sale_type_options(); $data['sale_type_options'] = $this->get_sale_type_options();
echo view('reports/date_input', $data); return view('reports/date_input', $data);
} }
/** /**
* Receivings date input. Used in app/Config/Routes.php * Receivings date input. Used in app/Config/Routes.php
* *
* @return void * @return string
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function date_input_recv(): void public function date_input_recv(): string
{ {
$stock_locations = $data = $this->stock_location->get_allowed_locations('receivings'); $stock_locations = $data = $this->stock_location->get_allowed_locations('receivings');
$stock_locations['all'] = lang('Reports.all'); $stock_locations['all'] = lang('Reports.all');
$data['stock_locations'] = array_reverse($stock_locations, true); $data['stock_locations'] = array_reverse($stock_locations, true);
$data['mode'] = 'receiving'; $data['mode'] = 'receiving';
echo view('reports/date_input', $data); return view('reports/date_input', $data);
} }
/** /**
@@ -714,10 +720,10 @@ class Reports extends Secure_Controller
* @param string $start_date * @param string $start_date
* @param string $end_date * @param string $end_date
* @param string $sale_type * @param string $sale_type
* @return void * @return string
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function graphical_summary_expenses_categories(string $start_date, string $end_date, string $sale_type): void public function graphical_summary_expenses_categories(string $start_date, string $end_date, string $sale_type): string
{ {
$this->clearCache(); $this->clearCache();
@@ -750,7 +756,7 @@ class Reports extends Secure_Controller
'show_currency' => true 'show_currency' => true
]; ];
echo view('reports/graphical', $data); return view('reports/graphical', $data);
} }
/** /**
@@ -760,9 +766,9 @@ class Reports extends Secure_Controller
* @param string $end_date * @param string $end_date
* @param string $sale_type * @param string $sale_type
* @param string $location_id * @param string $location_id
* @return void * @return string
*/ */
public function graphical_summary_sales(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void public function graphical_summary_sales(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{ {
$this->clearCache(); $this->clearCache();
@@ -796,7 +802,7 @@ class Reports extends Secure_Controller
'show_currency' => true 'show_currency' => true
]; ];
echo view('reports/graphical', $data); return view('reports/graphical', $data);
} }
/** /**
@@ -806,9 +812,9 @@ class Reports extends Secure_Controller
* @param string $end_date * @param string $end_date
* @param string $sale_type * @param string $sale_type
* @param string $location_id * @param string $location_id
* @return void * @return string
*/ */
public function graphical_summary_items(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void public function graphical_summary_items(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{ {
$this->clearCache(); $this->clearCache();
@@ -843,7 +849,7 @@ class Reports extends Secure_Controller
'show_currency' => true 'show_currency' => true
]; ];
echo view('reports/graphical', $data); return view('reports/graphical', $data);
} }
/** /**
@@ -853,9 +859,9 @@ class Reports extends Secure_Controller
* @param string $end_date * @param string $end_date
* @param string $sale_type * @param string $sale_type
* @param string $location_id * @param string $location_id
* @return void * @return string
*/ */
public function graphical_summary_categories(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void public function graphical_summary_categories(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{ // TODO: Duplicated Code { // TODO: Duplicated Code
$this->clearCache(); $this->clearCache();
@@ -886,7 +892,7 @@ class Reports extends Secure_Controller
'show_currency' => true 'show_currency' => true
]; ];
echo view('reports/graphical', $data); return view('reports/graphical', $data);
} }
/** /**
@@ -896,9 +902,9 @@ class Reports extends Secure_Controller
* @param string $end_date * @param string $end_date
* @param string $sale_type * @param string $sale_type
* @param string $location_id * @param string $location_id
* @return void * @return string
*/ */
public function graphical_summary_suppliers(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void public function graphical_summary_suppliers(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{ // TODO: Duplicated Code { // TODO: Duplicated Code
$this->clearCache(); $this->clearCache();
@@ -931,7 +937,7 @@ class Reports extends Secure_Controller
'show_currency' => true 'show_currency' => true
]; ];
echo view('reports/graphical', $data); return view('reports/graphical', $data);
} }
/** /**
@@ -941,9 +947,9 @@ class Reports extends Secure_Controller
* @param string $end_date * @param string $end_date
* @param string $sale_type * @param string $sale_type
* @param string $location_id * @param string $location_id
* @return void * @return string
*/ */
public function graphical_summary_employees(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void public function graphical_summary_employees(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{ {
$this->clearCache(); $this->clearCache();
@@ -975,7 +981,7 @@ class Reports extends Secure_Controller
'show_currency' => true 'show_currency' => true
]; ];
echo view('reports/graphical', $data); return view('reports/graphical', $data);
} }
/** /**
@@ -985,9 +991,9 @@ class Reports extends Secure_Controller
* @param string $end_date * @param string $end_date
* @param string $sale_type * @param string $sale_type
* @param string $location_id * @param string $location_id
* @return void * @return string
*/ */
public function graphical_summary_taxes(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void public function graphical_summary_taxes(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{ // TODO: Duplicated Code { // TODO: Duplicated Code
$this->clearCache(); $this->clearCache();
@@ -1019,7 +1025,7 @@ class Reports extends Secure_Controller
'show_currency' => true 'show_currency' => true
]; ];
echo view('reports/graphical', $data); return view('reports/graphical', $data);
} }
/** /**
@@ -1029,9 +1035,9 @@ class Reports extends Secure_Controller
* @param string $end_date * @param string $end_date
* @param string $sale_type * @param string $sale_type
* @param string $location_id * @param string $location_id
* @return void * @return string
*/ */
public function graphical_summary_sales_taxes(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void public function graphical_summary_sales_taxes(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{ // TODO: Duplicated Code { // TODO: Duplicated Code
$this->clearCache(); $this->clearCache();
@@ -1063,7 +1069,7 @@ class Reports extends Secure_Controller
'show_currency' => true 'show_currency' => true
]; ];
echo view('reports/graphical', $data); return view('reports/graphical', $data);
} }
/** /**
@@ -1073,9 +1079,9 @@ class Reports extends Secure_Controller
* @param string $end_date * @param string $end_date
* @param string $sale_type * @param string $sale_type
* @param string $location_id * @param string $location_id
* @return void * @return string
*/ */
public function graphical_summary_customers(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void public function graphical_summary_customers(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{ // TODO: Duplicated Code { // TODO: Duplicated Code
$this->clearCache(); $this->clearCache();
@@ -1109,7 +1115,7 @@ class Reports extends Secure_Controller
'show_currency' => true 'show_currency' => true
]; ];
echo view('reports/graphical', $data); return view('reports/graphical', $data);
} }
/** /**
@@ -1120,9 +1126,10 @@ class Reports extends Secure_Controller
* @param string $sale_type * @param string $sale_type
* @param string $location_id ID of the location to be reported or 'all' if none is specified * @param string $location_id ID of the location to be reported or 'all' if none is specified
* @param int $discount_type * @param int $discount_type
* @return string
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function graphical_summary_discounts(string $start_date, string $end_date, string $sale_type, string $location_id = 'all', int $discount_type = 0): void public function graphical_summary_discounts(string $start_date, string $end_date, string $sale_type, string $location_id = 'all', int $discount_type = 0): string
{ // TODO: Duplicated Code { // TODO: Duplicated Code
$this->clearCache(); $this->clearCache();
@@ -1157,7 +1164,7 @@ class Reports extends Secure_Controller
'show_currency' => false 'show_currency' => false
]; ];
echo view('reports/graphical', $data); return view('reports/graphical', $data);
} }
/** /**
@@ -1167,9 +1174,9 @@ class Reports extends Secure_Controller
* @param string $end_date * @param string $end_date
* @param string $sale_type * @param string $sale_type
* @param string $location_id * @param string $location_id
* @return void * @return string
*/ */
public function graphical_summary_payments(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void public function graphical_summary_payments(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{ {
$this->clearCache(); $this->clearCache();
@@ -1203,16 +1210,16 @@ class Reports extends Secure_Controller
'show_currency' => true 'show_currency' => true
]; ];
echo view('reports/graphical', $data); return view('reports/graphical', $data);
} }
/** /**
* Gets the specific customer input view. Used in app/Config/Routes.php * Gets the specific customer input view. Used in app/Config/Routes.php
* *
* @return void * @return string
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function specific_customer_input(): void public function specific_customer_input(): string
{ {
$this->clearCache(); $this->clearCache();
@@ -1230,7 +1237,7 @@ class Reports extends Secure_Controller
$data['sale_type_options'] = $this->get_sale_type_options(); $data['sale_type_options'] = $this->get_sale_type_options();
$data['payment_type'] = $this->get_payment_type(); $data['payment_type'] = $this->get_payment_type();
echo view('reports/specific_customer_input', $data); return view('reports/specific_customer_input', $data);
} }
/** /**
@@ -1257,10 +1264,10 @@ class Reports extends Secure_Controller
* @param string $customer_id * @param string $customer_id
* @param string $sale_type * @param string $sale_type
* @param string $payment_type * @param string $payment_type
* @return void * @return string
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function specific_customers(string $start_date, string $end_date, string $customer_id, string $sale_type, string $payment_type): void public function specific_customers(string $start_date, string $end_date, string $customer_id, string $sale_type, string $payment_type): string
{ {
$this->clearCache(); $this->clearCache();
@@ -1351,16 +1358,16 @@ class Reports extends Secure_Controller
'overall_summary_data' => $specific_customer->getSummaryData($inputs) 'overall_summary_data' => $specific_customer->getSummaryData($inputs)
]; ];
echo view('reports/tabular_details', $data); return view('reports/tabular_details', $data);
} }
/** /**
* Detailed employee report input form. Used in app/Config/Routes.php * Detailed employee report input form. Used in app/Config/Routes.php
* *
* @return void * @return string
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function specific_employee_input(): void public function specific_employee_input(): string
{ {
$this->clearCache(); $this->clearCache();
@@ -1374,7 +1381,7 @@ class Reports extends Secure_Controller
$data['specific_input_data'] = $employees; $data['specific_input_data'] = $employees;
$data['sale_type_options'] = $this->get_sale_type_options(); $data['sale_type_options'] = $this->get_sale_type_options();
echo view('reports/specific_input', $data); return view('reports/specific_input', $data);
} }
/** /**
@@ -1384,10 +1391,10 @@ class Reports extends Secure_Controller
* @param string $end_date * @param string $end_date
* @param string $employee_id * @param string $employee_id
* @param string $sale_type * @param string $sale_type
* @return void * @return string
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function specific_employees(string $start_date, string $end_date, string $employee_id, string $sale_type): void public function specific_employees(string $start_date, string $end_date, string $employee_id, string $sale_type): string
{ {
$this->clearCache(); $this->clearCache();
@@ -1474,16 +1481,16 @@ class Reports extends Secure_Controller
'overall_summary_data' => $specific_employee->getSummaryData($inputs) 'overall_summary_data' => $specific_employee->getSummaryData($inputs)
]; ];
echo view('reports/tabular_details', $data); return view('reports/tabular_details', $data);
} }
/** /**
* Detailed discount report. Used in app/Config/Routes.php * Detailed discount report. Used in app/Config/Routes.php
* *
* @return void * @return string
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function specific_discount_input(): void public function specific_discount_input(): string
{ {
$this->clearCache(); $this->clearCache();
@@ -1498,7 +1505,7 @@ class Reports extends Secure_Controller
$data['discount_type_options'] = ['0' => lang('Reports.discount_percent'), '1' => lang('Reports.discount_fixed')]; $data['discount_type_options'] = ['0' => lang('Reports.discount_percent'), '1' => lang('Reports.discount_fixed')];
$data['sale_type_options'] = $this->get_sale_type_options(); $data['sale_type_options'] = $this->get_sale_type_options();
echo view('reports/specific_input', $data); return view('reports/specific_input', $data);
} }
/** /**
@@ -1509,10 +1516,10 @@ class Reports extends Secure_Controller
* @param string $discount * @param string $discount
* @param string $sale_type * @param string $sale_type
* @param string $discount_type * @param string $discount_type
* @return void * @return string
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function specific_discounts(string $start_date, string $end_date, string $discount, string $sale_type, string $discount_type): void public function specific_discounts(string $start_date, string $end_date, string $discount, string $sale_type, string $discount_type): string
{ {
$this->clearCache(); $this->clearCache();
@@ -1605,17 +1612,17 @@ class Reports extends Secure_Controller
'overall_summary_data' => $specific_discount->getSummaryData($inputs) 'overall_summary_data' => $specific_discount->getSummaryData($inputs)
]; ];
echo view('reports/tabular_details', $data); return view('reports/tabular_details', $data);
} }
/** /**
* Gets the detailed sales data row for given sale_id. Used in app/Views/reports/tabular_details.php * Gets the detailed sales data row for given sale_id. Used in app/Views/reports/tabular_details.php
* *
* @param string $sale_id * @param string $sale_id
* @return void * @return ResponseInterface
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function getGet_detailed_sales_row(string $sale_id): void public function getGet_detailed_sales_row(string $sale_id): ResponseInterface
{ {
$this->clearCache(); $this->clearCache();
@@ -1658,16 +1665,16 @@ class Reports extends Secure_Controller
) )
]; ];
echo json_encode([$sale_id => $summary_data]); return $this->response->setJSON([$sale_id => $summary_data]);
} }
/** /**
* Detailed Supplier report input form. Used in app/Config/Routes.php * Detailed Supplier report input form. Used in app/Config/Routes.php
* *
* @return void * @return string
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function specific_supplier_input(): void public function specific_supplier_input(): string
{ {
$this->clearCache(); $this->clearCache();
@@ -1681,7 +1688,7 @@ class Reports extends Secure_Controller
$data['specific_input_data'] = $suppliers; $data['specific_input_data'] = $suppliers;
$data['sale_type_options'] = $this->get_sale_type_options(); $data['sale_type_options'] = $this->get_sale_type_options();
echo view('reports/specific_input', $data); return view('reports/specific_input', $data);
} }
/** /**
@@ -1691,9 +1698,9 @@ class Reports extends Secure_Controller
* @param string $end_date * @param string $end_date
* @param string $supplier_id * @param string $supplier_id
* @param string $sale_type * @param string $sale_type
* @return void * @return string
*/ */
public function specific_suppliers(string $start_date, string $end_date, string $supplier_id, string $sale_type): void public function specific_suppliers(string $start_date, string $end_date, string $supplier_id, string $sale_type): string
{ {
$inputs = [ $inputs = [
'start_date' => $start_date, 'start_date' => $start_date,
@@ -1727,7 +1734,7 @@ class Reports extends Secure_Controller
]; ];
} }
$supplier_info = $this->supplier->get_info($supplier_id); $supplier_info = $this->supplier->get_info((int) $supplier_id);
$data = [ $data = [
'title' => $supplier_info->company_name . ' (' . $supplier_info->first_name . ' ' . $supplier_info->last_name . ') ' . lang('Reports.report'), 'title' => $supplier_info->company_name . ' (' . $supplier_info->first_name . ' ' . $supplier_info->last_name . ') ' . lang('Reports.report'),
'subtitle' => $this->_get_subtitle_report(['start_date' => $start_date, 'end_date' => $end_date]), 'subtitle' => $this->_get_subtitle_report(['start_date' => $start_date, 'end_date' => $end_date]),
@@ -1736,7 +1743,7 @@ class Reports extends Secure_Controller
'summary_data' => $specific_supplier->getSummaryData($inputs) 'summary_data' => $specific_supplier->getSummaryData($inputs)
]; ];
echo view('reports/tabular', $data); return view('reports/tabular', $data);
} }
/** /**
@@ -1763,9 +1770,9 @@ class Reports extends Secure_Controller
* @param string $end_date * @param string $end_date
* @param string $sale_type * @param string $sale_type
* @param string $location_id * @param string $location_id
* @return void * @return string
*/ */
public function detailed_sales(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): void public function detailed_sales(string $start_date, string $end_date, string $sale_type, string $location_id = 'all'): string
{ {
$this->clearCache(); $this->clearCache();
@@ -1869,17 +1876,17 @@ class Reports extends Secure_Controller
'details_data_rewards' => $details_data_rewards, 'details_data_rewards' => $details_data_rewards,
'overall_summary_data' => $this->detailed_sales->getSummaryData($inputs) 'overall_summary_data' => $this->detailed_sales->getSummaryData($inputs)
]; ];
echo view('reports/tabular_details', $data); return view('reports/tabular_details', $data);
} }
/** /**
* Returns detailed receivings row for given receiving_id. Used in app/Views/reports/tabular_details.php * Returns detailed receivings row for given receiving_id. Used in app/Views/reports/tabular_details.php
* *
* @param string $receiving_id * @param string $receiving_id
* @return void * @return ResponseInterface
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function getGet_detailed_receivings_row(string $receiving_id): void public function getGet_detailed_receivings_row(string $receiving_id): ResponseInterface
{ {
$inputs = ['receiving_id' => $receiving_id]; $inputs = ['receiving_id' => $receiving_id];
@@ -1909,7 +1916,7 @@ class Reports extends Secure_Controller
) )
]; ];
echo json_encode([$receiving_id => $summary_data]); return $this->response->setJSON([$receiving_id => $summary_data]);
} }
/** /**
@@ -1917,9 +1924,9 @@ class Reports extends Secure_Controller
* @param string $end_date * @param string $end_date
* @param string $receiving_type * @param string $receiving_type
* @param string $location_id * @param string $location_id
* @return void * @return string
*/ */
public function detailed_receivings(string $start_date, string $end_date, string $receiving_type, string $location_id = 'all'): void public function detailed_receivings(string $start_date, string $end_date, string $receiving_type, string $location_id = 'all'): string
{ {
$this->clearCache(); $this->clearCache();
@@ -1993,13 +2000,13 @@ class Reports extends Secure_Controller
'overall_summary_data' => $this->detailed_receivings->getSummaryData($inputs) 'overall_summary_data' => $this->detailed_receivings->getSummaryData($inputs)
]; ];
echo view('reports/tabular_details', $data); return view('reports/tabular_details', $data);
} }
/** /**
* @return void * @return string
*/ */
public function inventory_low(): void public function inventory_low(): string
{ {
$this->clearCache(); $this->clearCache();
@@ -2028,16 +2035,16 @@ class Reports extends Secure_Controller
'summary_data' => $inventory_low->getSummaryData($inputs) 'summary_data' => $inventory_low->getSummaryData($inputs)
]; ];
echo view('reports/tabular', $data); return view('reports/tabular', $data);
} }
/** /**
* Gets the inventory summary input view. Used in app/Config/Routes.php * Gets the inventory summary input view. Used in app/Config/Routes.php
* *
* @return void * @return string
* @noinspection PhpUnused * @noinspection PhpUnused
*/ */
public function inventory_summary_input(): void public function inventory_summary_input(): string
{ {
$this->clearCache(); $this->clearCache();
@@ -2048,15 +2055,15 @@ class Reports extends Secure_Controller
$stock_locations['all'] = lang('Reports.all'); $stock_locations['all'] = lang('Reports.all');
$data['stock_locations'] = array_reverse($stock_locations, true); $data['stock_locations'] = array_reverse($stock_locations, true);
echo view('reports/inventory_summary_input', $data); return view('reports/inventory_summary_input', $data);
} }
/** /**
* @param string $location_id * @param string $location_id
* @param string $item_count * @param string $item_count
* @return void * @return string
*/ */
public function inventory_summary(string $location_id = 'all', string $item_count = 'all'): void public function inventory_summary(string $location_id = 'all', string $item_count = 'all'): string
{ {
$this->clearCache(); $this->clearCache();
@@ -2088,7 +2095,7 @@ class Reports extends Secure_Controller
'summary_data' => $this->inventory_summary->getSummaryData($report_data) 'summary_data' => $this->inventory_summary->getSummaryData($report_data)
]; ];
echo view('reports/tabular', $data); return view('reports/tabular', $data);
} }
/** /**

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -34,7 +34,7 @@ class Migration_Sales_Tax_Data extends Migration
public function up(): void public function up(): void
{ {
$number_of_unmigrated = $this->get_count_of_unmigrated(); $number_of_unmigrated = $this->get_count_of_unmigrated();
error_log("Migrating sales tax history. The number of sales that will be migrated is $number_of_unmigrated"); log_message('info', "Migrating sales tax history. The number of sales that will be migrated is $number_of_unmigrated");
if ($number_of_unmigrated > 0) { if ($number_of_unmigrated > 0) {
$unmigrated_invoices = $this->get_unmigrated($number_of_unmigrated)->getResultArray(); $unmigrated_invoices = $this->get_unmigrated($number_of_unmigrated)->getResultArray();
@@ -44,7 +44,7 @@ class Migration_Sales_Tax_Data extends Migration
} }
} }
error_log('Migrating sales tax history. The number of sales that will be migrated is finished.'); log_message('info', 'Migrating sales tax history. The number of sales that will be migrated is finished.');
} }
/** /**
@@ -146,7 +146,7 @@ class Migration_Sales_Tax_Data extends Migration
. ' ORDER BY SIT.sale_id) as US')->getResultArray(); . ' ORDER BY SIT.sale_id) as US')->getResultArray();
if (!$result) { if (!$result) {
error_log('Database error in 20170502221506_sales_tax_data.php related to sales_taxes or sales_items_taxes.'); log_message('info', 'Database error in 20170502221506_sales_tax_data.php related to sales_taxes or sales_items_taxes.');
return 0; return 0;
} }

View File

@@ -19,8 +19,6 @@ class Migration_IndiaGST extends Migration
helper('migration'); helper('migration');
execute_script(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_indiagst.sql'); 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(); $count_of_tax_codes = $this->get_count_of_tax_code_entries();
if ($count_of_tax_codes > 0) { if ($count_of_tax_codes > 0) {
@@ -42,8 +40,6 @@ class Migration_IndiaGST extends Migration
} }
$this->drop_backups(); $this->drop_backups();
error_log('Migrating tax configuration completed');
} }
/** /**

View File

@@ -13,10 +13,6 @@ class Migration_IndiaGST1 extends Migration
{ {
helper('migration'); helper('migration');
execute_script(APPPATH . 'Database/Migrations/sqlscripts/3.3.0_indiagst1.sql'); 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');
} }
/** /**

View File

@@ -11,6 +11,8 @@ class Migration_fix_empty_reports extends Migration
*/ */
public function up(): void public function up(): void
{ {
log_message('info', 'Starting migration: Fix empty reports.');
$builder = $this->db->table('stock_locations'); $builder = $this->db->table('stock_locations');
$builder->select('location_name'); $builder->select('location_name');
$builder->where('location_id', 1); $builder->where('location_id', 1);
@@ -23,6 +25,8 @@ class Migration_fix_empty_reports extends Migration
$builder->where('permission_id', 'receivings_' . $location_name); $builder->where('permission_id', 'receivings_' . $location_name);
$builder->orWhere('permission_id', 'sales_' . $location_name); $builder->orWhere('permission_id', 'sales_' . $location_name);
$builder->update(); $builder->update();
log_message('info', 'Finished migration: Fix empty reports.');
} }
/** /**

View File

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

View File

@@ -41,7 +41,7 @@ class Migration_TaxAmount extends Migration
$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(); $number_of_unmigrated = $this->get_count_of_unmigrated();
error_log('Migrating sales tax fixing. The number of sales that will be migrated is ' . $number_of_unmigrated); log_message('info', 'Migrating sales tax fixing. The number of sales that will be migrated is ' . $number_of_unmigrated);
if ($number_of_unmigrated > 0) { if ($number_of_unmigrated > 0) {
$unmigrated_invoices = $this->get_unmigrated($number_of_unmigrated)->getResultArray(); $unmigrated_invoices = $this->get_unmigrated($number_of_unmigrated)->getResultArray();
@@ -54,7 +54,7 @@ class Migration_TaxAmount extends Migration
$this->db->query('DROP TABLE ' . $this->db->prefixTable('sales_taxes_backup')); $this->db->query('DROP TABLE ' . $this->db->prefixTable('sales_taxes_backup'));
} }
error_log('Migrating sales tax fixing. The number of sales that will be migrated is finished.'); log_message('info', 'Migrating sales tax fixing. The number of sales that will be migrated is finished.');
} }
} }
@@ -126,7 +126,7 @@ class Migration_TaxAmount extends Migration
. ' ORDER BY SIT.sale_id) as US')->getResultArray(); . ' ORDER BY SIT.sale_id) as US')->getResultArray();
if (!$result) { if (!$result) {
error_log('Database error in 20200202000000_taxamount.php related to sales_taxes or sales_items_taxes.'); log_message('info', 'Database error in 20200202000000_taxamount.php related to sales_taxes or sales_items_taxes.');
return 0; return 0;
} }

View File

@@ -11,6 +11,7 @@ class Migration_taxgroupconstraint extends Migration
*/ */
public function up(): void 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)'); $this->db->query('ALTER TABLE ' . $this->db->prefixTable('tax_jurisdictions') . ' ADD CONSTRAINT tax_jurisdictions_uq1 UNIQUE (tax_group)');
} }

View File

@@ -11,6 +11,7 @@ class Migration_image_upload_defaults extends Migration
*/ */
public function up(): void public function up(): void
{ {
log_message('info', 'Migrating image upload defaults.');
$image_values = [ $image_values = [
['key' => 'image_allowed_types', 'value' => 'gif|jpg|png'], ['key' => 'image_allowed_types', 'value' => 'gif|jpg|png'],
['key' => 'image_max_height', 'value' => '480'], ['key' => 'image_max_height', 'value' => '480'],

View File

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

View File

@@ -11,6 +11,7 @@ class Migration_cashrounding extends Migration
*/ */
public function up(): void 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`'); $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,8 @@ class Migration_add_item_kit_number extends Migration
*/ */
public function up(): void public function up(): void
{ {
error_log('Migrating add_item_kit_number');
helper('migration'); helper('migration');
execute_script(APPPATH . 'Database/Migrations/sqlscripts/3.3.3_add_kits_item_number.sql'); execute_script(APPPATH . 'Database/Migrations/sqlscripts/3.3.3_add_kits_item_number.sql');
error_log('Migrating add_item_kit_number');
} }
/** /**

View File

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

View File

@@ -16,7 +16,7 @@ class Migration_database_optimizations extends Migration
*/ */
public function up(): void public function up(): void
{ {
error_log('Migrating database_optimizations'); log_message('info', 'Migrating database optimizations.');
$attribute = model(Attribute::class); $attribute = model(Attribute::class);
@@ -82,7 +82,7 @@ class Migration_database_optimizations extends Migration
helper('migration'); helper('migration');
execute_script(APPPATH . 'Database/Migrations/sqlscripts/3.4.0_database_optimizations.sql'); execute_script(APPPATH . 'Database/Migrations/sqlscripts/3.4.0_database_optimizations.sql');
error_log('Migrating database_optimizations completed'); log_message('info', 'Finished migrating database optimizations.');
} }
/** /**

View File

@@ -12,11 +12,11 @@ class Migration_remove_duplicate_links extends Migration
*/ */
public function up(): void public function up(): void
{ {
error_log('Migrating remove_duplicate_links'); log_message('info', 'Removing duplicate links.');
$this->migrate_duplicate_attribute_links(); $this->migrate_duplicate_attribute_links();
error_log('Migrating remove_duplicate_links completed'); log_message('info', 'Duplicate links removed.');
} }
/** /**

View File

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

View File

@@ -27,8 +27,6 @@ class Convert_to_ci4 extends Migration
*/ */
public function up(): void public function up(): void
{ {
error_log('Migrating database to CodeIgniter4 formats');
helper('migration'); helper('migration');
execute_script(APPPATH . 'Database/Migrations/sqlscripts/3.4.0_ci4_conversion.sql'); execute_script(APPPATH . 'Database/Migrations/sqlscripts/3.4.0_ci4_conversion.sql');
@@ -39,8 +37,6 @@ class Convert_to_ci4 extends Migration
} }
remove_backup(); remove_backup();
error_log('Migrating to CodeIgniter4 formats completed');
} }
/** /**

View File

@@ -11,6 +11,7 @@ class IntToTinyint extends Migration
*/ */
public function up(): void 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('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'); $this->db->query('ALTER TABLE ' . $this->db->prefixTable('cash_up') . ' MODIFY `note` tinyint NOT NULL DEFAULT 0');
} }
@@ -20,6 +21,7 @@ class IntToTinyint extends Migration
*/ */
public function down(): void 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('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'); $this->db->query('ALTER TABLE ' . $this->db->prefixTable('cash_up') . ' MODIFY `note` int NOT NULL DEFAULT 0');
} }

View File

@@ -11,6 +11,7 @@ class Migration_add_missing_config extends Migration
*/ */
public function up(): void public function up(): void
{ {
log_message('info', 'Adding missing configs.');
$image_values = [ $image_values = [
['key' => 'account_number', 'value' => ''], // This has no current maintenance, but it's used in Sales ['key' => 'account_number', 'value' => ''], // This has no current maintenance, but it's used in Sales
['key' => 'category_dropdown', 'value' => ''], ['key' => 'category_dropdown', 'value' => ''],

View File

@@ -11,6 +11,7 @@ class Migration_drop_account_number_index extends Migration
*/ */
public function up(): void 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') . ' DROP INDEX account_number');
$this->db->query('ALTER TABLE ' . $this->db->prefixTable('customers') . ' ADD INDEX account_number (account_number)'); $this->db->query('ALTER TABLE ' . $this->db->prefixTable('customers') . ' ADD INDEX account_number (account_number)');
} }

View File

@@ -25,7 +25,7 @@ class Migration_Convert_Barcode_Types extends Migration
*/ */
public function up(): void public function up(): void
{ {
log_message('info', 'Converting barcode types.');
$old_barcode_type = $this->config['barcode_type']; $old_barcode_type = $this->config['barcode_type'];
switch ($old_barcode_type) { switch ($old_barcode_type) {
@@ -52,6 +52,7 @@ class Migration_Convert_Barcode_Types extends Migration
*/ */
public function down(): void public function down(): void
{ {
log_message('info', 'Converting barcode types.');
$new_barcode_type = $this->config['barcode_type']; $new_barcode_type = $this->config['barcode_type'];
switch ($new_barcode_type) { switch ($new_barcode_type) {

View File

@@ -12,6 +12,7 @@ class Migration_fix_keys_for_db_upgrade extends Migration
*/ */
public function up(): void public function up(): void
{ {
log_message('info', 'Fixing keys for database upgrade.');
helper('migration'); helper('migration');
$forge = Database::forge(); $forge = Database::forge();

View File

@@ -13,6 +13,7 @@ class Migration_Attributes_fix_cascading_delete extends Migration
*/ */
public function up(): void public function up(): void
{ {
log_message('info', 'Fixing cascading deletes.');
helper('migration'); helper('migration');
$this->db->query("ALTER TABLE `ospos_attribute_links` DROP INDEX `attribute_links_uq3`"); $this->db->query("ALTER TABLE `ospos_attribute_links` DROP INDEX `attribute_links_uq3`");

View File

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

View File

@@ -12,7 +12,7 @@ class MigrationOptimizationIndices extends Migration
*/ */
public function up(): void public function up(): void
{ {
error_log('Migrating Optimization Indices'); log_message('info', 'Migrating Optimization Indices');
helper('migration'); helper('migration');
$forge = Database::forge(); $forge = Database::forge();
@@ -33,8 +33,6 @@ class MigrationOptimizationIndices extends Migration
$forge->addKey(['trans_items', 'trans_date'], false, false, 'trans_items_trans_date'); $forge->addKey(['trans_items', 'trans_date'], false, false, 'trans_items_trans_date');
$forge->processIndexes('inventory'); $forge->processIndexes('inventory');
} }
error_log('Migrating Optimization Indices');
} }
/** /**

View File

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

View File

@@ -0,0 +1,24 @@
<?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

@@ -0,0 +1,24 @@
<?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,8 +1,6 @@
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. # 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. # This accounts for dropdown rows (null item_id) and rows associated with sales or receivings.
ALTER TABLE `ospos_attribute_links` ALTER TABLE `ospos_attribute_links`
ADD COLUMN `generated_unique_column` VARCHAR(255) GENERATED ALWAYS AS ( ADD COLUMN `generated_unique_column` VARCHAR(255) GENERATED ALWAYS AS (
CASE CASE

View File

@@ -0,0 +1,11 @@
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

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

View File

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

View File

@@ -89,6 +89,8 @@ function get_languages(): array
'pt-BR:portuguese' => 'Portuguese (Brazil)', 'pt-BR:portuguese' => 'Portuguese (Brazil)',
'ro:romanian' => 'Romanian', 'ro:romanian' => 'Romanian',
'ru:russian' => 'Russian', 'ru:russian' => 'Russian',
'sw-KE:swahili' => 'Swahili (Kenya)',
'sw-TZ:swahili' => 'Swahili (Tanzania)',
'sv:swedish' => 'Swedish', 'sv:swedish' => 'Swedish',
'ta:tamil' => 'Tamil', 'ta:tamil' => 'Tamil',
'th:thai' => 'Thai', 'th:thai' => 'Thai',

View File

@@ -3,12 +3,14 @@
use Config\Database; use Config\Database;
/** /**
* Migration helper * Migration helper.
* @param string $path Path to migration script.
* @return bool Whether the migration executed successfully.
*/ */
function execute_script(string $path): void function execute_script(string $path): bool
{ {
$version = preg_replace("/(.*_)?(.*).sql/", "$2", $path); $version = preg_replace("/(.*_)?(.*).sql/", "$2", $path);
error_log("Migrating to $version (file: $path)"); log_message('info', "Migrating to $version (file: $path)");
$sql = file_get_contents($path); $sql = file_get_contents($path);
$sqls = explode(';', $sql); $sqls = explode(';', $sql);
@@ -16,17 +18,73 @@ function execute_script(string $path): void
$db = Database::connect(); $db = Database::connect();
$success = true; // whether *all* queries succeeded
foreach ($sqls as $statement) { foreach ($sqls as $statement) {
$statement = "$statement;"; $statement = "$statement;";
$hadError = !$db->simpleQuery($statement);
if (!$db->simpleQuery($statement)) { if ($hadError) {
$success = false;
foreach ($db->error() as $error) { foreach ($db->error() as $error) {
error_log("error: $error"); log_message('error', "error: $error");
} }
} }
} }
error_log("Migrated to $version"); if ($success) {
log_message('info', "Successfully migrated to $version");
}
else {
log_message('info', "Could not migrate to $version.");
}
return $success;
}
/**
* Migration helper that uses a transaction.
* @param string $path Path to migration script.
* @return bool Whether the migration executed successfully.
*/
function executeScriptWithTransaction(string $path): bool
{
$version = preg_replace("/(.*_)?(.*).sql/", "$2", $path);
log_message('info', "Migrating to $version (file: $path) with transaction");
$sql = file_get_contents($path);
$sqls = explode(';', $sql);
array_pop($sqls);
$db = Database::connect();
$db->transStart();
$success = true;
try {
foreach ($sqls as $statement) {
$statement = "$statement;";
$hadError = !$db->query($statement);
if ($hadError) {
$success = false;
foreach ($db->error() as $error) {
log_message('info', "error: $error");
}
}
}
} catch (Exception $e) {
log_message('info', "Could not migrate to $version: " . $e->getMessage());
$db->transRollback();
return false;
}
if ($success) {
log_message('info', "Successfully migrated to $version");
} else {
log_message('info', "Could not migrate to $version.");
}
$db->transComplete();
return $success;
} }
/** /**
@@ -212,6 +270,36 @@ function foreignKeyExists(string $constraintName, string $tableName): bool {
return $query->getNumRows() > 0; return $query->getNumRows() > 0;
} }
/**
* Drops a column from a table if it exists.
*
* @param string $table The name of the table.
* @param string $column The name of the column to drop.
* @return void
*/
function dropColumnIfExists(string $table, string $column): void
{
$prefix = overridePrefix();
$db = Database::connect();
$builder = $db->table('information_schema.COLUMNS');
// Check if the column exists in the table
$builder->select('COLUMN_NAME')
->where('TABLE_SCHEMA', $db->database)
->where('TABLE_NAME', $prefix . $table)
->where('COLUMN_NAME', $column);
$query = $builder->get();
if ($query->getNumRows() > 0)
{
// Drop the column if it exists
$db->query("ALTER TABLE `" . $prefix . "$table` DROP COLUMN `$column`");
}
overridePrefix($prefix);
}
/** /**
* Checks if the current database is MariaDB. * Checks if the current database is MariaDB.
* *

View File

@@ -109,13 +109,3 @@ function remove_backup(): void
log_message('info', "File $backup_path has been removed"); log_message('info', "File $backup_path has been removed");
} }
function purifyHtml($data)
{
if (is_array($data)) {
return array_map('purifyHtml', $data);
} elseif (is_string($data)) {
return Services::HtmlPurifier()->purify($data);
}
return $data;
}

View File

@@ -48,7 +48,7 @@ function transform_headers(array $headers, bool $readonly = false, bool $editabl
'field' => key($element), 'field' => key($element),
'title' => current($element), 'title' => current($element),
'switchable' => $element['switchable'] ?? !preg_match('(^$|&nbsp)', current($element)), 'switchable' => $element['switchable'] ?? !preg_match('(^$|&nbsp)', current($element)),
'escape' => !preg_match("/(edit|phone_number|email|messages|item_pic|customer_name|note)/", key($element)) && !(isset($element['escape']) && !$element['escape']), 'escape' => !preg_match("/(edit|email|messages|item_pic|customer_name|note)/", key($element)) && !(isset($element['escape']) && !$element['escape']),
'sortable' => $element['sortable'] ?? current($element) != '', 'sortable' => $element['sortable'] ?? current($element) != '',
'checkbox' => $element['checkbox'] ?? false, 'checkbox' => $element['checkbox'] ?? false,
'class' => isset($element['checkbox']) || preg_match('(^$|&nbsp)', current($element)) ? 'print_hide' : '', 'class' => isset($element['checkbox']) || preg_match('(^$|&nbsp)', current($element)) ? 'print_hide' : '',

View File

@@ -43,7 +43,7 @@ return [
"start_typing_supplier_name" => "ابداء بكتابة اسم المورد....", "start_typing_supplier_name" => "ابداء بكتابة اسم المورد....",
"stock" => "المخزون", "stock" => "المخزون",
"stock_destination" => "المخزون المحول له", "stock_destination" => "المخزون المحول له",
"stock_locaiton" => "مكان المخزون", "stock_location" => "مكان المخزون",
"stock_source" => "مصدر المخزون", "stock_source" => "مصدر المخزون",
"successfully_deleted" => "لقد تم الحذف", "successfully_deleted" => "لقد تم الحذف",
"successfully_updated" => "لقد تم التحديث", "successfully_updated" => "لقد تم التحديث",

View File

@@ -43,7 +43,7 @@ return [
"start_typing_supplier_name" => "ابداء بكتابة اسم المورد....", "start_typing_supplier_name" => "ابداء بكتابة اسم المورد....",
"stock" => "المخزون", "stock" => "المخزون",
"stock_destination" => "المخزون المحول له", "stock_destination" => "المخزون المحول له",
"stock_locaiton" => "مكان المخزون", "stock_location" => "مكان المخزون",
"stock_source" => "مصدر المخزون", "stock_source" => "مصدر المخزون",
"successfully_deleted" => "لقد تم الحذف", "successfully_deleted" => "لقد تم الحذف",
"successfully_updated" => "لقد تم التحديث", "successfully_updated" => "لقد تم التحديث",

View File

@@ -43,7 +43,7 @@ return [
"start_typing_supplier_name" => "Təchizatçıın adını yazmağa başlayın ...", "start_typing_supplier_name" => "Təchizatçıın adını yazmağa başlayın ...",
"stock" => "Ehtiyyat", "stock" => "Ehtiyyat",
"stock_destination" => "Ehtiyyatın Hədəfi", "stock_destination" => "Ehtiyyatın Hədəfi",
"stock_locaiton" => "Ehtiyyatın Yeri", "stock_location" => "Ehtiyyatın Yeri",
"stock_source" => "Ehtiyyatın Mənbəyi", "stock_source" => "Ehtiyyatın Mənbəyi",
"successfully_deleted" => "cəmi", "successfully_deleted" => "cəmi",
"successfully_updated" => "alışda sehv var", "successfully_updated" => "alışda sehv var",

View File

@@ -43,7 +43,7 @@ return [
"start_typing_supplier_name" => "Start Typing Supplier's name...", "start_typing_supplier_name" => "Start Typing Supplier's name...",
"stock" => "", "stock" => "",
"stock_destination" => "Stock Destination", "stock_destination" => "Stock Destination",
"stock_locaiton" => "Stock Location", "stock_location" => "Stock Location",
"stock_source" => "Stock Source", "stock_source" => "Stock Source",
"successfully_deleted" => "You have successfully deleted", "successfully_deleted" => "You have successfully deleted",
"successfully_updated" => "Receiving successfully updated", "successfully_updated" => "Receiving successfully updated",

View File

@@ -43,7 +43,7 @@ return [
"start_typing_supplier_name" => "Počnite upisivati ime dobavljača ...", "start_typing_supplier_name" => "Počnite upisivati ime dobavljača ...",
"stock" => "Skladište", "stock" => "Skladište",
"stock_destination" => "Destinacija skladišta", "stock_destination" => "Destinacija skladišta",
"stock_locaiton" => "Lokacija zaliha", "stock_location" => "Lokacija zaliha",
"stock_source" => "Izvor zaliha", "stock_source" => "Izvor zaliha",
"successfully_deleted" => "Uspješno ste izbrisali prijem", "successfully_deleted" => "Uspješno ste izbrisali prijem",
"successfully_updated" => "Uspješno ste ažurirali prijem", "successfully_updated" => "Uspješno ste ažurirali prijem",

View File

@@ -43,7 +43,7 @@ return [
'start_typing_supplier_name' => "دەست بکە بە نووسینی ناوی دابینکەر...", 'start_typing_supplier_name' => "دەست بکە بە نووسینی ناوی دابینکەر...",
'stock' => "کۆگا", 'stock' => "کۆگا",
'stock_destination' => "شوێنی مەبەستی کۆگا", 'stock_destination' => "شوێنی مەبەستی کۆگا",
'stock_locaiton' => "شوێنی کۆگا", 'stock_location' => "شوێنی کۆگا",
'stock_source' => "سەرچاوەی کۆگا", 'stock_source' => "سەرچاوەی کۆگا",
'successfully_deleted' => "بەسەرکەوتوویی سڕیتەوە", 'successfully_deleted' => "بەسەرکەوتوویی سڕیتەوە",
'successfully_updated' => "وەرگرتن بە سەرکەوتوویی نوێ کراوەتەوە", 'successfully_updated' => "وەرگرتن بە سەرکەوتوویی نوێ کراوەتەوە",

View File

@@ -43,7 +43,7 @@ return [
"start_typing_supplier_name" => "Začněte psát jméno dodavatele...", "start_typing_supplier_name" => "Začněte psát jméno dodavatele...",
"stock" => "Sklad", "stock" => "Sklad",
"stock_destination" => "Cílový sklad", "stock_destination" => "Cílový sklad",
"stock_locaiton" => "Umístění skladu", "stock_location" => "Umístění skladu",
"stock_source" => "", "stock_source" => "",
"successfully_deleted" => "Smazáno", "successfully_deleted" => "Smazáno",
"successfully_updated" => "Upraveno", "successfully_updated" => "Upraveno",

View File

@@ -43,7 +43,7 @@ return [
"start_typing_supplier_name" => "", "start_typing_supplier_name" => "",
"stock" => "", "stock" => "",
"stock_destination" => "", "stock_destination" => "",
"stock_locaiton" => "", "stock_location" => "",
"stock_source" => "", "stock_source" => "",
"successfully_deleted" => "", "successfully_deleted" => "",
"successfully_updated" => "", "successfully_updated" => "",

View File

@@ -43,7 +43,7 @@ return [
"start_typing_supplier_name" => "Lieferantenname eingeben", "start_typing_supplier_name" => "Lieferantenname eingeben",
"stock" => "", "stock" => "",
"stock_destination" => "Lagerort (Ziel)", "stock_destination" => "Lagerort (Ziel)",
"stock_locaiton" => "Lagerort", "stock_location" => "Lagerort",
"stock_source" => "Lagerort (Quelle)", "stock_source" => "Lagerort (Quelle)",
"successfully_deleted" => "Löschung erfolgreich", "successfully_deleted" => "Löschung erfolgreich",
"successfully_updated" => "Änderung erfolgreich", "successfully_updated" => "Änderung erfolgreich",

View File

@@ -43,7 +43,7 @@ return [
"start_typing_supplier_name" => "Eintippen des Namens des Lieferanten beginnen...", "start_typing_supplier_name" => "Eintippen des Namens des Lieferanten beginnen...",
"stock" => "Lager", "stock" => "Lager",
"stock_destination" => "Lagerort (Ziel)", "stock_destination" => "Lagerort (Ziel)",
"stock_locaiton" => "Lagerort", "stock_location" => "Lagerort",
"stock_source" => "Lagerort (Quelle)", "stock_source" => "Lagerort (Quelle)",
"successfully_deleted" => "Löschung erfolgreich", "successfully_deleted" => "Löschung erfolgreich",
"successfully_updated" => "Änderung erfolgreich", "successfully_updated" => "Änderung erfolgreich",

View File

@@ -43,7 +43,7 @@ return [
"start_typing_supplier_name" => "Πληκτρολογήστε το όνομα του Προμηθευτή...", "start_typing_supplier_name" => "Πληκτρολογήστε το όνομα του Προμηθευτή...",
"stock" => "Απόθεμα", "stock" => "Απόθεμα",
"stock_destination" => "Προορισμός Αποθέματος", "stock_destination" => "Προορισμός Αποθέματος",
"stock_locaiton" => "Τοποθεσία Αποθέματος", "stock_location" => "Τοποθεσία Αποθέματος",
"stock_source" => "Προέλευση Αποθέματος", "stock_source" => "Προέλευση Αποθέματος",
"successfully_deleted" => "Έχετε διαγράψει επιτυχώς", "successfully_deleted" => "Έχετε διαγράψει επιτυχώς",
"successfully_updated" => "Επιτυχής ενημέρωση Παραλαβής", "successfully_updated" => "Επιτυχής ενημέρωση Παραλαβής",

View File

@@ -43,7 +43,7 @@ return [
"start_typing_supplier_name" => "Start Typing Supplier's name...", "start_typing_supplier_name" => "Start Typing Supplier's name...",
"stock" => "Stock", "stock" => "Stock",
"stock_destination" => "Stock Destination", "stock_destination" => "Stock Destination",
"stock_locaiton" => "Stock Location", "stock_location" => "Stock Location",
"stock_source" => "Stock Source", "stock_source" => "Stock Source",
"successfully_deleted" => "You have successfully deleted receiving", "successfully_deleted" => "You have successfully deleted receiving",
"successfully_updated" => "Receiving successfully updated", "successfully_updated" => "Receiving successfully updated",

View File

@@ -146,4 +146,5 @@ return [
"used" => "Points Used", "used" => "Points Used",
"work_orders" => "Work Orders", "work_orders" => "Work Orders",
"zero_and_less" => "Zero and Less", "zero_and_less" => "Zero and Less",
"toggle_cost_and_profit" => "Toggle Cost & Profit",
]; ];

View File

@@ -14,7 +14,9 @@ return [
"current_password_invalid" => "Current Password is invalid.", "current_password_invalid" => "Current Password is invalid.",
"employee" => "Employee", "employee" => "Employee",
"error_adding_updating" => "Employee add or update failed.", "error_adding_updating" => "Employee add or update failed.",
"error_deleting_admin" => "You cannot delete an admin user.",
"error_deleting_demo_admin" => "You can not delete the demo admin user.", "error_deleting_demo_admin" => "You can not delete the demo admin user.",
"error_updating_admin" => "You cannot modify an admin user.",
"error_updating_demo_admin" => "You can not change the demo admin user.", "error_updating_demo_admin" => "You can not change the demo admin user.",
"language" => "Language", "language" => "Language",
"login_info" => "Login", "login_info" => "Login",

View File

@@ -43,7 +43,7 @@ return [
"start_typing_supplier_name" => "Start Typing Supplier's name...", "start_typing_supplier_name" => "Start Typing Supplier's name...",
"stock" => "Stock", "stock" => "Stock",
"stock_destination" => "Stock Destination", "stock_destination" => "Stock Destination",
"stock_locaiton" => "Stock Location", "stock_location" => "Stock Location",
"stock_source" => "Stock Source", "stock_source" => "Stock Source",
"successfully_deleted" => "You have successfully deleted", "successfully_deleted" => "You have successfully deleted",
"successfully_updated" => "Receiving successfully updated", "successfully_updated" => "Receiving successfully updated",

View File

@@ -146,4 +146,5 @@ return [
"used" => "Points Used", "used" => "Points Used",
"work_orders" => "Work Orders", "work_orders" => "Work Orders",
"zero_and_less" => "Zero and less", "zero_and_less" => "Zero and less",
"toggle_cost_and_profit" => "Toggle Cost & Profit",
]; ];

View File

@@ -43,7 +43,7 @@ return [
"start_typing_supplier_name" => "Empieza a escribir el nombre del proveedor...", "start_typing_supplier_name" => "Empieza a escribir el nombre del proveedor...",
"stock" => "Inventario", "stock" => "Inventario",
"stock_destination" => "Inventario de Destino", "stock_destination" => "Inventario de Destino",
"stock_locaiton" => "Ubicación de Inventario", "stock_location" => "Ubicación de Inventario",
"stock_source" => "Inventario de Origen", "stock_source" => "Inventario de Origen",
"successfully_deleted" => "Borro exitosamente", "successfully_deleted" => "Borro exitosamente",
"successfully_updated" => "Recepción exitosamente actualizada", "successfully_updated" => "Recepción exitosamente actualizada",

View File

@@ -43,7 +43,7 @@ return [
"start_typing_supplier_name" => "Empiece a escribir el nombre del Proveedor...", "start_typing_supplier_name" => "Empiece a escribir el nombre del Proveedor...",
"stock" => "Existencia", "stock" => "Existencia",
"stock_destination" => "Destino del Inventario", "stock_destination" => "Destino del Inventario",
"stock_locaiton" => "Ubicación del Inventario", "stock_location" => "Ubicación del Inventario",
"stock_source" => "Origen del Inventario", "stock_source" => "Origen del Inventario",
"successfully_deleted" => "Se ha borrado exitosamente", "successfully_deleted" => "Se ha borrado exitosamente",
"successfully_updated" => "Recepción actualizada exitosamente", "successfully_updated" => "Recepción actualizada exitosamente",

View File

@@ -43,7 +43,7 @@ return [
"start_typing_supplier_name" => "شروع به تایپ کردن نام ارائه دهنده ...", "start_typing_supplier_name" => "شروع به تایپ کردن نام ارائه دهنده ...",
"stock" => "موجودی", "stock" => "موجودی",
"stock_destination" => "مقصد سهام", "stock_destination" => "مقصد سهام",
"stock_locaiton" => "موقعیت مکانی سهام", "stock_location" => "موقعیت مکانی سهام",
"stock_source" => "منبع سهام", "stock_source" => "منبع سهام",
"successfully_deleted" => "شما با موفقیت حذف شده اید", "successfully_deleted" => "شما با موفقیت حذف شده اید",
"successfully_updated" => "دریافت با موفقیت به روز شد", "successfully_updated" => "دریافت با موفقیت به روز شد",

View File

@@ -43,7 +43,7 @@ return [
"start_typing_supplier_name" => "Commencez à saisir le nom du fournisseur...", "start_typing_supplier_name" => "Commencez à saisir le nom du fournisseur...",
"stock" => "Inventaire", "stock" => "Inventaire",
"stock_destination" => "Destination de stock", "stock_destination" => "Destination de stock",
"stock_locaiton" => "Emplacement du stock", "stock_location" => "Emplacement du stock",
"stock_source" => "Source de stock", "stock_source" => "Source de stock",
"successfully_deleted" => "Suppression réussie", "successfully_deleted" => "Suppression réussie",
"successfully_updated" => "Réception correctement mise à jour", "successfully_updated" => "Réception correctement mise à jour",

View File

@@ -43,7 +43,7 @@ return [
"start_typing_supplier_name" => "התחל להקליד את שם הספק ...", "start_typing_supplier_name" => "התחל להקליד את שם הספק ...",
"stock" => "מלאי", "stock" => "מלאי",
"stock_destination" => "יעד מלאי", "stock_destination" => "יעד מלאי",
"stock_locaiton" => "מיקום מלאי", "stock_location" => "מיקום מלאי",
"stock_source" => "מקור מלאי", "stock_source" => "מקור מלאי",
"successfully_deleted" => "נמחק בהצלחה", "successfully_deleted" => "נמחק בהצלחה",
"successfully_updated" => "החזרה עודכנה בהצלחה", "successfully_updated" => "החזרה עודכנה בהצלחה",

View File

@@ -43,7 +43,7 @@ return [
"start_typing_supplier_name" => "Počnite upisivati ime dobavljača ...", "start_typing_supplier_name" => "Počnite upisivati ime dobavljača ...",
"stock" => "", "stock" => "",
"stock_destination" => "Na skladište", "stock_destination" => "Na skladište",
"stock_locaiton" => "Mjesto skladišta", "stock_location" => "Mjesto skladišta",
"stock_source" => "Iz skladišta", "stock_source" => "Iz skladišta",
"successfully_deleted" => "Uspješno ste obrisali primku", "successfully_deleted" => "Uspješno ste obrisali primku",
"successfully_updated" => "Uspješno ste ažurirali primku", "successfully_updated" => "Uspješno ste ažurirali primku",

View File

@@ -43,7 +43,7 @@ return [
"start_typing_supplier_name" => "Kezdje gépelni a beszállitó nevét", "start_typing_supplier_name" => "Kezdje gépelni a beszállitó nevét",
"stock" => "", "stock" => "",
"stock_destination" => "Célraktár", "stock_destination" => "Célraktár",
"stock_locaiton" => "Raktár helyszin", "stock_location" => "Raktár helyszin",
"stock_source" => "Raktár forrás", "stock_source" => "Raktár forrás",
"successfully_deleted" => "Sikeres törlés", "successfully_deleted" => "Sikeres törlés",
"successfully_updated" => "Átvétel sikeresen módositva", "successfully_updated" => "Átvétel sikeresen módositva",

View File

@@ -43,7 +43,7 @@ return [
"start_typing_supplier_name" => "", "start_typing_supplier_name" => "",
"stock" => "", "stock" => "",
"stock_destination" => "", "stock_destination" => "",
"stock_locaiton" => "", "stock_location" => "",
"stock_source" => "", "stock_source" => "",
"successfully_deleted" => "", "successfully_deleted" => "",
"successfully_updated" => "", "successfully_updated" => "",

View File

@@ -1,89 +1,89 @@
<?php <?php
return [ return [
"address_1" => "Alamat 1", 'address_1' => "Alamat 1",
"address_2" => "Alamat 2", 'address_2' => "Alamat 2",
"admin" => "", 'admin' => "",
"city" => "Kota", 'city' => "Kota",
"clerk" => "", 'clerk' => "",
"close" => "Tutup", 'close' => "Tutup",
"color" => "", 'color' => "",
"comments" => "Komentar", 'comments' => "Komentar",
"common" => "umum", 'common' => "umum",
"confirm_search" => "Anda telah memilih satu atau beberapa baris, ini tidak akan dipilih lagi setelah pencarian Anda. Apakah Anda yakin ingin mengirimkan pencarian ini?", 'confirm_search' => "Anda telah memilih satu atau beberapa baris, ini tidak akan dipilih lagi setelah pencarian Anda. Apakah Anda yakin ingin mengirimkan pencarian ini?",
"copyrights" => "© 2010 - {0}", 'copyrights' => "© 2010 - {0}",
"correct_errors" => "Silahkan perbaiki kesalahan sebelum menyimpan", 'correct_errors' => "Silahkan perbaiki kesalahan sebelum menyimpan",
"country" => "Negara", 'country' => "Negara",
"dashboard" => "", 'dashboard' => "",
"date" => "Tanggal", 'date' => "Tanggal",
"delete" => "Hapus", 'delete' => "Hapus",
"det" => "detil", 'det' => "detail",
"download_import_template" => "Unduh yang Diimpor dalam format CSV (CSV)", 'download_import_template' => "Unduh yang Diimpor dalam format CSV (CSV)",
"edit" => "ubah", 'edit' => "ubah",
"email" => "Email", 'email' => "Surel",
"email_invalid_format" => "Alamat email tidak dalam format yang benar.", 'email_invalid_format' => "Alamat surel tidak dalam format yang benar.",
"export_csv" => "Ekspor ke CSV", 'export_csv' => "Ekspor ke CSV",
"export_csv_no" => "Tidak", 'export_csv_no' => "Tidak",
"export_csv_yes" => "Ya", 'export_csv_yes' => "Ya",
"fields_required_message" => "Bagian yang berwarna merah harus diisi", 'fields_required_message' => "Bagian yang berwarna merah harus diisi",
"fields_required_message_unique" => "", 'fields_required_message_unique' => "",
"first_name" => "Nama Depan", 'first_name' => "Nama Depan",
"first_name_required" => "Nama Depan harus diisi.", 'first_name_required' => "Nama Depan harus diisi.",
"first_page" => "Pertama", 'first_page' => "Pertama",
"gender" => "Jenis Kelamin", 'gender' => "Jenis Kelamin",
"gender_female" => "P", 'gender_female' => "P",
"gender_male" => "L", 'gender_male' => "L",
"gender_undefined" => "", 'gender_undefined' => "",
"icon" => "ikon", 'icon' => "Ikon",
"id" => "Nomor ID", 'id' => "ID",
"import" => "Impor", 'import' => "Impor",
"import_change_file" => "Ubah", 'import_change_file' => "Ubah",
"import_csv" => "Impor dari CSV", 'import_csv' => "Impor dari CSV",
"import_full_path" => "Diperlukan alamat lengkap file CSV", 'import_full_path' => "Diperlukan alamat lengkap file CSV",
"import_remove_file" => "Hapus", 'import_remove_file' => "Hapus",
"import_select_file" => "Pilih file", 'import_select_file' => "Pilih file",
"inv" => "Persediaan", 'inv' => "Persediaan",
"last_name" => "Nama Belakang", 'last_name' => "Nama Belakang",
"last_name_required" => "Nama belakang harus diisi.", 'last_name_required' => "Nama belakang harus diisi.",
"last_page" => "Akhir", 'last_page' => "Akhir",
"learn_about_project" => "Untuk mempelajari informasi terbaru tentang proyek ini.", 'learn_about_project' => "Untuk mempelajari informasi terbaru tentang proyek ini.",
"list_of" => "Daftar", 'list_of' => "Daftar",
"logo" => "Logo", 'logo' => "Logo",
"logo_mark" => "Tanda", 'logo_mark' => "Tanda",
"logout" => "Keluar", 'logout' => "Keluar",
"manager" => "", 'manager' => "",
"migration_needed" => "Migrasi data ke {0} akan dimulai setelah masuk.", 'migration_needed' => "Migrasi data ke {0} akan dimulai setelah masuk.",
"new" => "Baru", 'new' => "Baru",
"no" => "Tidak", 'no' => "Tidak",
"no_persons_to_display" => "Tidak ada orang yang ditampilkan.", 'no_persons_to_display' => "Tidak ada orang yang ditampilkan.",
"none_selected_text" => "[Pilih]", 'none_selected_text' => "[Pilih]",
"or" => "ATAU", 'or' => "ATAU",
"people" => "", 'people' => "",
"phone_number" => "Nomor Telepon", 'phone_number' => "Nomor Telepon",
"phone_number_required" => "Nomer Telepon Wajib Diisi", 'phone_number_required' => "Nomer Telepon Wajib Diisi",
"please_visit_my" => "Silahkan kunjungi", 'please_visit_my' => "Silahkan kunjungi",
"position" => "", 'position' => "",
"powered_by" => "Diberdayakan oleh", 'powered_by' => "Diberdayakan oleh",
"price" => "Harga", 'price' => "Harga",
"print" => "Cetak", 'print' => "Cetak",
"remove" => "Hapus", 'remove' => "Hapus",
"required" => "Diperlukan", 'required' => "Diperlukan",
"restore" => "Kembalikan", 'restore' => "Kembalikan",
"return_policy" => "Kebijakan Retur", 'return_policy' => "Kebijakan Retur",
"search" => "Cari", 'search' => "Cari",
"search_options" => "Pilihan pencarian", 'search_options' => "Pilihan pencarian",
"searched_for" => "Mencari untuk", 'searched_for' => "Mencari untuk",
"software_short" => "OSPOS", 'software_short' => "OSPOS",
"software_title" => "Sumber Terbuka Titik Penjualan", 'software_title' => "Sumber Terbuka Titik Penjualan",
"state" => "Provinsi", 'state' => "Provinsi",
"submit" => "Kirim", 'submit' => "Kirim",
"total_spent" => "Total", 'total_spent' => "Total",
"unknown" => "Tidak diketahui", 'unknown' => "Tidak diketahui",
"view_recent_sales" => "Lihat Penjualan Terkini", 'view_recent_sales' => "Lihat Penjualan Terkini",
"website" => "Situs", 'website' => "Situs",
"welcome" => "Selamat Datang", 'welcome' => "Selamat Datang",
"welcome_message" => "Selamat Datang di OSPOS, klik modul di bawah ini untuk memulai.", 'welcome_message' => "Selamat Datang di OSPOS, klik modul di bawah ini untuk memulai.",
"yes" => "Iya", 'yes' => "Iya",
"you_are_using_ospos" => "Anda menggunakan Open Source Point Of Sale Versi", 'you_are_using_ospos' => "Anda menggunakan Open Source Point Of Sale Versi",
"zip" => "Kode POS", 'zip' => "Kode POS",
]; ];

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