Commit Graph

86 Commits

Author SHA1 Message Date
Ollama
8bb31a9e30 fix: Make item_sort_columns return format compatible with sanitizeSortColumn
- sanitizeSortColumn expects nested array format [['col' => 'label'], ...]
- Reuse item_headers() as base and add attribute columns
- This maintains DRY principle by not redefining columns twice
2026-03-29 07:44:04 +00:00
Ollama
4cb70c4a76 style: Apply PSR-12 formatting
- Fix PHPDoc comment format in item_sort_columns() helper
- Remove duplicate blank line after properties in Item model
- Remove unused variable assignment in Items controller
2026-03-19 18:21:54 +00:00
Ollama
1ffe142f83 Refactor: Use existing sanitizeSortColumn method with item_sort_columns helper
- Add item_sort_columns() helper function in tabular_helper.php
- Helper returns all sortable columns including dynamic attribute IDs
- Remove duplicate sanitizeSortColumnAttribute method from Items controller
- Remove unused ALLOWED_SORT_COLUMNS constant from Item model
- Reuses existing sanitizeSortColumn method from Secure_Controller
2026-03-19 18:21:54 +00:00
Ollama
7b9bd664ab Implement Phase 3: Multi-attribute search AND logic and Phase 4: Sort by attribute columns
Phase 3 - Multi-attribute Search:
- Add parse_attribute_search() method to parse search syntax like
  'color: blue size: large' or 'color:blue AND size:large'
- Update search_by_attributes() to support AND/OR logic for multiple
  attribute queries
- Add search_by_attribute_value() private method for single value search

Phase 4 - Sort by Attribute Columns:
- Add get_attribute_sort_definition_id() method to detect attribute
  column sorting
- Update Item::search() to join attribute tables when sorting by
  attribute columns
- Update tabular_helper to make attribute columns sortable
- Add sanitizeSortColumnAttribute() method in Items controller to
  validate attribute definition IDs as sort columns

