* Add `reference_code` to sale payment queries and group by statements
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* Refactor `Sales` controller to improve payment handling readability and replace snake_case with camelCase variables
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* Add missing translations for `Sales` language file and include new keys like `must_enter_rrn` and `reference_code`
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* Refactor `Sales` payment handling to use camelCase and extend `addPayment` with `referenceCode` support
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* Refactor `Sales` models, controllers, and libraries to adopt camelCase naming conventions and improve readability
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* Add translations and updates for `must_enter_reference_code` and `reference_code` across language files and update `Sales` controller to replace `must_enter_rrn` with the new key
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* feat(sales): add reference code input and payment type helper
- Add `get_reference_code_payment_types()` to locale_helper as single
source of truth for card-requiring payment types
- Add reference code row to register view, shown/hidden via JS based
on selected payment type
- Fix payment type dropdown width to 100% for consistent layout
- Add min-width to payment buttons and right-padding to button group
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* feat(config): add payment reference code length configuration
- Add payment_reference_code_min and payment_reference_code_max fields
to Config controller save logic
- Add translation keys for reference code length limits across all
language files (min/max label + section header)
- Align array key formatting in Config controller for readability
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* style(lang): normalize string delimiters to single quotes across all language files
Convert double-quoted array keys and values to single quotes in all
app/Language/*/Config.php and app/Language/*/Sales.php variants.
No translation content changed — formatting only.
Also add Localization section to AGENTS.md documenting language file
conventions for new keys and fallback behavior.
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* feat(lang): add payment reference code length translations
Add localized strings for payment_reference_code_length_limits,
payment_reference_code_length_max_label, and
payment_reference_code_length_min_label across all supported locales.
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* test(config,sales): add payment reference code min/max validation tests
- Add baseLocalePayload() helper in ConfigTest for postSaveLocale tests
- Add testSaveLocale_AcceptsValidReferenceCodeMinMax and related boundary tests
- Add Sale_libPaymentTest for payment reference code validation in Sale_lib
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* fix(sales): add type-specific validation for amount_tendered
Gift card payments use amount_tendered as giftcard number (integer);
cash/other payments require decimal_locale format. Apply correct
validation rule per payment type instead of generic required.
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* fix(lang): replace self-closing </br> with <br> in all locales
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* fix(sales): use configurable precision in discount comparison
Replace hardcoded precision 2 with totals_decimals() when comparing
discount against item total via bccomp/bcmul, so discount validation
respects the configured decimal precision setting.
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* fix(lang): correct Azerbaijani translations in Config.php
Replace placeholder/mismatched strings with accurate translations:
- email_mailpath, email_smtp_pass, invoice_email_message
- number_locale_invalid/required, receipt_template
- reward_configuration, right, tax_decimals, theme
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* feat(sales): add reference code support to payment edit flow
- Add reference_code field to new payment row in sale edit form
- Persist reference_code on insert in Sale model
- Validate reference_code_new in Sales controller using configurable min/max length rules
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* feat(lang): add Georgian (ka) language stubs for Config and Sales
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* Match the fallback maximum reference_code length to the maximum of the field in the db
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
* Bug fixes
- Add validation of UI settings to prevent overridden values from being passed.
- Correct maximum value in JS for payment_reference_code maximum length to 40.
- Fix bug causing copy_entire_sale() to incorrectly copy the reference code and cash_adjustment
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
---------
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
Co-authored-by: Travis Garrison <travis@chiraqbookstore.com>
- Add `$pluginData` parameter to `Events::trigger` calls for key events (e.g., `sale_completed`, `customer_saved`)
- Update core views to include `data-plugin-form` attribute for plugin-field serialization
- Bundle `plugin_data_helper.js` to handle form field extraction for plugins
- Extend README.md with comprehensive documentation on using `$pluginData`
- Refactor language files to support `install` translations and streamline UI labels
- Add new view hooks for sales receipt and register UI extension
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
- Intercept uninstall action to show confirmation modal before AJAX call
- Change uninstall to soft-delete: set installed=0 instead of purging all config
- Add deleteAllNonControlForPlugin to preserve control rows on uninstall
- Add isPluginInstalled helper to PluginManager for installed state checks
- Fix isInstalled guard to treat installed=0 as not installed
Signed-off-by: Travis Garrison <travis@chiraqbookstore.com>
- Remove unneeded keys from Config.php
- Remove unneeded lang() function override from BasePlugin.php
- Update README.md to reflect changes to language loading
- Correct language file string
- Correct lang() function calls to remove `$this->` from the call since we aren't overriding it anymore.
- Add code to correctly register namespace so that languages load.
- Fix plugin view render bug
Signed-off-by: objec <objecttothis@gmail.com>
- Refactor Plugins.php language keys
- Correct spacing between key and `=>`
- Replaced `"` with `'` to avoid calling the PHP string parser
- Propagated Plugins.php language string file to other languages
- removed redundant `plugin_` from key names
Signed-off-by: objec <objecttothis@gmail.com>
- Moved Language strings over to the plugin directory
- Removed them from the original language files (Config.php, Customers.php, Sales.php)
- Added translations for missing languages related to MailchimpPlugin.php
Signed-off-by: objec <objecttothis@gmail.com>
Add validation for the mailpath POST parameter to prevent command injection
attacks. The path is validated to only allow alphanumeric characters,
underscores, dashes, forward slashes, and dots.
- Required mailpath when protocol is "sendmail"
- Validates format for all non-empty mailpath values
- Blocks common injection vectors: ; | & ` $() spaces newlines
- Added mailpath_invalid translation to all 43 language files
- Simplified validation logic to avoid redundant conditions
Files changed:
- app/Controllers/Config.php: Add regex validation with protocol check
- app/Language/*/Config.php: Add mailpath_invalid error message (43 languages)
- tests/Controllers/ConfigTest.php: Unit tests for validation
* Fix business logic vulnerability allowing negative sale totals (GHSA-wv3j-pp8r-7q43)
Add server-side validation in postEditItem() to reject negative prices,
quantities, and discounts, as well as percentage discounts exceeding 100%
and fixed discounts exceeding the item total. Also block sale completion
with negative totals in non-return mode to prevent fraud/theft.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix: exempt return mode from negative quantity validation
Return mode legitimately stores items with negative quantities.
The quantity validation now skips the non-negative check in return mode,
consistent with the existing return mode exemption in postComplete().
Also use abs() for fixed discount comparison to handle return quantities.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Refactor: use $rules + validate() pattern per review feedback
Address review comments from jekkos on PR #4450:
1. Use CI4 $rules variable with custom non_negative_decimal validation
rule instead of manual if-checks for price/discount validation.
2. Add validation error strings to all 44 non-English language files
(English fallback values used until translations are contributed).
3. Use validate() method with $messages array for localized error
display, maintaining the existing controller pattern.
Additional improvements:
- Add non_negative_decimal rule to OSPOSRules.php (leverages
parse_decimals() for locale-aware decimal parsing)
- Preserve manual checks for business logic (return mode quantity
exemption, discount bounds via bccomp)
- Fix PHP 8.1+ compatibility: avoid passing method return to reset()
- Explicit empty discount handling for bc-math safety
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* Fix: rename to nonNegativeDecimal (PSR), clear non-English translation strings
- Rename validation rule method non_negative_decimal → nonNegativeDecimal in
OSPOSRules.php and all $rules/$messages references in Sales.php (PSR naming
per @objecttothis review)
- Replace English fallback text with "" in 43 non-English language files so
CI4 falls back to the base language string; weblate will handle translations
(per @jekkos and @objecttothis agreement)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Paul <morimori-dev@github.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
- Use 'Bénéfice' in French Reports.php for consistency with 'profit' key
- Fix Italian grammar: 'Il numero di telefono è richiesto'
- Use 'Responsabile' for 'manager' in Italian Common.php
- Add 'sale_not_found' translation key to missing languages (km, ml, ta, ur)
- Tamil (ta) gets proper translation, others get English fallback
- Add Calendar.php translation file for es-ES, nl-NL, de-DE
- Fill empty string translations in Common.php for de-DE, nl-NL, fr, it, pt-BR
- Translate UBL invoice strings (ubl_invoice, download_ubl, ubl_generation_failed) in Sales.php
- Add toggle_cost_and_profit in Reports.php for all languages
- Translate error_deleting_admin and error_updating_admin in Employees.php
- Translate csv_import_invalid_location error message in Items.php
- Update various missing translations for administrator, clerk, manager, dashboard, etc.
Languages updated: Spanish (es-ES), Dutch (nl-NL), German (de-DE), French (fr), Italian (it), Portuguese (pt-BR)
* Fix stored XSS vulnerability in Attribute Definitions
GHSA-rvfg-ww4r-rwqf: Stored XSS via Attribute Definition Name
Security Impact:
- Authenticated users with attribute management permission can inject XSS payloads
- Payloads execute when viewing/editing attributes in admin panel
- Can steal session cookies, perform CSRF attacks, or compromise admin operations
Root Cause:
1. Input: Attributes.php postSaveDefinition() accepts definition_name without sanitization
2. Output: Views echo definition_name without proper escaping
Fix Applied:
- Input sanitization: Added FILTER_SANITIZE_FULL_SPECIAL_CHARS to definition_name and definition_unit
- Output escaping: Added esc() wrapper when displaying definition_name in views
- Defense-in-depth: htmlspecialchars on attribute values saved to database
Files Changed:
- app/Controllers/Attributes.php - Sanitize inputs on save
- app/Views/attributes/form.php - Escape output on display
- app/Views/attributes/item.php - Escape output on display
* Remove input sanitization, keep output escaping only
Use escaping on output (esc() in views) as the sole XSS prevention
measure instead of sanitizing on input. This preserves the original
data in the database while still protecting against XSS attacks.
* Add validation for definition_fk foreign key in attribute definitions
Validate definition_group input before saving:
- Must be a positive integer (> 0)
- Must exist in attribute_definitions table
- Must be of type GROUP to ensure data integrity
Also add translation for definition_invalid_group error message
in all 45 language files (English placeholder for translations).
* Refactor definition_fk validation into single conditional statement
* Add esc() to attribute value outputs for XSS protection
- Add esc() to TEXT input value in item.php
- Add esc() to definition_unit in form.php
These fields display user-provided content and need output escaping
to prevent stored XSS attacks.
* Refactor definition_group validation into separate method
Extract validation logic for definition_fk into validateDefinitionGroup()
private method to improve code readability and reduce method complexity.
Returns:
- null if input is empty (no group selected)
- false if validation fails (invalid group)
- integer ID if valid
* Add translations for definition_invalid_group in all languages
- Added proper translations for 28 languages (de, es, fr, it, nl, pl, pt-BR, ru, tr, uk, th, zh-Hans, zh-Hant, ro, sv, vi, id, el, he, fa, hu, da, sw-KE, sw-TZ, ar-LB, ar-EG)
- Set empty string for 14 languages to fallback to English (cs, hr-HR, bg, bs, ckb, hy, km, lo, ml, nb, ta, tl, ur, az)
---------
Co-authored-by: Ollama <ollama@steganos.dev>
- Add csv_import_invalid_location to Items.php for CSV import validation
- Add error_deleting_admin and error_updating_admin to Employees.php for admin protection messages
Strings added with empty values so they fallback to English and show as untranslated in Weblate.
* 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