Replace hardcoded string concatenation of the app name and version in the
document <title> with named-placeholder interpolation, consistent with the
existing Common.migration_needed pattern.
- header.php passes ['OSPOS', application_version] as the lang() array
argument instead of concatenating values around the translation
- All 46 Common.php locale files convert powered_by to a named-placeholder
template, preserving current rendered output while allowing each locale
to reorder the app name and version as needed
- hy, ml, nb, and ur leave powered_by empty so MY_Language::getLine()
falls back to English rather than rendering bare placeholder strings
- de-CH powered_by translated to German
- Codify named-placeholder + ICU MessageFormat as the localization standard
in the agents documentation
Refactor Stock_location model to camelCase naming and introduce
is_default and sort_order fields with full migration, UI, and
item-sync support. Multiple follow-up fixes consolidated.
Database
- Add is_default (TINYINT, backfilled to oldest non-deleted row) and
sort_order (nullable unsigned TINYINT unique, dense 0..N-1) columns
via new migration; MySQL 5.7-compatible backfill using user variables
instead of ROW_NUMBER(); down() drops both columns
Model
- Rename show_locations → showLocations (camelCase convention)
- Add getDefaultLocationId(), setDefaultLocation(), saveSortOrder();
validate location existence before setting as default
- delete() compacts sort_order via two-pass CASE update to avoid
collisions after prior reorders
- Atomic sort_order assignment via explicit SQL COUNT query
Controller / Config
- Modularize save logic into sanitizeSubmittedLocations(),
deleteRemovedLocations(), saveSubmittedLocations(),
saveLocationOrderAndDefault(); wrap in single transaction
- Support stock_location_new inputs for new-row creation
- Resolve new-* ID placeholders to real IDs post-save
- Abort loop on save failure; default missing POST arrays to []
- Validate that at least one location array is non-empty
Views
- Add Default column with center-aligned radio buttons; disable for
unsaved rows; use attr() instead of data() for location IDs
- Escape dynamic location IDs against XSS in all affected partials
- form_count_details.php: fall back to default location when current
is undefined; guard quantity input similarly
- Add aria-label to default radio inputs
Libraries / Items
- Widen Item_lib::get_item_location() and get_stock_destination() to
nullable return types
- Guard null location_id in Items::getRow() and getGenerateBarcodes()
- Item::get_multiple_info(): accept ?int $location_id; short-circuit
with where('item_id', -1) instead of always-false where('1','0')
i18n
- Add stock_location_default, stock_location_default_header,
stock_location_name_header across all locale files
Tests
- Stock_locationTest: getDefaultLocationId, setDefaultLocation,
saveSortOrder, delete compaction, saveValue; rename to
testMethod_Scenario convention
- Add ConfigControllerTest / StockLocationsControllerTest with
AdminAuthTrait covering CRUD, reorder, default assignment, and
malformed/empty/blank payload validation
- DatabaseBootstrapTrait-based setup for ItemTest and Stock_locationTest
Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(cashups,items): sync date globals from picker on Apply
Address CodeRabbit review on #4731: when a page loads with restored GET
dates the globals are overwritten after the picker initializes, so applying
an unchanged range (which skips the picker change callback) refreshed the
table with the stale globals instead of the visible range. Add a shared
apply.daterangepicker handler in the daterangepicker partial that copies the
picker range into start_date/end_date; it binds before page-level handlers
so refreshes and URL updates use the visible range.
* style(views): remove redundant comments in daterangepicker
* fix(tabs): resolve inner tab active switching, adjust padding, and correct tab title showing 'system_conf' instead of 'system_info'
* fix(views): enhance config forms with multi-breakpoint responsive grids for better readability and usability on smaller screens
* refactor(shortcuts): remove redundant container wrappers and optimize grid column widths for proper spacing
* refactor(system-info): replace min-height hacks with form-horizontal rows, adopt utility classes, and fix timezone check
* style: replace hardcoded red with 'text-danger' on required labels for proper Bootswatch theme integration
* chore: update dev dependency
* fix(auth): return 401 JSON for AJAX requests on session timeout (#4696)
IsLoggedIn previously threw RedirectException('login') for every request
type. For XHR calls the browser transparently followed the 302 and fetched
the login page's HTML where JSON was expected, so the table silently
rendered empty and the failure looked like a broken sort.
- Server: IsLoggedIn::before() now returns a JSON 401 response when the
request is an AJAX call, keeping the redirect behavior for normal
navigations.
- Client: a global $(document).ajaxError handler in the authenticated
layout redirects to the login URL on a 401 response.
* fix(auth): run isLoggedIn before csrf for expired sessions (#4696)
An expired-session AJAX POST with an invalid CSRF token was hitting the
globally-configured csrf filter first, which throws a CSRF exception before
isLoggedIn can return its 401. Reorder the global before-filters so the
authentication check runs before CSRF validation; CSRF protection is fully
retained for authenticated requests.
---------
Co-authored-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
* refactor: Replace var with let/const in JavaScript files
- Replace var with let for variables that are reassigned
- Replace var with const for variables that are never reassigned
- Modernize manage_tables.js and nominatim.autocomplete.js
- Skip third-party libraries (imgpreview.full.jquery.js, clipboard.min.js)
Closes#4491
* refactor: Replace var with let/const in inline JavaScript
- Fixed CodeRabbit review: changed enable_actions and load_success
from const to let in manage_tables.js (they are reassigned in init)
- Replaced all var declarations in inline JavaScript in Views with
let (for reassigned) or const (for never reassigned)
- Modernized 48 additional files with inline JavaScript
* refactor: Replace var with let/const in remaining JS files
- Modernized gulpfile.js: 3 var declarations replaced
- Modernized app/Views/errors/html/debug.js: all var declarations replaced
- Used const for never-reassigned, let for reassigned variables
* fix: Replace remaining var declarations in Views
- Changed var to const in sales/register.php
- Changed var to const in configs/receipt_config.php
These were missed in the initial pass.
* fix: Replace remaining var declarations in gulpfile.js
- Converted 12 remaining var declarations to const
- All variables are function-scoped and never reassigned
- Complete coverage for this file now
* fix: Address CodeRabbit review comments
- items/manage.php: Remove duplicate let declaration for start_date
(partial/daterangepicker already declares it)
- header_js.php: Escape CSRF hash in JavaScript context
- tax_jurisdictions.php: Fix mismatched selector (remove_tax_jurisdictions
-> remove_tax_jurisdiction)
* style(views): Replace var with let/const and fix comment casing
- Convert var to let in items/manage.php for JS modernization
- Capitalize \"Submit\" in validation comments across tax view files
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
---------
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
Co-authored-by: Ollama <ollama@steganos.dev>
Co-authored-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
Co-authored-by: Travis Garrison <travis@chiraqbookstore.com>
- reinstated 'update-licenses' task in gulp (accidentally removed in 3e844f2f89)
- updated bootstrap, bootswatch, and various dev dependencies
- refinded text across UI
- applied consistency fixes
- added 'number' and 'tel' input types to relevant settings
- improved system info layout (still room for improvement, but better)
- updated and fixed changelog
- Merge Config and Core File Changes 4.6.3 > 4.6.4
- Merge Config and Core File Changes 4.6.4 > 4.7.0
- Added app\Config\WorkerMode.php
- Merge Config and Core File Changes Not previously merged
- Added app\Config\Hostnames.php
- Corrected incorrect CSS property used in invoice.php view.
- Corrected unknown CSS properties used in register.php view.
- Used shorthand CSS in debug.css
- Corrected indentation in barcode_sheet.php view.
- Corrected indentation in footer.php view.
- Corrected indentation in invoice_email.php view.
- Replaced obsolete attributes with CSS style attributes in barcode_sheet.php
- Replaced obsolete attribute in error_exception.php
- Replaced obsolete attribute in invoice_email.php
- Replaced obsolete attribute in quote_email.php
- Replaced obsolete attributes in work_order_email.php
- Fixed indentation in system_info.php
- Replaced <strong> tag outside <p> tags, which isn't allowed, with style attributes.
- Simplified js return logic and indentation fixes in tax_categories.php
- Simplified js return logic in tax_codes.php
- Simplified js return logic in tax_jurisdictions.php
- Removed unnecessary labels in manage views.
- Rewrite JavaScript function and PHP to be more readable in bar.php, hbar.php, line.php and pie.php
- Added type declarations, return types and an import to app\Config\Services
- Updated Attribute.php parameter type
- Updated Receiving_lib.php parameter type
- Updated Receivings.php parameter types and updated PHPdocs
- Updated tabular_helper.php parameter types and updated PHPdocs
- Added type declarations and corrected PHPdocs in url_helper.php
- Added return types to functions
- Revert $objectSrc value in ContentSecurityPolicy.php
- Correct return type in Customer->get_stats()
- Correct return type in Item->get_info_by_id_or_number()
- Correct misspelling in border-spacing
- Added missing css style semicolons
- Resolve operator precedence ambiguity.
- Resolve column mismatch.
- Added missing escaping in view.
- Updated requirement for PHP 8.2
- Resolve unresolved conflicts
- Added PHP 8.2 requirement to the README.md
- Fixed bugs in display of UI
- Fixed duplicated `>` in app\Views\Expenses\manage.php
- Removed excess whitespace at the end of some lines in table_filter_persistence.php
- Added missing `>` in app\Views\Expenses\manage.php
- Corrected grammar in PHPdoc in table_filter_persistence.php
- Remove bug causing `\` to be injected into the new giftcard value
- Fix bug causing DROPDOWN Attribute Values to not save correctly
- Added check for null in $normalizedItemId
- Removing < PHP 8.2 from linting and tests
- Update Linter to not include PHP 8.2 and 8.1
- Remove PHP 8.1 unit test cycle.
- Update Bug Report Template
- Update Composer files for CodeIgniter 4.7.2
- Updated INSTALL.md to reflect changes.
---------
Signed-off-by: objec <objecttothis@gmail.com>
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>
* 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>
* 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
* Convert menu icons to SVG
- replaced png images with svg
- 20% decrease in file size, improving load times
- removed 384 unused files from repo
* Transferred package to organisation
Random fixes in time for the 3.4.0 release.
- corrects typo in the items controller
- small update to login view
- removes deprecated code from header view
- ospos license updated to end 2024
- moved gulp packages to dev dependencies
- updated gulp-zip and npm-check-updates to latest version
- updated readme for consistency
- makes ospos license in config fully readable
- fixes composer libraries license view in config
- gulp now updates composer libraries license and ospos license
- updated other license views in config
- Replaced == with === to avoid type juggling
- Removed unneeded TODO
- Added HTMLPurifier to composer.json
- Added Service to allow singleton instance of purifier.
- Implemented use in Customer Controller Search function.
Signed-off-by: objecttothis <objecttothis@gmail.com>
- 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>
- Made view CI form helper function call format uniform.
- replaced calls to array() with []
- Placed { on its own line
- Removed empty lines where there shouldn't be any.
- Replaced text/javascript with application/javascript as the former is deprecated
- Updated datepicker_locale.php to prevent array/string conversion.
- changed bootstrap-datepicker_locale version in package.json to specify which version.
- Changed bootstrap-table back to latest since the github commit did not resolve the issue.
- Removed XLSX export format due to errors.
- Upgraded Fakerphp to try to resolve datepicker issues.
- Attempted to fix datepicker language issues.
- Removed duplicate Sunday in the picker.
- Replaced TRUE/FALSE constants with true/false keywords
- Replaced NULL constant with null keyword
- Replaced `<?php echo` in views with shortened `<?=`
- Added missing variable declaration
- Added missing function return type in declaration
- replaced `== true`, `== false`, `=== true` and `=== false` in if statements with simplified forms
- PHP 8.2 deprecates dynamically declared class properties. Adding these declarations removes deprecation warnings and makes the code PHP 8.3 compatible.
- Add Elvis operator to set search string to an empty string when it's value is null to get rid of an error in the search function call.
- Imported class for OSPOS config
- Replaced private with protected in parent controller's property.
- Removed unneeded TODO
- Refactored local variables
- Replaced ternary notation
- Removed unneeded comments
- Removed unneeded class property
- Removed unneeded @property declarations
- Fixed database version
- when the payments array was folded into sale_data there was an earlier payments[] reference in the foreach loop that didn't get folded in.
- Update PHPdoc
- Added ::class to remove polymorphic call warning
- Removed unreachable 'break;' statement after return statement.
- Added missing return type
- fixed missing assignment of mailchimp_api_key
- Bump composer.json/lock to codeigniter 4.4.3
- Fix base_url() call without arguments
- Updated files in the project space
- Bump composer.json/lock to kint 5.0.4
- Update composer.json to include missing CI elements
- Corrected composer.json regarding minimum versions
- Updated README.md to reflect CI4 implementation
- Migrated some Routes.php to Routing.php
- Removed deprecated settings from Config/App.php
* CI4: Bugfix string interpolation language files
These are the language files with all placeholders converted to CI4 numbered style eg {0}.
* CI4: Bugfix string interpolation source code files
These are the controllers and views which call lang() with parameters to be interpolated.
* CI4: Bugfix string interpolation shell scripts
These are the Linux bash scripts which use the sed (stream editor) utility to convert earlier forms of placeholders to CI4 numeric type. A number of typographical errors in the original Language files were corrected by these scripts.
* Initial setup in a new environment
The result of running the npm build and editing the .env file
* Revert "Initial setup in a new environment"
This reverts commit 23e06dea7f.
* Language interpolation update
I have edited all the interpolations in the en-US tree. To be consistent in using named parameters and not just positional numbers, I also edited the relevant lines in two controllers (Sales.php and Items.php) to send named variables to the lang() calls. The language string 'Sales.invoice_number_duplicate' contains an interploation for 'invoice_number'. This is sent when used by Controllers/Sales.php, but not sent when used by Views/sales/form.php, which means that string will contain a double space where the invoice number should be. The language string 'Customers.csv_import_partially_failed' contains no interpolations but two parameters are not being sent where it is used by Controllers/Customers.php. The string appears to be a near duplicate of 'Items.csv_import_partially_failed' which contains two interpolations. Either the Customers controller needs to be edited, or the Customers language string needs to be revised to look like the Items string.
---------
Co-authored-by: objecttothis <17935339+objecttothis@users.noreply.github.com>