Fixes #2722 - sorting by attribute columns now works
2026-03-19 18:21:54 +00:00
jekkos
c482e75304 Fix DECIMAL attribute not respecting locale format (#4422)
* Fix DECIMAL attribute not respecting locale format

Issue: DECIMAL attribute values were displayed as raw database values
instead of being formatted according to the user's locale settings.

Fix:
1. Modified Attribute::get_definitions_by_flags() to optionally return
   definition types along with names (new $include_types parameter)
2. Updated expand_attribute_values() in tabular_helper.php to detect
   DECIMAL attributes and apply to_decimals() locale formatting
3. Updated callers (Reports, Items table) to pass include_types=true
   where attributes are displayed

The DECIMAL values in table views (items, sales reports, receiving reports)
now respect the configured locale number format, matching DATE attributes
which already use locale-based formatting.

* Apply PSR-12 camelCase naming to new variables

Response to PR review comments:
- Rename  to
- Rename  to
- Rename  to

---------

Co-authored-by: Ollama <ollama@steganos.dev>
2026-03-13 21:23:52 +00:00
jekkos
f7e8d6e427 Add filter persistence for table views via URL query string (#4400)
This commit adds URL-based filter persistence for table views, allowing
users to navigate away from a filtered view (e.g., clicking into sale
details) and return without losing their filter settings.

The solution uses history.replaceState() to update the URL without
triggering a page reload, providing a seamless user experience while
maintaining shareable/bookmarkable URLs.

Fixes navigation issue where filters are lost when viewing details or
navigating away from table views.

* Move filter restoration to server-side for cleaner architecture

Changes:
- Controllers now restore filters from URL query string on initial page load:
  * Sales.php: Reads start_date, end_date, and filters[] from GET
  * Items.php: Reads start_date, end_date, filters[], and stock_location
  * Expenses.php: Reads start_date, end_date, and filters[]
  * Cashups.php: Reads start_date, end_date, and filters[]

- Views now receive restored filter values from controllers:
  * Server-side date override via JavaScript variables
  * form_multiselect() receives $selected_filters from controller
  * Removed setTimeout hack from table_filter_persistence.php

- Simplified table_filter_persistence.php:
  * Now only handles URL updates on filter changes
  * No longer responsible for restoring state
  * Cleaner, single responsibility (client-side URL management)

Benefits:
- Works without JavaScript for initial render
- Cleaner architecture (server controls initial state)
- Client-side JS only handles "live" filter updates
- Filters persist across navigation via URL query string
- Shareable/bookmarkable URLs

How it works:
1. User visits /sales/manage?start_date=2024-01-01&filters[]=only_cash
2. Controller reads GET params and passes to view
3. View renders with correct initial filter values
4. User changes filter → JavaScript updates URL via replaceState()
5. User navigates away and back → Controller restores from URL again

* Refactor filter restoration into helper function and use PSR-12 naming

* Use array_merge with helper to reduce code duplication

---------

Co-authored-by: Ollama <ollama@steganos.dev>
2026-03-11 20:11:00 +01:00
Ollama
a229bf6031 Fix stored XSS vulnerabilities in employee permissions and customer data
1. Stock Location XSS (GHSA-7hg5-68rx-xpmg):
   - Stock location names were rendered unescaped in employee form
   - Malicious stock locations could contain XSS payloads that execute
     when viewing employee permissions
   - Fixed by adding esc() to permission display in employees/form.php

2. Customer Name XSS (GHSA-hcfr-9hfv-mcwp):
   - Bootstrap-table columns had escape disabled for customer_name,
     email, phone_number, and note fields
   - Malicious customer names could execute XSS in Daily Sales view
   - Fixed by removing user-controlled fields from escape exception list
   - Only 'edit', 'messages', and 'item_pic' remain in exception list
     (these contain safe server-generated HTML)

Both vulnerabilities allow authenticated attackers with basic permissions
to inject JavaScript that executes in admin/other user sessions.
2026-03-08 18:42:30 +01:00
jekkos
3a33098776 Fix: Handle image filenames with spaces in thumbnails
- URL-encode filenames when constructing image/thumbnail URLs
- Decode filename parameter in getPicThumb() controller
- Prevents Apache AH10411 error with spaces in rewritten URLs

Fixes #4372
2026-03-06 17:09: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
849439c71e Fix multiple XSS vulnerabilities (#3965) (#4356) 2025-12-22 17:21:49 +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
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
jekkos
0d1f4efe3c Extended payment delete fix (#4274)
* Create a  Base64 URL-Safe encoding and decoding helper

* Rename web_helper to url_helper

---------

Co-authored-by: El_Coloso <diegoramosp@gmail.com>
2025-07-07 13:57:03 +02:00
objecttothis
6f587498e6 Migration fix for MariaDB databases
- This fix properly creates Primary Keys on both MariaDB and MySQL

Signed-off-by: objecttothis <objecttothis@gmail.com>
2025-06-01 10:15:57 +02:00
objecttothis
e1fedab9b7 Bugfix: constraint migration fixes (#4230)
- Refactored function names for PSR-12 compliance
- Programmatically cascade delete attribute_link rows when a drop-down attribute is deleted but leave attribute_link rows associated with transactions.
- Added `WHERE item_id IS NOT NULL` to migration to prevent failure on MySQL databases during migration
- Retroactive correction of migration to prevent MySQL databases from failing.
- Refactored generic functions to helper
- Reverted attribute_links foreign key to ON DELETE RESTRICT which is required for a unique constraint on this table. Cascading deletes are now handled programmatically.
- Migration Session table to match Code Igniter 4.6
- Add index to attribute_links to prevent query timeout in items view on large databases
- Added overridePrefix() function to the migration_helper. Any time QueryBuilder is adding a prefix to the query when we don't want it to, this query can be used to override the prefix then set it back after you're done.
- Added dropAllForeignKeyConstraints() helper function.
- Added deleteIndex() helper function.
- Added indexExists() helper function.
- Added primaryKeyExists() helper function.
- Added recreateForeignKeyConstraints() helper function.
- Added CRUD section headings to the Attribute model.
- Replaced `==` with `===` to prevent type juggling.
- Removed unused delete_value function.
- Reworked deleteDefinition() and deleteDefinitionList() functions to delete rows from the attribute_links table which are associated.
- Added deleteAttributeLinksByDefinitionId() function

Implement Cascading Delete
- Function to delete attribute links with one or more attribute definitions.
- Call function to implement an effective cascading delete.
- Refactor function naming to meet PSR-12 conventions

Fix Migration
- Add drop of Generated Column to prevent failure of migration on MySQL databases.

Fix Migration
- Removed blank lines
- Refactored function naming for PSR compliance
- Reformatted code for PSR compliance
- Added logic to drop dependent foreign key constraints before deleting an index then recreating them.

Migrate ospos_sessions table
- DROP and CREATE session table to prevent migration problems on populated databases

Fixed Bug in Migration
- In the event that item_id = null (e.g., it's a dropdown) it should not be included in the results.

Fixed bug in Dropdown deletes
- Removed delete_value function in Attributes Controller as it is unused.
- Renamed postDelete_attribute_value function for PSR-12 compliance.
- Renamed delete_value Attribute model function for PSR-12 compliance.
- Refactored out function to getAttributeIdByValue
- Replaced == with === to prevent type juggling
- Reorganized parts of model to make it easier to find CRUD functions.

Refactoring
- PSR-12 Compliance formatting changes
- Refactored several generic functions into the migration_helper.php
- First check if primary key exists before attempting to create it.
- Grouped functions together in migration_helper.php
- phpdoc commenting functions

Optimizing Indices
- There are two queries run while opening the Items view which time out on large databases with weak hardware. These indices cut the query execution in half or better.

Add Unique constraint back into attribute_links
- This migration reverts ospos_attribute_links_ibfk_1 and 2 to ON DELETE RESTRICT. Cascade delete is done programmatically. This is needed to have a unique column on the attribute_links table which prevents duplicate attributes from begin created with the same item_id-attribute_id-definition_id combination

Correct spacing after if for PSR-12

Minor code cleanup.
- Removed Comments separating sections of code in Attribute model
- Removed extra log line to prevent cluttering of the log
2025-05-29 15:24:08 +04:00
BudsieBuds
e83c23cf0c Improve code style and PSR-12 compliance (#4204)
* Improve code style and PSR-12 compliance
- refactored code formatting to adhere to PSR-12 guidelines
- standardized coding conventions across the codebase
- added missing framework files and reverted markup changes
- reformatted arrays for enhanced readability
- updated language files for consistent styling and clarity
- minor miscellaneous improvements
2025-05-02 19:37:06 +02:00
BudsieBuds
3e996b7818 Update language names (#4218) 2025-04-16 07:16:28 +02:00
BudsieBuds
82f0e75bf0 Fix PHP 8.4 errors (#4200) 2025-04-15 20:38:52 +02:00
BudsieBuds
766b3b967e Convert language ku to ckb (#4211)
- convert ku (Kurdish) to ckb (Central Kurdish)
- replaced tabs with spaces
- replace single quotation marks with double
2025-04-15 08:31:40 +02:00
BudsieBuds
a62bef53b4 Add Kurdish language option to UI (#4210) 2025-04-14 18:33:05 +02:00
objecttothis
e90b5b87da Replace tabs with spaces (#4196)
Signed-off-by: objecttothis <objecttothis@gmail.com>
2025-03-28 21:24:21 +04:00
jekkos
cf73ffa825 Fix attribute dropdown delete (#4176) 2025-03-01 00:37:23 +01:00
jekkos
1378794e7e Revert "Use app language for current_lang (#4175)"
This reverts commit 19974bc8e0.
2025-02-15 01:10:16 +01:00
jekkos
882f3b4522 Fix table header translations (#4175) 2025-02-15 01:08:19 +01:00
jekkos
19974bc8e0 Use app language for current_lang (#4175) 2025-02-10 08:53:11 +01:00
jekkos
ac90c07c90 Remove support for PHP7.4 for now 2025-01-13 01:13:28 +01:00
jekkos
c81c546286 Remove prepare_decimal and filter_var 2025-01-13 01:13:28 +01:00
Derek Christman
a87b6eebb2 Removed PSR12 reformatting 2025-01-13 01:13:28 +01:00
Derek Christman
487e7dc0bd Revert "Fixed cast to int and inadvertant cast of false to double when parsing locale values to float"
This reverts commit 3e4c987894e3790f671e49398c9db7820bc3378d.
2025-01-13 01:13:28 +01:00
Derek Christman
467144f884 Fixed cast to int and inadvertant cast of false to double when parsing locale values to float 2025-01-13 01:13:28 +01:00
jekkos
2f365dce91 Parse prices directly using numberformatter (#4107) 2025-01-13 01:13:28 +01:00
jekkos
3cac58965a Remove html space in headers (#4125) 2024-11-29 00:25:33 +01:00
objecttothis
d946b31cf4 Bugfix Attributes not saving (#4080)
Fixed issue with Attribute Values not saving correctly

This issue was caused by the Attribute->attributeValueExists function receiving a date which was already in Y-m-d format, so the conversion was returning false. Added logic to pass the date through if it was already in Y-m-d format.

Signed-off-by: objecttothis <objecttothis@gmail.com>
2024-11-05 22:37:47 +01:00
jekkos
691ba1e8ca Fix definition flags (#4081) 2024-10-05 02:45:39 +02:00
jekkos
0f4d06af61 Blind SQL injection fix (#3284) 2024-10-03 00:00:55 +02:00
jekkos
72f147074d Enable html escape + fix XSS (#3965) 2024-10-02 21:29:09 +02:00
jekkos
4293f70cd5 Fix column refresh after attribute delete (#2911) 2024-09-20 01:15:13 +02:00
objecttothis
6eb22276f3 Locale handling of decimals in attribute saves
- Added check in controller to convert locale-specific decimal formats to use a period decimal separator.
- Added PHPdoc explanation

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

Add TODO to clarify workaround

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

Fixed bugs in SQL

- Added checks before attempting to delete non-existing values.
- Corrected function which deletes duplicate attribute values and replaces the attribute_ids

Signed-off-by: objecttothis <objecttothis@gmail.com>
2024-09-16 14:18:17 +02:00
jekkos
f49d763254 XSS mitigation features (#4041)
* Remove HtmlPurifier calls

- All calls to Services::htmlPurifier()->purify() removed from data received from view.
- Bootstrap and bootswatch bump in package-lock.json

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

* Pre-view filtering Items Controller

- Refactored code for clarity
- Created and called sanitization functions.
- Sanitize TEXT type Attributes before being sent to the view.

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

* Pre-view filtering Customers Controller

- Refactored code for clarity
- Replaced == with === operator to prevent type juggling
- Added Sanitization of Customer data before being sent to the view

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

* Bump bootstrap-table to 1.23.1

- Bump bootstrap-table to 1.23.1 in attempt to resolve issue with sticky headers
- Sanitize attribute data in tables
- Sanitize item data with controller function.

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

* Pre-view filtering Items Controller

- Refactored code for clarity
- Created and called sanitization functions.
- Sanitize TEXT type Attributes before being sent to the view.

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

* Sanitize Item data

- Sanitize category and item_number before display in forms.
- refactor check in pic_filename for empty to be best practices compliant.
- Added TODO

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

* Minor changes

- Refactored for code clarity.
- Removed extra blank lines.
- Minor reformatting.
- Added PHPdocs
- bumped bootstrap-table to 1.23.2

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

* Pre-view filtering Items Controller

- Refactored code for clarity
- Created and called sanitization functions.
- Sanitize TEXT type Attributes before being sent to the view.

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

* Sanitize Item data

- Sanitize category and item_number before display in forms.
- refactor check in pic_filename for empty to be best practices compliant.
- Added TODO

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

---------

Signed-off-by: objecttothis <objecttothis@gmail.com>
Co-authored-by: objecttothis <objecttothis@gmail.com>
2024-08-26 11:35:56 +04:00
Steve Ireland
05538570ec Supplementing issue #3997, this change allows the discount amount to be deleted by the user (instead of needing to enter a zero). 2024-07-26 21:36:19 +02:00
BudsieBuds
c39b733c90 Language fallback improvement
- Changes for following best practice for CI4 localization
- Norwegian and Urdu languages now working again
- Sort languages by alphabet in config
2024-06-15 17:19:15 +02:00
objecttothis
1328b4d9b8 - Removed TODOs that had been completed
- Added TODO where we need to convert to querybuilder
- Converted to switch statement.
- Removed unnecessary local variable
- Replaced Qualifiers with imports
- Replaced isset() call with null coalescing operator
- Replaced strpos function calls in if statements with str_contains calls
- Removed unnecessary leading \ in use statement
- Replaced deprecated functions
- Updated PHPdocs to match function signature
- Added missing type declarations
- Made class variables private.
- Explicitly declared dynamic properties
- use https:// links instead of http://
- Fixed type error from sending null when editing transactions
- Fixed Search Suggestion function name in Employees, Persons, Suppliers controller
- Fixed function name on Receivings Controller

Signed-off-by: objecttothis <objecttothis@gmail.com>
2024-06-15 17:19:15 +02:00
objecttothis
68d3482065 Attribute item form and decimal fixes
- Updated formatting to reflect standard
- Wrapped Decimal type in to_decimals() function for localization
- Fixed function name
- Removed unneeded TODO
- Fixed problems with sales register not receiving decimals with comma for separator properly.

Signed-off-by: objecttothis <objecttothis@gmail.com>
2024-06-15 17:19:15 +02:00
objecttothis
6d37414444 Removed escaping 2024-06-15 17:19:15 +02:00
objecttothis
a6b674e995 Barcode & escaping
- Removed overflow-visible as it is not needed.
- Bumped TamTamChik/nameCase to latest.
- Workaround to prevent nameCase from capitalizing the first letter of html entities
- Autoload security_helper.php
- Develop means of escaping outputs without encoding characters we don't want encoded.
- proof of concept in form_basic_info.php
2024-06-15 17:19:15 +02:00
objecttothis
e327bb3780 Suppliers Fixes
- Added html_entity_decode() to outputs which had been html encoded
- Added escaping of direct data from the database.
2024-06-15 17:19:15 +02:00
objecttothis
68d6479f0d Decimal changes
- Format percentage per locale rules
- Format sequence as integer, not per quantity rules
- Minor formatting changes
2024-06-15 17:19:15 +02:00
objecttothis
7356500d86 - Fixed missing call to helper and helper function
- Format percentage per locale rules
- Moved constants to Constants.php
- Added PHPdoc comments
- Refactor code for clarity and simplicity.
- Added decimal formatting per locale for display.
- autoload locale helper
- Remove unneeded calls to helpers
- Removed unneeded comments
- fixed errors causing checks in parse_decimals to return false due to locales which use a comma.
2024-06-15 17:19:15 +02:00
objecttothis
61cc93ab57 Updated helper
- Removed TODO which is already a github issue (https://github.com/opensourcepos/opensourcepos/issues/3833)
- Removed call to auto_detect_line_endings which was deprecated in php 8.1. This only negatively affects files created using macOS 9 or earlier which had an EOL in 2002.
- Updated PHPdoc comments
- Removed unnecessary comments
2024-06-15 17:19:15 +02:00