Compare commits

..

23 Commits

Author SHA1 Message Date
BudsieBuds
394883c813 Bootstrap 5 WIP
- work in progress build of conversion from bootstrap 3 to 5
2026-05-14 22:36:14 +02:00
BudsieBuds
d29f402e50 Bye Glyphicons
- replaced glyphicons with bootstrap-icons
2026-05-14 22:35:40 +02:00
jekkos
70fb347fc4 fix(docker): correct permissions and fix migration barcode_type error (#4546)
* fix(ci): include hidden files in Docker build context

actions/upload-artifact@v4 excludes hidden files (dotfiles) by default,
causing .htaccess files to be missing from the Docker image. Add
include-hidden-files: true to preserve .htaccess in the build artifact.

* fix(docker): correct permissions and add barcode_type default

- Set proper permissions (750) for writable/logs, writable/uploads,
  writable/cache, public/uploads, and public/uploads/item_pics
- Set permissions (640) for writable/uploads/importCustomers.csv
- Add barcode_type default value to prevent 'unknown key' error
  during initial migration when database is not yet initialized

---------

Co-authored-by: Ollama <ollama@steganos.dev>
Co-authored-by: objecttothis <17935339+objecttothis@users.noreply.github.com>
2026-05-13 20:55:59 +02:00
jekkos
2f5c0130f4 feat: add ALLOWED_HOSTNAMES environment variable support for Docker/Compose (#4544)
Allow configuring allowed hostnames via ALLOWED_HOSTNAMES environment
variable as an alternative to app.allowedHostnames in .env file. This
is more convenient for Docker/Compose deployments where environment
variables are set directly in compose files.

The ALLOWED_HOSTNAMES variable takes precedence over app.allowedHostnames
if both are set, allowing deployment-specific overrides.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Ollama <ollama@steganos.dev>
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-13 09:03:32 +02:00
jekkos
fdd6a408ec fix(ci): include hidden files in Docker build context (#4543)
actions/upload-artifact@v4 excludes hidden files (dotfiles) by default,
causing .htaccess files to be missing from the Docker image. Add
include-hidden-files: true to preserve .htaccess in the build artifact.

Co-authored-by: Ollama <ollama@steganos.dev>
2026-05-13 07:06:23 +02:00
BudsieBuds
ef91e6a9df chore: sync project files to match upstream templates (#4537)
- updated some files to match the official CodeIgniter 4 skeleton.
- rebuilt package.json from a clean init and modernized metadata and formatting
- rebuilt composer.json with modernized metadata and formatting
- replaced code of conduct text with markdown
- updated Dockerfile to replace deprecated instruction
2026-05-12 15:55:36 +02:00
dependabot[bot]
144e73eba6 chore(deps): bump minimatch from 3.1.2 to 3.1.5 (#4536)
Bumps [minimatch](https://github.com/isaacs/minimatch) from 3.1.2 to 3.1.5.
- [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/minimatch/compare/v3.1.2...v3.1.5)

---
updated-dependencies:
- dependency-name: minimatch
  dependency-version: 3.1.5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-08 16:49:39 +04:00
BudsieBuds
42ba39d290 chore: miscellaneous updates and improvements (#4530)
- 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
2026-05-08 09:07:52 +02:00
WShells
81213f0434 Assignable Keyboard Shortcuts Updates (#4532)
* Add configurable sales shortcuts

* Fix sales shortcut payment flow

* Resolve shortcut keys review comment

* Sanitize shortcut config notifications

* Clarify keyboard shortcut configuration labels

---------

Co-authored-by: WShells <26513147+WShells@users.noreply.github.com>
2026-05-07 22:53:25 +04:00
khao_lek
7edefe8ee1 Translated using Weblate (Thai)
Currently translated at 100.0% (15 of 15 strings)

Translation: opensourcepos/login
Translate-URL: https://translate.opensourcepos.org/projects/opensourcepos/login/th/
2026-04-28 10:06:38 +02:00
khao_lek
68e14191f9 Translated using Weblate (Thai)
Currently translated at 100.0% (8 of 8 strings)

Translation: opensourcepos/bootstrap_tables
Translate-URL: https://translate.opensourcepos.org/projects/opensourcepos/bootstrap_tables/th/
2026-04-28 10:05:06 +02:00
khao_lek
a381c3ca54 Translated using Weblate (Thai)
Currently translated at 99.5% (227 of 228 strings)

Translation: opensourcepos/sales
Translate-URL: https://translate.opensourcepos.org/projects/opensourcepos/sales/th/
2026-04-28 10:05:06 +02:00
enricodelarosa
058e12244e fix(home): improve internal data type handling for user identification in auth process 2026-04-28 09:56:56 +02:00
jekkos
f1c6fe2981 fix: Catch mysqli_sql_exception in DB fallback handlers for fresh Docker installs (#4525)
* fix: Catch mysqli_sql_exception in DB fallback handlers for fresh Docker installs

On a fresh Docker install with an empty database, the ospos_sessions
table doesn't exist yet. The CSRF filter triggers session initialization
before the login/migration page can be reached.

The existing code in Session.php, OSPOS.php, and MY_Migration.php
catches DatabaseException, but the MySQLi driver throws
mysqli_sql_exception (which extends RuntimeException, not
DatabaseException) when the table doesn't exist. This causes an
unhandled exception resulting in HTTP 500.

Fix: Change all three catch blocks from  to
 so that mysqli_sql_exception and any other unexpected
database errors are caught, allowing the app to fall back gracefully:

- Session.php: Falls back to FileHandler so sessions work without DB
- OSPOS.php: Falls back to empty settings so config loads work
- MY_Migration.php: Falls back to version 0 / false so the migration
  check passes gracefully

This allows the login page with migration UI to be served on first
access, so the initial schema migration can run.

Fixes #4524
---------

Co-authored-by: Ollama <ollama@steganos.dev>
2026-04-22 21:13:52 +02:00
jekkos
ff7a8d2e88 fix: Update calendar translations (#4498)
- Fix typo 'mayl' to 'may' in Calendar.php for lo, ka, ml, nb locales
- Improve Spanish translation in Items.php for csv_import_invalid_location
- Add trailing newlines to Calendar.php files (ka, ml, nb, lo) per PSR-12

Co-authored-by: Ollama <ollama@steganos.dev>
2026-04-20 06:48:57 +00:00
jekkos
e602eddb47 fix: Scope orWhere clauses in Item::exists() and Item::get_item_id() (#4520)
In PR #4250 (commit 29c3c55), orWhere was added to match items by
either item_id or item_number, but the OR condition was not wrapped
in groupStart()/groupEnd(). This causes:

1. Wrong SQL semantics: generates
   WHERE item_id = ? OR item_number = ? AND deleted = 0
   instead of
   WHERE (item_id = ? OR item_number = ?) AND deleted = 0
   Due to AND binding tighter than OR, the deleted filter only applies
   to the item_number branch, allowing deleted items to match via item_id.

2. Performance: the unscoped OR causes MySQL to bypass the item_id
   primary key index and fall back to full table scans when item_number
   is a string column compared against a numeric parameter.

Both exists() and get_item_id() are fixed by wrapping the OR
conditions in groupStart()/groupEnd() for proper parenthesization.

Co-authored-by: Ollama <ollama@steganos.dev>
2026-04-20 06:22:42 +00:00
jekkos
0a313aa09d fix: Language dropdown not displaying saved language correctly (#4518)
Root cause: In commit 7f9321eca, the refactoring incorrectly used object
notation ($config->language_code) on an array instead of array notation
($config['language_code']).

The settings property in OSPOS config is an array, so:
- $config->language_code returns null (object access on array)
- $config['language_code'] returns the actual value

This caused both functions to always fall back to defaults, making the
language dropdown show incorrect values.

Fix: Change both functions to use array notation:
- Line 25: $config['language_code'] (returns saved language code)
- Line 46: $config['language'] (returns saved language name)

Also fixed the wrong DEFAULT_LANGUAGE_CODE fallback on line 46 - should be
DEFAULT_LANGUAGE since current_language() returns a name not a code.

Fixes #4517

Co-authored-by: Ollama <ollama@steganos.dev>
2026-04-19 22:06:11 +02:00
jekkos
12e3c7e31f fix: Add missing $img_tag variable in Sales::getSendPdf() (#4515)
* fix: Add missing $img_tag variable in Sales::getSendPdf()

The receipt_email.php view expects $img_tag but getSendPdf() wasn't passing it.
This caused 'Undefined variable $img_tag' error when sending receipt emails.

Closes #4514

* refactor: Extract img_tag building into helper method

Refactored duplicate img_tag building code into _build_img_tag helper method.
Both getSendPdf and getSendReceipt now use this shared method.

* refactor: Move logo-related methods to Email_lib

Moved buildLogoImgTag and getLogoMimeType methods to Email_lib library
where they logically belong alongside email-related functionality.

This removes duplicate code and centralizes email-related helpers.
Sales controller now uses email_lib->buildLogoImgTag() and
email_lib->getLogoMimeType() instead of private methods.

* fix: Address CodeRabbit review comments

- buildLogoImgTag now uses getLogoMimeType for actual MIME type instead of hardcoding image/png
- getLogoMimeType returns empty string instead of false for consistency
- Consolidated logo path/exists check logic between both methods

---------

Co-authored-by: Ollama <ollama@steganos.dev>
2026-04-17 21:02:45 +00:00
jekkos
de62e9f3bd Fix CRC currency reverting to EUR/LAK in locale config (#4511)
Root cause: In postCheckNumberLocale(), when number_locale differed from
save_number_locale (which happens during form typing/validation), the code
ignored user-provided currency values and always used locale defaults.

For example:
- User sets currency_code to "CRC" (Costa Rica Colon)
- checkNumberLocale is called with save_number_locale from hidden field
- If locale values don't match, original code overwrites with locale defaults
- This caused CRC to revert to the default currency for that locale (EUR, LAK, etc.)

Fix: Always respect user-provided currency_symbol and currency_code values
when they are non-empty, regardless of whether locale changed or not.

Fixes #4494

Co-authored-by: Ollama <ollama@steganos.dev>
2026-04-17 17:53:46 +00:00
jekkos
97ca738b2d fix: Escape dynamic output and fix CSS property in barcode_sheet.php (#4501)
- Add esc() for dynamic output in HTML attributes and URLs
- Cast numeric values to int for CSS properties
- Fix invalid 'borderspacing' CSS property to 'border-spacing'
- Add quotes around class attribute

Closes #4487

Co-authored-by: Ollama <ollama@steganos.dev>
2026-04-16 19:37:06 +00:00
jekkos
c714dd6f68 fix: propagate attribute definition failures in postSaveGeneral() (#4509)
- Wrap attribute definition and appconfig save in single transaction
- Capture return values from saveDefinition() and deleteDefinition()
- Only call batch_save() if attribute operation succeeds
- Combine success status with transStatus() for atomic result
- Prevents category_dropdown config persistence when attribute fails

Fixes #4461

Co-authored-by: Ollama <ollama@steganos.dev>
2026-04-16 19:14:50 +00:00
dependabot[bot]
b6f28da058 Bump dompurify from 3.3.2 to 3.4.0 (#4512)
Bumps [dompurify](https://github.com/cure53/DOMPurify) from 3.3.2 to 3.4.0.
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/3.3.2...3.4.0)

---
updated-dependencies:
- dependency-name: dompurify
  dependency-version: 3.4.0
  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-04-16 14:14:29 +04:00
objecttothis
165c3351eb Encourage users to star the project
Added a request to star the project for support.
2026-04-15 16:25:06 +04:00
149 changed files with 7192 additions and 7577 deletions

View File

@@ -16,6 +16,9 @@ CI_ENVIRONMENT = production
# Configure with comma-separated list of domains/subdomains:
# app.allowedHostnames = 'yourdomain.com,www.yourdomain.com'
#
# Or via environment variable (useful for Docker/Compose):
# ALLOWED_HOSTNAMES=yourdomain.com,www.yourdomain.com
#
# For local development:
# app.allowedHostnames = 'localhost'
#

View File

@@ -123,6 +123,7 @@ jobs:
.
!.git
!node_modules
include-hidden-files: true
retention-days: 1
docker:

View File

@@ -1,5 +1,4 @@
[unreleased]: https://github.com/opensourcepos/opensourcepos/compare/3.4.0...HEAD
[3.4.2]: https://github.com/opensourcepos/opensourcepos/compare/3.4.1...3.4.2
[unreleased]: https://github.com/opensourcepos/opensourcepos/compare/3.4.1...HEAD
[3.4.1]: https://github.com/opensourcepos/opensourcepos/compare/3.4.0...3.4.1
[3.4.0]: https://github.com/opensourcepos/opensourcepos/compare/3.3.9...3.4.0
[3.3.9]: https://github.com/opensourcepos/opensourcepos/compare/3.3.8...3.3.9
@@ -34,10 +33,36 @@ All notable changes to this project will be documented in this file.
## [Unreleased]
## [3.4.0] - 2025-02-06
## [3.4.1] - 2025-06-05
- Feature: PSR-12 Compliant Indentation by @objecttothis in ([#4196](https://github.com/opensourcepos/opensourcepos/pull/4196))
- Add .env to dist zip by @jekkos in ([#4199](https://github.com/opensourcepos/opensourcepos/pull/4199))
- Add CI4 coding standards linter ([#3708](https://github.com/opensourcepos/opensourcepos/issues/3708)) by @jekkos in ([#4198](https://github.com/opensourcepos/opensourcepos/pull/4198))
- Bump canvg from 3.0.10 to 3.0.11 by @dependabot in ([#4189](https://github.com/opensourcepos/opensourcepos/pull/4189))
- Bump jspdf and jspdf-autotable by @dependabot in ([#4190](https://github.com/opensourcepos/opensourcepos/pull/4190))
- Feature bump ci to 4.6.0 by @objecttothis in ([#4197](https://github.com/opensourcepos/opensourcepos/pull/4197))
- Add Kurdish language option to UI by @BudsieBuds in ([#4210](https://github.com/opensourcepos/opensourcepos/pull/4210))
- Convert language ku to ckb by @BudsieBuds in ([#4211](https://github.com/opensourcepos/opensourcepos/pull/4211))
- Fix PHP 8.4 errors by @BudsieBuds in ([#4215](https://github.com/opensourcepos/opensourcepos/pull/4215))
- Add default bootstrap to themes by @BudsieBuds in ([#4219](https://github.com/opensourcepos/opensourcepos/pull/4219))
- Update language names by @BudsieBuds in ([#4218](https://github.com/opensourcepos/opensourcepos/pull/4218))
- Update install docs by @BudsieBuds in ([#4217](https://github.com/opensourcepos/opensourcepos/pull/4217))
- Convert menu icons to SVG by @BudsieBuds in ([#4220](https://github.com/opensourcepos/opensourcepos/pull/4220))
- Enhance license handling by @BudsieBuds in ([#4223](https://github.com/opensourcepos/opensourcepos/pull/4223))
- Fix datetime rendering ([#4226](https://github.com/opensourcepos/opensourcepos/issues/4226)) by @jekkos in ([#4227](https://github.com/opensourcepos/opensourcepos/pull/4227))
- Fix datetime rendering by @jekkos in ([#4228](https://github.com/opensourcepos/opensourcepos/pull/4228))
- Fix null error when sending by email a receipt of a sale that has no invoice by @diego-ramos in ([#4229](https://github.com/opensourcepos/opensourcepos/pull/4229))
- Update Receivings.php to save form. by @odiea in ([#4231](https://github.com/opensourcepos/opensourcepos/pull/4231))
- Update Cashups.php for ajax cashup total to work. by @odiea in ([#4238](https://github.com/opensourcepos/opensourcepos/pull/4238))
- Coding style updates for PSR-12 compliance & improved readability by @BudsieBuds in ([#4204](https://github.com/opensourcepos/opensourcepos/pull/4204))
- Fix Codeigniter disallowed characters error with payment types that have accents by @diego-ramos in ([#4232](https://github.com/opensourcepos/opensourcepos/pull/4232))
- Fixed broken escape string for success & warning messages by @Franchovy in ([#4253](https://github.com/opensourcepos/opensourcepos/pull/4253))
- Bugfix constraint migration fix by @objecttothis in ([#4230](https://github.com/opensourcepos/opensourcepos/pull/4230))
- Fix item number lookup in sales/receivings ([#4212](https://github.com/opensourcepos/opensourcepos/issues/4212)) by @jekkos in ([#4250](https://github.com/opensourcepos/opensourcepos/pull/4250))
## [3.4.0] - 2025-03-23
- Translation updates (Spanish, Indonesian, Swedish, Urdu, Chinese, Thai, French, Dutch)
- PHP 8.x support
- PHP `8.x` support
- Security fixes (XSS, SQLi)
- Migration to Gulp as buildsystem
- Decimal validation fix

View File

@@ -1,98 +1,85 @@
Contributor Covenant Code of Conduct
Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, caste, color, religion, or sexual
identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
[comment]: # (Contributor Covenant 2.1 - from https://www.contributor-covenant.org/version/2/1/code_of_conduct/code_of_conduct.md)
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the overall
community
* Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
* Focusing on what is best not just for us as individuals, but for the overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or advances of
any kind
* The use of sexualized language or imagery, and sexual attention or advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others private information, such as a physical or email address,
without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
* Publishing others' private information, such as a physical or email address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official email address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
[INSERT CONTACT METHOD].
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
1. Correction
Community Impact: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
Consequence: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
2. Warning
Community Impact: A violation through a single incident or series of
actions.
Consequence: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or permanent
ban.
3. Temporary Ban
Community Impact: A serious violation of community standards, including
sustained inappropriate behavior.
Consequence: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
4. Permanent Ban
Community Impact: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
Consequence: A permanent ban from any sort of public interaction within the
community.
Attribution
This Code of Conduct is adapted from the Contributor Covenant,
version 2.1, available at
https://www.contributor-covenant.org/version/2/1/code_of_conduct.html.
Community Impact Guidelines were inspired by
Mozillas code of conduct enforcement ladder.
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at [INSERT CONTACT METHOD]. All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series of actions.
**Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1, available at [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
For answers to common questions about this code of conduct, see the FAQ at [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at [https://www.contributor-covenant.org/translations][translations].
[homepage]: https://www.contributor-covenant.org
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
[Mozilla CoC]: https://github.com/mozilla/diversity
[FAQ]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations

View File

@@ -13,7 +13,8 @@ RUN echo "date.timezone = \"\${PHP_TIMEZONE}\"" > /usr/local/etc/php/conf.d/time
WORKDIR /app
COPY --chown=www-data:www-data . /app
RUN chmod 770 /app/writable/uploads /app/writable/logs /app/writable/cache \
RUN chmod 750 /app/writable/logs /app/writable/uploads /app/writable/cache /app/public/uploads /app/public/uploads/item_pics \
&& chmod 640 /app/writable/uploads/importCustomers.csv \
&& ln -s /app/*[^public] /var/www \
&& rm -rf /var/www/html \
&& ln -nsf /app/public /var/www/html

View File

@@ -1,6 +1,10 @@
<p align="center"><img src="https://raw.githubusercontent.com/opensourcepos/opensourcepos/master/branding/emblem.svg" alt="Open Source Point of Sale Logo" width="auto" height="200"></p>
<h3 align="center">Open Source Point of Sale</h3>
## ☢️ Bootstrap 5 conversion WIP
This is a heavily under-construction build converting OSPOS from Bootstrap 3 to Bootstrap 5. Please do not use!
<p align="center">
<a href="#-introduction">Introduction</a> · <a href="#-live-demo">Demo</a> · <a href="#-installation">Installation</a> ·
<a href="#-contributing">Contributing</a> · <a href="#-reporting-bugs">Bugs</a> · <a href="#-faq">FAQ</a> ·
@@ -106,7 +110,7 @@ NOTE: If you're running non-release code, please make sure you always run the la
## 🏃 Keep the Machine Running
If you like our project, please consider buying us a coffee through the button below so we can keep adding features.
If you like our project, please consider buying us a coffee through the button below so we can keep adding features. Please star the project if you like it!
[![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=MUN6AEG7NY6H8)\
Or refer to the [FUNDING.yml](.github/FUNDING.yml) file.

View File

@@ -58,9 +58,9 @@ class App extends BaseConfig
* Allowed Hostnames in the Site URL other than the hostname in the baseURL.
* If you want to accept multiple Hostnames, set this.
*
* E.g.,
* When your site URL ($baseURL) is 'http://example.com/', and your site
* also accepts 'http://media.example.com/' and 'http://accounts.example.com/':
* Or via environment variable (useful for Docker/Compose):
* ALLOWED_HOSTNAMES=example.com,www.example.com
*
* ['media.example.com', 'accounts.example.com']
*
* @var list<string>
@@ -278,7 +278,7 @@ class App extends BaseConfig
* @see http://www.html5rocks.com/en/tutorials/security/content-security-policy/
* @see http://www.w3.org/TR/CSP/
*/
public bool $CSPEnabled = true;
public bool $CSPEnabled = false;
public function __construct()
{
@@ -286,7 +286,11 @@ class App extends BaseConfig
// Solution for CodeIgniter 4 limitation: arrays cannot be set from .env
// See: https://github.com/codeigniter4/CodeIgniter4/issues/7311
$envAllowedHostnames = getenv('app.allowedHostnames');
// Support both: app.allowedHostnames (from .env) and ALLOWED_HOSTNAMES (from environment/Docker)
$envAllowedHostnames = getenv('ALLOWED_HOSTNAMES');
if ($envAllowedHostnames === false || trim($envAllowedHostnames) === '') {
$envAllowedHostnames = getenv('app.allowedHostnames');
}
if ($envAllowedHostnames !== false && trim($envAllowedHostnames) !== '') {
$this->allowedHostnames = array_values(array_filter(
array_map('trim', explode(',', $envAllowedHostnames)),
@@ -327,7 +331,7 @@ class App extends BaseConfig
$errorMessage =
'Security: allowedHostnames is not configured. ' .
'Host header injection protection is disabled. ' .
'Set app.allowedHostnames in your .env file. ' .
'Set app.allowedHostnames in your .env file or ALLOWED_HOSTNAMES environment variable. ' .
'Example: app.allowedHostnames = "example.com,www.example.com" ' .
'Received Host: ' . $httpHost;

View File

@@ -486,10 +486,9 @@ class Mimes
/**
* Attempts to determine the best mime type for the given file extension.
*
* @param string $extension
* @return array|string|null The mime type found, or none if unable to determine.
* @return string|null The mime type found, or none if unable to determine.
*/
public static function guessTypeFromExtension(string $extension): array|string|null
public static function guessTypeFromExtension(string $extension)
{
$extension = trim(strtolower($extension), '. ');
@@ -507,7 +506,7 @@ class Mimes
*
* @return string|null The extension determined, or null if unable to match.
*/
public static function guessExtensionFromType(string $type, ?string $proposedExtension = null): ?string
public static function guessExtensionFromType(string $type, ?string $proposedExtension = null)
{
$type = trim(strtolower($type), '. ');
@@ -523,7 +522,7 @@ class Mimes
}
// Reverse check the mime type list if no extension was proposed.
// This search is order-sensitive!
// This search is order sensitive!
foreach (static::$mimes as $ext => $types) {
if (in_array($type, (array) $types, true)) {
return $ext;

View File

@@ -5,7 +5,6 @@ namespace Config;
use App\Models\Appconfig;
use CodeIgniter\Cache\CacheInterface;
use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Database\Exceptions\DatabaseException;
/**
* This class holds the configuration options stored from the database so that on launch those settings can be cached
@@ -41,13 +40,16 @@ class OSPOS extends BaseConfig
$this->settings[$app_config->key] = $app_config->value;
}
$this->cache->save('settings', encode_array($this->settings));
} catch (DatabaseException $e) {
} catch (\Exception $e) {
// Database table doesn't exist yet (migrations haven't run)
// Return empty settings to allow migration page to display
// or database connection failed. Return empty settings to
// allow migration page to display. Catches mysqli_sql_exception
// which is not a subclass of DatabaseException.
$this->settings = [
'language' => 'english',
'language_code' => 'en',
'company' => 'Home'
'company' => 'Home',
'barcode_type' => 'Code39'
];
}
}

View File

@@ -3,7 +3,6 @@
namespace Config;
use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Database\Exceptions\DatabaseException;
use CodeIgniter\Session\Handlers\BaseHandler;
use CodeIgniter\Session\Handlers\DatabaseHandler;
use CodeIgniter\Session\Handlers\FileHandler;
@@ -139,7 +138,11 @@ class Session extends BaseConfig
$this->driver = FileHandler::class;
$this->savePath = WRITEPATH . 'session';
}
} catch (DatabaseException $e) {
} catch (\Exception $e) {
// Database not available yet (e.g. fresh install before migrations).
// Fall back to file-based sessions so the login/migration page
// can still be served. Catches mysqli_sql_exception which is
// not a subclass of DatabaseException but is a RuntimeException.
$this->driver = FileHandler::class;
$this->savePath = WRITEPATH . 'session';
}

View File

@@ -28,12 +28,9 @@ abstract class BaseController extends Controller
// protected $session;
/**
* @param RequestInterface $request
* @param ResponseInterface $response
* @param LoggerInterface $logger
* @return void
*/
public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger): void
public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
{
// Load here all helpers you want to be available in your controllers that extend BaseController.
// Caution: Do not put the this below the parent::initController() call below.

View File

@@ -82,7 +82,7 @@ class Config extends Secure_Controller
$npmDev = false;
$license = [];
$license[$i]['title'] = 'Open Source Point Of Sale ' . config('App')->application_version;
$license[$i]['title'] = 'Open Source Point of Sale ' . config('App')->application_version;
if (file_exists('license/LICENSE')) {
$license[$i]['text'] = file_get_contents('license/LICENSE', false, null, 0, 3000);
@@ -221,6 +221,7 @@ class Config extends Secure_Controller
*/
public function getIndex(): string
{
$data['config'] = $this->config;
$data['stock_locations'] = $this->stock_location->get_all()->getResultArray();
$data['dinner_tables'] = $this->dinner_table->get_all()->getResultArray();
$data['customer_rewards'] = $this->customer_rewards->get_all()->getResultArray();
@@ -231,6 +232,8 @@ class Config extends Secure_Controller
$data['line_sequence_options'] = $this->sale_lib->get_line_sequence_options();
$data['register_mode_options'] = $this->sale_lib->get_register_mode_options();
$data['invoice_type_options'] = $this->sale_lib->get_invoice_type_options();
$data['keyboardShortcutOptions'] = $this->sale_lib->getKeyShortcutsOptions();
$data['keyboardShortcuts'] = $this->sale_lib->getKeyShortcuts();
$data['rounding_options'] = rounding_mode::get_rounding_options();
$data['tax_code_options'] = $this->tax_lib->get_tax_code_options();
$data['tax_category_options'] = $this->tax_lib->get_tax_category_options();
@@ -368,8 +371,6 @@ class Config extends Secure_Controller
public function postSaveGeneral(): ResponseInterface
{
$batchSaveData = [
'theme' => $this->request->getPost('theme'),
'login_form' => $this->request->getPost('login_form'),
'default_sales_discount_type' => $this->request->getPost('default_sales_discount_type') != null,
'default_sales_discount' => parse_decimals($this->request->getPost('default_sales_discount')),
'default_receivings_discount_type' => $this->request->getPost('default_receivings_discount_type') != null,
@@ -377,8 +378,6 @@ class Config extends Secure_Controller
'enforce_privacy' => $this->request->getPost('enforce_privacy') != null,
'receiving_calculate_average_price' => $this->request->getPost('receiving_calculate_average_price') != null,
'lines_per_page' => $this->request->getPost('lines_per_page', FILTER_SANITIZE_NUMBER_INT),
'notify_horizontal_position' => $this->request->getPost('notify_horizontal_position'),
'notify_vertical_position' => $this->request->getPost('notify_vertical_position'),
'image_max_width' => $this->request->getPost('image_max_width', FILTER_SANITIZE_NUMBER_INT),
'image_max_height' => $this->request->getPost('image_max_height', FILTER_SANITIZE_NUMBER_INT),
'image_max_size' => $this->request->getPost('image_max_size', FILTER_SANITIZE_NUMBER_INT),
@@ -398,6 +397,9 @@ class Config extends Secure_Controller
$this->module->set_show_office_group($this->request->getPost('show_office_group') != null);
$this->db->transStart();
$attributeSuccess = true;
if ($batchSaveData['category_dropdown']) {
$definitionData['definition_name'] = 'ospos_category';
$definitionData['definition_flags'] = 0;
@@ -405,12 +407,36 @@ class Config extends Secure_Controller
$definitionData['definition_id'] = CATEGORY_DEFINITION_ID;
$definitionData['deleted'] = 0;
$this->attribute->saveDefinition($definitionData, CATEGORY_DEFINITION_ID);
$attributeSuccess = $this->attribute->saveDefinition($definitionData, CATEGORY_DEFINITION_ID);
} elseif ($batchSaveData['category_dropdown'] == NO_DEFINITION_ID) {
$this->attribute->deleteDefinition(CATEGORY_DEFINITION_ID);
$attributeSuccess = $this->attribute->deleteDefinition(CATEGORY_DEFINITION_ID);
}
$success = $this->appconfig->batch_save($batchSaveData);
$success = $attributeSuccess && $this->appconfig->batch_save($batchSaveData);
$this->db->transComplete();
$success = $success && $this->db->transStatus();
return $this->response->setJSON(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
}
/**
* Saves Appearance configuration. Used in app/Views/configs/appearance_config.php
*/
public function postSaveAppearance(): ResponseInterface
{
$batch_save_data = [
'theme' => $this->request->getPost('theme'),
'login_form' => $this->request->getPost('login_form'),
'notify_horizontal_position' => $this->request->getPost('notify_horizontal_position'),
'notify_vertical_position' => $this->request->getPost('notify_vertical_position'),
'color_mode' => $this->request->getPost('color_mode'),
'config_menu_position' => $this->request->getPost('config_menu_position'),
'responsive_design' => $this->request->getPost('responsive_design') != null
];
$success = $this->appconfig->batch_save($batch_save_data);
return $this->response->setJSON(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
}
@@ -423,32 +449,35 @@ class Config extends Secure_Controller
*/
public function postCheckNumberLocale(): ResponseInterface
{
$number_locale = $this->request->getPost('number_locale');
$save_number_locale = $this->request->getPost('save_number_locale');
$numberLocale = $this->request->getPost('number_locale');
$saveNumberLocale = $this->request->getPost('save_number_locale');
$postedCurrencySymbol = $this->request->getPost('currency_symbol');
$postedCurrencyCode = $this->request->getPost('currency_code');
$fmt = new NumberFormatter($number_locale, NumberFormatter::CURRENCY);
if ($number_locale != $save_number_locale) {
$currency_symbol = $fmt->getSymbol(NumberFormatter::CURRENCY_SYMBOL);
$currency_code = $fmt->getTextAttribute(NumberFormatter::CURRENCY_CODE);
$save_number_locale = $number_locale;
} else {
$currency_symbol = empty($this->request->getPost('currency_symbol')) ? $fmt->getSymbol(NumberFormatter::CURRENCY_SYMBOL) : $this->request->getPost('currency_symbol');
$currency_code = empty($this->request->getPost('currency_code')) ? $fmt->getTextAttribute(NumberFormatter::CURRENCY_CODE) : $this->request->getPost('currency_code');
$fmt = new NumberFormatter($numberLocale, NumberFormatter::CURRENCY);
// Use posted values if provided, otherwise fall back to locale defaults
$currencySymbol = $postedCurrencySymbol !== '' ? $postedCurrencySymbol : $fmt->getSymbol(NumberFormatter::CURRENCY_SYMBOL);
$currencyCode = $postedCurrencyCode !== '' ? $postedCurrencyCode : $fmt->getTextAttribute(NumberFormatter::CURRENCY_CODE);
// Update saved locale if it changed
if ($numberLocale !== $saveNumberLocale) {
$saveNumberLocale = $numberLocale;
}
if ($this->request->getPost('thousands_separator') == 'false') {
$fmt->setTextAttribute(NumberFormatter::GROUPING_SEPARATOR_SYMBOL, '');
}
$fmt->setSymbol(NumberFormatter::CURRENCY_SYMBOL, $currency_symbol);
$number_local_example = $fmt->format(1234567890.12300);
$fmt->setSymbol(NumberFormatter::CURRENCY_SYMBOL, $currencySymbol);
$numberLocaleExample = $fmt->format(1234567890.12300);
return $this->response->setJSON([
'success' => $number_local_example != false,
'save_number_locale' => $save_number_locale,
'number_locale_example' => $number_local_example,
'currency_symbol' => $currency_symbol,
'currency_code' => $currency_code,
'success' => $numberLocaleExample != false,
'save_number_locale' => $saveNumberLocale,
'number_locale_example' => $numberLocaleExample,
'currency_symbol' => $currencySymbol,
'currency_code' => $currencyCode,
]);
}
@@ -468,6 +497,7 @@ class Config extends Secure_Controller
'currency_code' => $this->request->getPost('currency_code'),
'language_code' => $exploded[0],
'language' => $exploded[1],
'rtl_language' => $this->request->getPost('rtl_language') != null,
'timezone' => $this->request->getPost('timezone'),
'dateformat' => $this->request->getPost('dateformat'),
'timeformat' => $this->request->getPost('timeformat'),
@@ -936,6 +966,44 @@ class Config extends Secure_Controller
return $this->response->setJSON(['success' => $success, 'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')]);
}
/**
* Saves keyboard shortcut bindings.
*
* @return ResponseInterface
* @noinspection PhpUnused
*/
public function postSaveShortcuts(): ResponseInterface
{
$allowedShortcuts = array_keys($this->sale_lib->getKeyShortcutsOptions());
$currentShortcuts = $this->sale_lib->getKeyShortcuts();
$batchSaveData = [];
foreach ($currentShortcuts as $name => $shortcut) {
$postedValue = trim((string)$this->request->getPost('key_' . $name));
if (!in_array($postedValue, $allowedShortcuts, true)) {
$postedValue = $shortcut['value'];
}
$batchSaveData['key_' . $name] = $postedValue;
}
$duplicateValues = array_filter(array_count_values($batchSaveData), static fn(int $count): bool => $count > 1);
if (!empty($duplicateValues)) {
return $this->response->setJSON([
'success' => false,
'message' => lang('Config.shortcuts_duplicate_bindings')
]);
}
$success = $this->appconfig->batch_save($batchSaveData);
return $this->response->setJSON([
'success' => $success,
'message' => lang('Config.saved_' . ($success ? '' : 'un') . 'successfully')
]);
}
/**
* Saves invoice configuration. Used in app/Views/configs/invoice_config.php.
*

View File

@@ -43,7 +43,7 @@ class Home extends Secure_Controller
public function getChangePassword(int $employeeId = NEW_ENTRY): ResponseInterface|string
{
$loggedInEmployee = $this->employee->get_logged_in_employee_info();
$currentPersonId = $loggedInEmployee->person_id;
$currentPersonId = (int) $loggedInEmployee->person_id;
$employeeId = $employeeId === NEW_ENTRY ? $currentPersonId : $employeeId;
@@ -68,10 +68,11 @@ class Home extends Secure_Controller
public function postSave(int $employeeId = NEW_ENTRY): ResponseInterface
{
$currentUser = $this->employee->get_logged_in_employee_info();
$currentPersonId = (int) $currentUser->person_id;
$employeeId = $employeeId === NEW_ENTRY ? $currentUser->person_id : $employeeId;
$employeeId = $employeeId === NEW_ENTRY ? $currentPersonId : $employeeId;
if (!$this->employee->isAdmin($currentUser->person_id) && $employeeId !== $currentUser->person_id) {
if (!$this->employee->isAdmin($currentPersonId) && $employeeId !== $currentPersonId) {
return $this->response->setStatusCode(403)->setJSON([
'success' => false,
'message' => lang('Employees.unauthorized_modify')

View File

@@ -1308,9 +1308,9 @@ class Reports extends Secure_Controller
'comment' => $row['comment'],
'edit' => anchor(
'sales/edit/' . $row['sale_id'],
'<span class="glyphicon glyphicon-edit"></span>',
'<i class="bi bi-pencil-square"></i>',
[
'class' => 'modal-dlg print_hide',
'class' => 'modal-launch print_hide',
$button_key => $button_label,
'data-btn-submit' => lang('Common.submit'),
'title' => lang('Sales.update')
@@ -1435,9 +1435,9 @@ class Reports extends Secure_Controller
'comment' => $row['comment'],
'edit' => anchor(
'sales/edit/' . $row['sale_id'],
'<span class="glyphicon glyphicon-edit"></span>',
'<i class="bi bi-pencil-square"></i>',
[
'class' => 'modal-dlg print_hide',
'class' => 'modal-launch print_hide',
$button_key => $button_label,
'data-btn-submit' => lang('Common.submit'),
'title' => lang('Sales.update')
@@ -1567,9 +1567,9 @@ class Reports extends Secure_Controller
'comment' => $row['comment'],
'edit' => anchor(
'sales/edit/' . $row['sale_id'],
'<span class="glyphicon glyphicon-edit"></span>',
'<i class="bi bi-pencil-square"></i>',
[
'class' => 'modal-dlg print_hide',
'class' => 'modal-launch print_hide',
$button_key => $button_label,
'data-btn-submit' => lang('Common.submit'),
'title' => lang('Sales.update')
@@ -1655,9 +1655,9 @@ class Reports extends Secure_Controller
'comment' => $report_data['comment'],
'edit' => anchor(
'sales/edit/' . $report_data['sale_id'],
'<span class="glyphicon glyphicon-edit"></span>',
'<i class="bi bi-pencil-square"></i>',
[
'class' => 'modal-dlg print_hide',
'class' => 'modal-launch print_hide',
$button_key => $button_label,
'data-btn-submit' => lang('Common.submit'),
'title' => lang('Sales.update')
@@ -1831,9 +1831,9 @@ class Reports extends Secure_Controller
'comment' => $row['comment'],
'edit' => anchor(
'sales/edit/' . $row['sale_id'],
'<span class="glyphicon glyphicon-edit"></span>',
'<i class="bi bi-pencil-square"></i>',
[
'class' => 'modal-dlg print_hide',
'class' => 'modal-launch print_hide',
$button_key => $button_label,
'data-btn-submit' => lang('Common.submit'),
'title' => lang('Sales.update')
@@ -1911,9 +1911,9 @@ class Reports extends Secure_Controller
'comment' => $report_data['comment'],
'edit' => anchor(
'receivings/edit/' . $report_data['receiving_id'],
'<span class="glyphicon glyphicon-edit"></span>',
'<i class="bi bi-pencil-square"></i>',
[
'class' => 'modal-dlg print_hide',
'class' => 'modal-launch print_hide',
'data-btn-submit' => lang('Common.submit'),
'data-btn-delete' => lang('Common.delete'),
'title' => lang('Receivings.update')
@@ -1971,9 +1971,9 @@ class Reports extends Secure_Controller
'comment' => $row['comment'],
'edit' => anchor(
'receivings/edit/' . $row['receiving_id'],
'<span class="glyphicon glyphicon-edit"></span>',
'<i class="bi bi-pencil-square"></i>',
[
'class' => 'modal-dlg print_hide',
'class' => 'modal-launch print_hide',
'data-btn-delete' => lang('Common.delete'),
'data-btn-submit' => lang('Common.submit'),
'title' => lang('Receivings.update')

View File

@@ -937,7 +937,10 @@ class Sales extends Secure_Controller
new Token_customer((array)$sale_data)
];
$text = $this->token_lib->render($text, $tokens);
$sale_data['mimetype'] = mime_content_type(FCPATH . 'uploads/' . $this->config['company_logo']);
$sale_data['mimetype'] = $this->email_lib->getLogoMimeType();
// Build img_tag for email views that need it (receipt_email.php)
$sale_data['img_tag'] = $this->email_lib->buildLogoImgTag();
// Generate email attachment: invoice in PDF format
$view = Services::renderer();
@@ -974,13 +977,7 @@ class Sales extends Secure_Controller
if (!empty($sale_data['customer_email'])) {
$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">';
}
$sale_data['img_tag'] = $this->email_lib->buildLogoImgTag();
$to = $sale_data['customer_email'];
$subject = lang('Sales.receipt');
@@ -1256,6 +1253,7 @@ class Sales extends Secure_Controller
$data['quote_number'] = $this->sale_lib->get_quote_number();
$data['work_order_number'] = $this->sale_lib->get_work_order_number();
$data['keyboardShortcuts'] = $this->sale_lib->getKeyShortcuts();
// TODO: the if/else set below should be converted to a switch
if ($this->sale_lib->get_mode() == 'sale_invoice') { // TODO: Duplicated code.
@@ -1644,7 +1642,9 @@ class Sales extends Secure_Controller
*/
public function getSalesKeyboardHelp(): string
{
return view('sales/help');
return view('sales/help', [
'keyboardShortcuts' => $this->sale_lib->getKeyShortcuts()
]);
}
/**

View File

@@ -1,5 +1,5 @@
FROM alpine:3.14
MAINTAINER jekkos
LABEL maintainer="jekkos"
ADD database.sql /docker-entrypoint-initdb.d/database.sql
VOLUME /docker-entrypoint-initdb.d

View File

@@ -0,0 +1,46 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class AddShortcutKeys extends Migration
{
public function up(): void
{
$shortcutValues = [
['key' => 'key_cancel', 'value' => '27 | ESC'],
['key' => 'key_items', 'value' => '49 | ALT + 1'],
['key' => 'key_customers', 'value' => '50 | ALT + 2'],
['key' => 'key_suspend', 'value' => '51 | ALT + 3'],
['key' => 'key_suspended', 'value' => '52 | ALT + 4'],
['key' => 'key_amount', 'value' => '53 | ALT + 5'],
['key' => 'key_payment', 'value' => '54 | ALT + 6'],
['key' => 'key_complete', 'value' => '55 | ALT + 7'],
['key' => 'key_finish', 'value' => '56 | ALT + 8'],
['key' => 'key_help', 'value' => '57 | ALT + 9'],
];
$this->db->table('app_config')->ignore(true)->insertBatch($shortcutValues);
}
public function down(): void
{
$shortcutKeys = [
'key_cancel',
'key_items',
'key_customers',
'key_suspend',
'key_suspended',
'key_amount',
'key_payment',
'key_complete',
'key_finish',
'key_help',
];
$this->db->table('app_config')
->whereIn('key', $shortcutKeys)
->delete();
}
}

View File

@@ -79,10 +79,14 @@ INSERT INTO `ospos_app_config` (`key`, `value`) VALUES
('smtp_timeout', '5'),
('smtp_crypto', 'ssl'),
('receipt_template', 'receipt_default'),
('theme', 'flatly'),
('theme', 'bootstrap'),
('statistics', '1'),
('language', 'english'),
('language_code', 'en');
('language_code', 'en'),
('rtl_language', '0'),
('color_mode', 'light'),
('config_menu_position', 'start'),
('responsive_design', '1');
-- --------------------------------------------------------

View File

@@ -22,7 +22,7 @@ function current_language_code(bool $load_system_language = false): string
}
}
return $config->language_code ?? DEFAULT_LANGUAGE_CODE;
return $config['language_code'] ?? DEFAULT_LANGUAGE_CODE;
}
/**
@@ -43,7 +43,7 @@ function current_language(bool $load_system_language = false): string
}
}
return $config->language ?? DEFAULT_LANGUAGE_CODE;
return $config['language'] ?? DEFAULT_LANGUAGE;
}
/**

View File

@@ -118,21 +118,21 @@ function get_sale_data_row(object $sale): array
? '-'
: anchor(
"$controller/invoice/$sale->sale_id",
'<span class="glyphicon glyphicon-list-alt"></span>',
'<i class="bi bi-file-text"></i>',
['title' => lang('Sales.show_invoice')]
);
}
$row['receipt'] = anchor(
"$controller/receipt/$sale->sale_id",
'<span class="glyphicon glyphicon-usd"></span>',
'<i class="bi bi-receipt"></i>',
['title' => lang('Sales.show_receipt')]
);
$row['edit'] = anchor(
"$controller/edit/$sale->sale_id",
'<span class="glyphicon glyphicon-edit"></span>',
'<i class="bi bi-pencil-square"></i>',
[
'class' => 'modal-dlg print_hide',
'class' => 'modal-launch print_hide',
'data-btn-delete' => lang('Common.delete'),
'data-btn-submit' => lang('Common.submit'),
'title' => lang(ucfirst($controller) . ".update")
@@ -232,18 +232,18 @@ function get_person_data_row(object $person): array
? ''
: anchor(
"Messages/view/$person->person_id",
'<span class="glyphicon glyphicon-phone"></span>',
'<i class="bi bi-telephone"></i>',
[
'class' => 'modal-dlg',
'class' => 'modal-launch',
'data-btn-submit' => lang('Common.submit'),
'title' => lang('Messages.sms_send')
]
),
'edit' => anchor(
"$controller/view/$person->person_id",
'<span class="glyphicon glyphicon-edit"></span>',
'<i class="bi bi-pencil-square"></i>',
[
'class' => 'modal-dlg',
'class' => 'modal-launch',
'data-btn-submit' => lang('Common.submit'),
'title' => lang(ucfirst($controller) . '.update') // TODO: String interpolation
]
@@ -299,18 +299,18 @@ function get_customer_data_row(object $person, object $stats): array
? ''
: anchor(
"Messages/view/$person->person_id",
'<span class="glyphicon glyphicon-phone"></span>',
'<i class="bi bi-telephone"></i>',
[
'class' => 'modal-dlg',
'class' => 'modal-launch',
'data-btn-submit' => lang('Common.submit'),
'title' => lang('Messages.sms_send')
]
),
'edit' => anchor(
"$controller/view/$person->person_id",
'<span class="glyphicon glyphicon-edit"></span>',
'<i class="bi bi-pencil-square"></i>',
[
'class' => 'modal-dlg',
'class' => 'modal-launch',
'data-btn-submit' => lang('Common.submit'),
'title' => lang(ucfirst($controller) . ".update")
]
@@ -369,18 +369,18 @@ function get_supplier_data_row(object $supplier): array
? ''
: anchor(
"Messages/view/$supplier->person_id",
'<span class="glyphicon glyphicon-phone"></span>',
'<i class="bi bi-telephone"></i>',
[
'class' => "modal-dlg",
'class' => "modal-launch",
'data-btn-submit' => lang('Common.submit'),
'title' => lang('Messages.sms_send')
]
),
'edit' => anchor(
"$controller/view/$supplier->person_id",
'<span class="glyphicon glyphicon-edit"></span>',
'<i class="bi bi-pencil-square"></i>',
[
'class' => "modal-dlg",
'class' => "modal-launch",
'data-btn-submit' => lang('Common.submit'),
'title' => lang(ucfirst($controller) . ".update")
]
@@ -498,26 +498,26 @@ function get_item_data_row(object $item): array
$icons = [
'inventory' => anchor(
"$controller/inventory/$item->item_id",
'<span class="glyphicon glyphicon-pushpin"></span>',
'<i class="bi bi-box"></i>',
[
'class' => 'modal-dlg',
'class' => 'modal-launch',
'data-btn-submit' => lang('Common.submit'),
'title' => lang(ucfirst($controller) . ".count")
]
),
'stock' => anchor(
"$controller/countDetails/$item->item_id",
'<span class="glyphicon glyphicon-list-alt"></span>',
'<i class="bi bi-info-square"></i>',
[
'class' => 'modal-dlg',
'class' => 'modal-launch',
'title' => lang(ucfirst($controller) . ".details_count")
]
),
'edit' => anchor(
"$controller/view/$item->item_id",
'<span class="glyphicon glyphicon-edit"></span>',
'<i class="bi bi-pencil-square"></i>',
[
'class' => 'modal-dlg',
'class' => 'modal-launch',
'data-btn-submit' => lang('Common.submit'),
'title' => lang(ucfirst($controller) . ".update")
]
@@ -561,9 +561,9 @@ function get_giftcard_data_row(object $giftcard): array
'value' => to_currency($giftcard->value),
'edit' => anchor(
"$controller/view/$giftcard->giftcard_id",
'<span class="glyphicon glyphicon-edit"></span>',
'<i class="bi bi-pencil-square"></i>',
[
'class' => 'modal-dlg',
'class' => 'modal-launch',
'data-btn-submit' => lang('Common.submit'),
'title' => lang(ucfirst($controller) . ".update")
]
@@ -607,9 +607,9 @@ function get_item_kit_data_row(object $item_kit): array
'total_unit_price' => to_currency($item_kit->total_unit_price),
'edit' => anchor(
"$controller/view/$item_kit->item_kit_id",
'<span class="glyphicon glyphicon-edit"></span>',
'<i class="bi bi-pencil-square"></i>',
[
'class' => 'modal-dlg',
'class' => 'modal-launch',
'data-btn-submit' => lang('Common.submit'),
'title' => lang(ucfirst($controller) . ".update")
]
@@ -715,9 +715,9 @@ function get_attribute_definition_data_row(object $attribute_row): array
'definition_flags' => $definition_flags,
'edit' => anchor(
"$controller/view/$attribute_row->definition_id",
'<span class="glyphicon glyphicon-edit"></span>',
'<i class="bi bi-pencil-square"></i>',
[
'class' => 'modal-dlg',
'class' => 'modal-launch',
'data-btn-submit' => lang('Common.submit'),
'title' => lang(ucfirst($controller) . ".update")
]
@@ -755,9 +755,9 @@ function get_expense_category_data_row(object $expense_category): array
'category_description' => $expense_category->category_description,
'edit' => anchor(
"$controller/view/$expense_category->expense_category_id",
'<span class="glyphicon glyphicon-edit"></span>',
'<i class="bi bi-pencil-square"></i>',
[
'class' => 'modal-dlg',
'class' => 'modal-launch',
'data-btn-submit' => lang('Common.submit'),
'title' => lang(ucfirst($controller) . ".update")
]
@@ -809,9 +809,9 @@ function get_expenses_data_row(object $expense): array
'created_by' => $expense->first_name . ' ' . $expense->last_name,
'edit' => anchor(
"$controller/view/$expense->expense_id",
'<span class="glyphicon glyphicon-edit"></span>',
'<i class="bi bi-pencil-square"></i>',
[
'class' => 'modal-dlg',
'class' => 'modal-launch',
'data-btn-submit' => lang('Common.submit'),
'title' => lang(ucfirst($controller) . ".update")
]
@@ -904,16 +904,16 @@ function get_cash_up_data_row(object $cash_up): array
'close_date' => to_datetime(strtotime($cash_up->close_date)),
'close_employee_id' => $cash_up->close_first_name . ' ' . $cash_up->close_last_name,
'closed_amount_cash' => to_currency($cash_up->closed_amount_cash),
'note' => $cash_up->note ? '<span class="glyphicon glyphicon-ok"></span>' : '<span class="glyphicon glyphicon-remove"></span>',
'note' => $cash_up->note ? '<i class="bi bi-check-lg"></i>' : '<i class="bi bi-x-lg"></i>',
'closed_amount_due' => to_currency($cash_up->closed_amount_due),
'closed_amount_card' => to_currency($cash_up->closed_amount_card),
'closed_amount_check' => to_currency($cash_up->closed_amount_check),
'closed_amount_total' => to_currency($cash_up->closed_amount_total),
'edit' => anchor(
"$controller/view/$cash_up->cashup_id",
'<span class="glyphicon glyphicon-edit"></span>',
'<i class="bi bi-pencil-square"></i>',
[
'class' => 'modal-dlg',
'class' => 'modal-launch',
'data-btn-submit' => lang('Common.submit'),
'title' => lang(ucfirst($controller) . ".update")
]

View File

@@ -36,9 +36,9 @@ function get_tax_code_data_row($tax_code_row): array
'state' => $tax_code_row->state,
'edit' => anchor(
"$controller_name/view_tax_codes/$tax_code_row->tax_code",
'<span class="glyphicon glyphicon-edit"></span>',
'<i class="bi bi-pencil-square"></i>',
[
'class' => 'modal-dlg',
'class' => 'modal-launch',
'data-btn-submit' => lang('Common.submit'),
'title' => lang(ucfirst($controller_name) . ".update_tax_codes")
]
@@ -74,9 +74,9 @@ function get_tax_categories_data_row($tax_categories_row): array
'tax_group_sequence' => $tax_categories_row->tax_group_sequence,
'edit' => anchor(
"$controller_name/view/$tax_categories_row->tax_category_id",
'<span class="glyphicon glyphicon-edit"></span>',
'<i class="bi bi-pencil-square"></i>',
[
'class' => 'modal-dlg',
'class' => 'modal-launch',
'data-btn-submit' => lang('Common.submit'),
'title' => lang(ucfirst($controller_name) . ".update")
]
@@ -111,9 +111,9 @@ function get_tax_jurisdictions_data_row($tax_jurisdiction_row): array
'reporting_authority' => $tax_jurisdiction_row->reporting_authority,
'edit' => anchor(
"$controller_name/view/$tax_jurisdiction_row->jurisdiction_id",
'<span class="glyphicon glyphicon-edit"></span>',
'<i class="bi bi-pencil-square"></i>',
[
'class' => 'modal-dlg',
'class' => 'modal-launch',
'data-btn-submit' => lang('Common.submit'),
'title' => lang(ucfirst($controller_name) . ".update")
]
@@ -156,9 +156,9 @@ function get_tax_rates_data_row($tax_rates_row): array
'rounding_code_name' => Rounding_mode::get_rounding_code_name($tax_rates_row->tax_rounding_code),
'edit' => anchor(
"$controller_name/view/$tax_rates_row->tax_rate_id",
'<span class="glyphicon glyphicon-edit"></span>',
'<i class="bi bi-pencil-square"></i>',
[
'class' => 'modal-dlg',
'class' => 'modal-launch',
'data-btn-submit' => lang('Common.submit'),
'title' => lang(ucfirst($controller_name) . ".update")
]

View File

@@ -302,6 +302,10 @@ return [
"suggestions_layout" => "Search Suggestions Layout",
"suggestions_second_column" => "Column 2",
"suggestions_third_column" => "Column 3",
"shortcuts" => "Shortcuts",
"shortcuts_configuration" => "Sales Keyboard Shortcut Configuration",
"shortcuts_duplicate_bindings" => "Shortcut bindings must be unique.",
"shortcuts_save_error" => "Unable to save shortcut settings.",
"system_conf" => "Setup & Conf",
"system_info" => "System Info",
"table" => "Table",

View File

@@ -26,7 +26,7 @@ return [
"cost_price_required" => "Precio al Por Mayor es un campo requerido.",
"count" => "Actualizar Inventario",
"csv_import_failed" => "Falló la importación de Hoja de Cálculo",
"csv_import_invalid_location" => "Ubicación(es) de stock inválida(s) encontrada(s): {0}. Solo ubicaciones de stock válidas son permitidas.",
"csv_import_invalid_location" => "Se encontraron ubicaciones de stock no válidas: {0}. Solo se permiten ubicaciones de stock válidas.",
"csv_import_nodata_wrongformat" => "El archivo subido no tiene datos o el formato es incorrecto.",
"csv_import_partially_failed" => "Hubo {0} falla(s) en la importación de producto(s) en la(s) línea(s): {1}. Ninguna fila ha sido importada.",
"csv_import_success" => "Se importaron los articulos exitosamente.",

View File

@@ -38,7 +38,7 @@ return [
"february" => "",
"march" => "",
"april" => "",
"mayl" => "",
"may" => "",
"june" => "",
"july" => "",
"august" => "",
@@ -46,4 +46,4 @@ return [
"october" => "",
"november" => "",
"december" => "",
];
];

View File

@@ -38,7 +38,7 @@ return [
"february" => "",
"march" => "",
"april" => "",
"mayl" => "",
"may" => "",
"june" => "",
"july" => "",
"august" => "",
@@ -46,4 +46,4 @@ return [
"october" => "",
"november" => "",
"december" => "",
];
];

View File

@@ -38,7 +38,7 @@ return [
"february" => "ഫെബ്രുവരി",
"march" => "മാർച്ച്",
"april" => "ഏപ്രിൽ",
"mayl" => "മേയ്",
"may" => "മേയ്",
"june" => "ജൂൺ",
"july" => "ജൂലൈ",
"august" => "ആഗസ്റ്റ്",
@@ -46,4 +46,4 @@ return [
"october" => "ഒക്ടോബർ",
"november" => "നവംബർ",
"december" => "ഡിസംബർ",
];
];

View File

@@ -38,7 +38,7 @@ return [
"february" => "Februar",
"march" => "Mars",
"april" => "April",
"mayl" => "Mai",
"may" => "Mai",
"june" => "Juni",
"july" => "Juli",
"august" => "August",
@@ -46,4 +46,4 @@ return [
"october" => "Oktober",
"november" => "November",
"december" => "Desember",
];
];

View File

@@ -1,12 +1,12 @@
<?php
return [
"all" => "ทั้งหมด",
"columns" => "คอลัมน์",
"hide_show_pagination" => "ซ่อน/แสดง รายการหน้า",
"loading" => "กำลังดำเนินการ รอสักครู่",
"page_from_to" => "แสดง {0} ถึง {1} จาก {2} รายการ",
"refresh" => "Refresh ข้อมูล",
"rows_per_page" => "{0} รายการ/หน้า",
"toggle" => "ซ่อน/แสดง",
'all' => "ทั้งหมด",
'columns' => "คอลัมน์",
'hide_show_pagination' => "ซ่อน/แสดง รายการหน้า",
'loading' => "กำลังดำเนินการ รอสักครู่ ...",
'page_from_to' => "แสดง {0} ถึง {1} จาก {2} รายการ",
'refresh' => "Refresh ข้อมูล",
'rows_per_page' => "{0} รายการ/หน้า",
'toggle' => "ซ่อน/แสดง",
];

View File

@@ -9,7 +9,9 @@ return [
"login" => "ลงชื่อเข้าใช้",
"logout" => "ออกจากระบบ",
"migration_needed" => "การย้ายฐานข้อมูลไปยัง {0} จะเริ่มต้นหลังจากเข้าสู่ระบบ",
"migration_required" => "",
"migration_required" => "จําเป็นต้องมีการปรับปรุงฐานข้อมูล",
"migration_auth_message" => "ผู้ดูแลระบบจำเป็นต้องมีสิทธิ์ในการปรับปรุงฐานข้อมูลเวอร์ชั่น {0} กรุณาเข้าระบบเพื่อดำเนินการต่อ",
"migration_complete_redirect" => "ทำการปรับปรุงฐานข้อมูลเรียบร้อย กำลังดำเนินการไปหน้าเข้าสู่ระบบ ...",
"migration_auth_message" => "",
"migration_initializing" => "",
"migration_running" => "",
@@ -17,7 +19,6 @@ return [
"migration_complete_login" => "",
"migration_failed" => "",
"migration_error_connection" => "",
"migration_complete_redirect" => "",
"password" => "รหัสผ่าน",
"required_username" => "จำเป็นต้องระบุชื่อผู้ใช้งาน",
"username" => "ชื่อผู้ใช้",

View File

@@ -1,232 +1,232 @@
<?php
return [
"customers_available_points" => "คะแนนที่มี",
"rewards_package" => "คะแนนสะสม",
"rewards_remaining_balance" => "คะแนนสะสมคงเหลือ ",
"account_number" => "บัญชี #",
"add_payment" => "เพิ่มบิล",
"amount_due" => "ยอดค้างชำระ",
"amount_tendered" => "ชำระเข้ามา",
"authorized_signature" => "ลายเซ็นผู้มีอำนาจ",
"cancel_sale" => "ยกเลิกการขาย",
"cash" => "เงินสด",
"cash_1" => "",
"cash_2" => "",
"cash_3" => "",
"cash_4" => "",
"cash_adjustment" => "การปรับเงินสดขาย",
"cash_deposit" => "ฝากเงินสด",
"cash_filter" => "เงินสด",
"change_due" => "เงินทอน",
"change_price" => "เปลี่ยนราคาขาย",
"check" => "โอนเงิน/พร้อมเพย์/เช็ค",
"check_balance" => "เช็คยอดคงเหลือ",
"check_filter" => "ตรวจสอบ",
"close" => "",
"comment" => "หมายเหตุ",
"comments" => "หมายเหตุ",
"company_name" => "",
"complete" => "",
"complete_sale" => "จบการขาย",
"confirm_cancel_sale" => "แน่ใจหรือไม่ที่จะล้างการขายนี้? ทุกรายการจะถูกลบทั้งหมด",
"confirm_delete" => "โปรดยืนยันการลบรายการขายที่เลือกไว้ ?",
"confirm_restore" => "คุณแน่ใจหรือไม่ว่าต้องการยกเลิกการขายที่เลือกไว้?",
"credit" => "เครดิตการ์ด",
"credit_deposit" => "เงินฝากเครดิต",
"credit_filter" => "บัตรเครติด",
"current_table" => "",
"customer" => "ลูกค้า",
"customer_address" => "Customer Address",
"customer_discount" => "ส่วนลด",
"customer_email" => "Customer Email",
"customer_location" => "Customer Location",
"customer_mailchimp_status" => "สถานะของระบบส่งเมล์เมล์ชิม",
"customer_optional" => "(ต้องระบุวันที่ชำระเงิน)",
"customer_required" => "(ต้องระบุ)",
"customer_total" => "Total",
"customer_total_spent" => "",
"daily_sales" => "",
"date" => "วันที่ขาย",
"date_range" => "ระหว่างวันที่",
"date_required" => "กรุณากรอกวันที่ให้ถูกต้อง",
"date_type" => "กรุณากรอกข้อมูลในช่องวันที่",
"debit" => "บัตรประชารัฐ/เดบิตการ์ด",
"debit_filter" => "",
"delete" => "อนุญาตให้ลบ",
"delete_confirmation" => "แน่ใจหรือไม่ที่จะลบรายการขายนี้, ลบแล้วไม่สามารถเรียกกลับคืนใด้",
"delete_entire_sale" => "ลบการขายทั้งหมด",
"delete_successful" => "คุณลบการขายสำเร็จ",
"delete_unsuccessful" => "คุณลบการขายไม่สำเร็จ",
"description_abbrv" => "รายละเอียด",
"discard" => "ยกเลิก",
"discard_quote" => "",
"discount" => "ส่วนลด %",
"discount_included" => "% ส่วนลด",
"discount_short" => "%",
"due" => "วันครบกำหนด",
"due_filter" => "วันที่ครบกำหนด",
"edit" => "แก้ไข",
"edit_item" => "แก้ไขสินค้า",
"edit_sale" => "แก้ไขการขาย",
"email_receipt" => "อีเมลบิล",
"employee" => "พนักงาน",
"entry" => "การนำเข้า",
"error_editing_item" => "แก้ไขสินค้าล้มเหลว",
"negative_price_invalid" => "",
"negative_quantity_invalid" => "",
"negative_discount_invalid" => "",
"discount_percent_exceeds_100" => "",
"discount_exceeds_item_total" => "",
"negative_total_invalid" => "",
"find_or_scan_item" => "ค้นหาสินค้า",
"find_or_scan_item_or_receipt" => "ค้นหา หรือ แสกนรายการ หรือ ใบเสร็จ",
"giftcard" => "บัตรของขวัญ",
"giftcard_balance" => "ยอดคงเหลือบัตรของขวัญ",
"giftcard_filter" => "",
"giftcard_number" => "เลขที่บัตรของขวัญ",
"group_by_category" => "กลุ่มตามหมวดหมู่",
"group_by_type" => "กลุ่มตามประเภท",
"hsn" => "HSN",
"id" => "เลขที่ขาย",
"include_prices" => "รวมในราคา?",
"invoice" => "ใบแจ้งหนี้",
"invoice_confirm" => "ใบแจ้งหนี้นี้จะถูกส่งไปที่",
"invoice_enable" => "เลขที่ใบแจ้งหนี้",
"invoice_filter" => "ใบแจ้งหนี้",
"invoice_no_email" => "ลูกค้ารายนี้ไม่มีที่อยู่อีเมล",
"invoice_number" => "เลขใบแจ้งหนี้ #",
"invoice_number_duplicate" => "ใบแจ้งหนี้หมายเลข {0} จะต้องไม่ซ้ำกัน",
"invoice_sent" => "ส่งใบแจ้งหนี้ไปที่",
"invoice_total" => "ยอดรวมในใบแจ้งหนี้",
"invoice_type_custom_invoice" => "ใบแจ้งหนี้ที่กำหนดเอง (custom_invoice.php)",
"invoice_type_custom_tax_invoice" => "ใบกำกับภาษีที่กำหนดเอง (custom_tax_invoice.php)",
"invoice_type_invoice" => "ใบแจ้งหนี้ (invoice.php)",
"invoice_type_tax_invoice" => "ใบกำกับภาษี (tax_invoice.php)",
"invoice_unsent" => "ไม่สามารถส่งใบแจ้งหนี้ถึง",
"invoice_update" => "คำนวณใหม่",
"item_insufficient_of_stock" => "จำนวนสินค้าไม่เพียงพอ",
"item_name" => "ชื่อสินค้า",
"item_number" => "สินค้า #",
"item_out_of_stock" => "สินค้าจำหน่ายหมด",
"key_browser" => "ความช่วยเหลือ",
"key_cancel" => "ยกเลิกใบเสนอราคา/ใบแจ้งหนี้ /ใบการขาย นี้",
"key_customer_search" => "ค้นหาลูกค้า",
"key_finish_quote" => "จบใบเสนอราคา/ใบแจ้งหนี้โดยไม่ต้องชำระเงิน",
"key_finish_sale" => "เพิ่มการชำระเงินและใบแจ้งหนี้ /ใบรายการขาย",
"key_full" => "เปิดแบบเต็มหน้าจอ",
"key_function" => "ฟังก์ชั่น",
"key_help" => "คำสั่งลัดงานขาย",
"key_help_modal" => "เปิดหน้าต่างคำสั่งลัดงานขาย",
"key_in" => "ขยายเข้า",
"key_item_search" => "ค้นหารายการขาย",
"key_out" => "ขยายออก",
"key_payment" => "เพิ่มการชำระเงิน",
"key_print" => "พิมพ์หน้านี้",
"key_restore" => "คืนการแสดงผลแบบดั้งเดิม/ขยาย",
"key_search" => "ค้นหาตารางรายงาน",
"key_suspend" => "พักรายการขายปัจจุบัน",
"key_suspended" => "แสดงรายการขายที่พักไว้",
"key_system" => "ทางลัดระบบ",
"key_tendered" => "แก้ไขจำนวนเงินรับมา",
"key_title" => "ทางลัดคียบอร์ดงานขาย",
"mc" => "",
"mode" => "รูปแบบการลงทะเบียน",
"must_enter_numeric" => "จำนวนที่ถุกประมูลต้องใส่ข้อมุลที่เปนตัวเลข",
"must_enter_numeric_giftcard" => "เลขที่บัตรของขวัญ ต้องใส่ตัวเลขเท่านั้น",
"new_customer" => "ลูกค้าใหม่",
"new_item" => "สินค้าใหม่",
"no_description" => "ไม่ระบุรายละเอียด",
"no_filter" => "ทั้งหมด",
"no_items_in_cart" => "ไม่พบสินค้าในตระกร้า",
"no_sales_to_display" => "ไม่มีการขายที่จะแสดง",
"none_selected" => "คุณยังไม่ได้เลือกการขายที่จะลบ",
"nontaxed_ind" => " . ",
"not_authorized" => "การกระทำนี้ไม่ได้รับอนุญาต",
"one_or_multiple" => "การขาย",
"payment" => "รูปแบบชำระเงิน",
"payment_amount" => "จำนวน",
"payment_not_cover_total" => "จำนวนเงินที่ชำระต้องมากกว่าหรือเท่ากับยอดรวม",
"payment_type" => "ชำระโดย",
"payments" => "",
"payments_total" => "ยอดชำระแล้ว",
"price" => "ราคา",
"print_after_sale" => "พิมพ์บิลหลังการขาย",
"quantity" => "จำนวน",
"quantity_less_than_reorder_level" => "คำเตือน ถ้าจำนวนของไม่เพียงพอกับความต้องการหรือไม่ตรงกับยอดในบันชี ก็สามารถทำการขายได้ แต่ต้องเชคปริมานสินค้าคงคลัง",
"quantity_less_than_zero" => "คำเตือน: ถ้าจำนวนของไม่เพียงพอกับความต้องการหรือไม่ตรงกับยอดในบัญชี ก็สามารถทำการขายได้ แต่ต้องตรวจสอบปริมาญสินค้าคงคลังก่อน",
"quantity_of_items" => "ปริมาณของ {0} รายการ",
"quote" => "ใบเสนอราคา",
"quote_number" => "หมายเลขอ้างอิง",
"quote_number_duplicate" => "หมายเลขอ้างอิงต้องไม่ซ้ำกัน",
"quote_sent" => "ส่งการอ้างอิงถึง",
"quote_unsent" => "ส่งการอ้างอิงถึงผิดพลาด",
"receipt" => "บิลขาย",
"receipt_no_email" => "ลูกค้านี้ไม่มีที่อยู่อีเมล์",
"receipt_number" => "จุดขาย#",
"receipt_sent" => "ส่งใบเสร็จไปที่",
"receipt_unsent" => "ไม่สามารถส่งใบเสร็จไปที่",
"refund" => "ประเภทการยกเลิกการขาย",
"register" => "ลงทะเบียนขาย",
"remove_customer" => "ลบลูกค้า",
"remove_discount" => "",
"return" => "คืน",
"rewards" => "คะแนนสะสม",
"rewards_balance" => "คะแนนสะสมคงเหลือ",
"sale" => "ขาย",
"sale_by_invoice" => "การขายโดยใบแจ้งหนี้",
"sale_for_customer" => "ลูกค้า:",
"sale_time" => "เวลา",
"sales_tax" => "ภาษีการขาย",
"sales_total" => "",
"select_customer" => "เลือกลูกค้า (Optional)",
"send_invoice" => "ส่งใบแจ้งหนี้",
"send_quote" => "ส่งใบเสนอราคา",
"send_receipt" => "ส่งใบเสร็จ",
"send_work_order" => "ส่งคำสั่งงาน",
"serial" => "หมายเลขซีเรียล",
"service_charge" => "",
"show_due" => "",
"show_invoice" => "ใบแจ้งหนี้",
"show_receipt" => "ใบเสร็จ",
"start_typing_customer_name" => "เริ่มต้นพิมพ์ชื่อลูกค้า...",
"start_typing_item_name" => "เริ่มต้นพิมพ์ชื่อสินค้า หรือ สแกนบาร์โค๊ด...",
"stock" => "คลังสินค้า",
"stock_location" => "ที่เก็บ",
"sub_total" => "ยอดรวมย่อย",
"successfully_deleted" => "ลบการขายสมยูรณ์",
"successfully_restored" => "คุณกู้คืนสำเร็จแล้ว",
"successfully_suspended_sale" => "การขายของคุณถูกระงับเรียบร้อย",
"successfully_updated" => "อัพเดทการขายสมบูรณ์",
"suspend_sale" => "พักรายการ",
"suspended_doc_id" => "รหัสเอกสาร",
"suspended_sale_id" => "รหัสการขายที่ถูกพัก",
"suspended_sales" => "การขายที่พักไว้",
"table" => "โต๊ะ",
"takings" => "การขายประจำวัน",
"tax" => "ภาษี",
"tax_id" => "รหัสภาษี",
"tax_invoice" => "ใบกำกับภาษี",
"tax_percent" => "ภาษี %",
"taxed_ind" => "",
"total" => "ยอดรวม",
"total_tax_exclusive" => "ยอดไม่รวมภาษี",
"transaction_failed" => "การดำเนินการขายล้มเหลว",
"unable_to_add_item" => "เพิ่มรายการไปยังการขายล้มเหลว",
"unsuccessfully_deleted" => "ลบการขายไม่สำเร็จ",
"unsuccessfully_restored" => "การคืนค่ารายการขายล้มเหลว",
"unsuccessfully_suspended_sale" => "การขายของคุณถูกระงับเรียบร้อย",
"unsuccessfully_updated" => "อัพเดทการขายไม่สมบูรณ์",
"unsuspend" => "ยกเลิกการระงับ",
"unsuspend_and_delete" => "ยกเลิกการระงับ และ ลบ",
"update" => "แก้ไข",
"upi" => "ยูพีไอ",
"visa" => "",
"wholesale" => "",
"work_order" => "คำสั่งงาน",
"work_order_number" => "หมายเลขคำสั่งงาน",
"work_order_number_duplicate" => "หมายเลขคำสั่งงานต้องไม่ซ้ำกัน",
"work_order_sent" => "คำสั่งงานส่งถึง",
"work_order_unsent" => "ส่งคำสั่งงานล้มเหลว",
"selected_customer" => "ลูกค้าที่เลือก",
'customers_available_points' => "คะแนนที่มี",
'rewards_package' => "คะแนนสะสม",
'rewards_remaining_balance' => "คะแนนสะสมคงเหลือ ",
'account_number' => "บัญชี #",
'add_payment' => "เพิ่มบิล",
'amount_due' => "ยอดค้างชำระ",
'amount_tendered' => "ชำระเข้ามา",
'authorized_signature' => "ลายเซ็นผู้มีอำนาจ",
'cancel_sale' => "ยกเลิกการขาย",
'cash' => "เงินสด",
'cash_1' => "",
'cash_2' => "",
'cash_3' => "",
'cash_4' => "",
'cash_adjustment' => "การปรับเงินสดขาย",
'cash_deposit' => "ฝากเงินสด",
'cash_filter' => "เงินสด",
'change_due' => "เงินทอน",
'change_price' => "เปลี่ยนราคาขาย",
'check' => "โอนเงิน/พร้อมเพย์/เช็ค",
'check_balance' => "เช็คยอดคงเหลือ",
'check_filter' => "ตรวจสอบ",
'close' => "",
'comment' => "หมายเหตุ",
'comments' => "หมายเหตุ",
'company_name' => "",
'complete' => "",
'complete_sale' => "จบการขาย",
'confirm_cancel_sale' => "แน่ใจหรือไม่ที่จะล้างการขายนี้? ทุกรายการจะถูกลบทั้งหมด",
'confirm_delete' => "โปรดยืนยันการลบรายการขายที่เลือกไว้ ?",
'confirm_restore' => "คุณแน่ใจหรือไม่ว่าต้องการยกเลิกการขายที่เลือกไว้?",
'credit' => "เครดิตการ์ด",
'credit_deposit' => "เงินฝากเครดิต",
'credit_filter' => "บัตรเครติด",
'current_table' => "",
'customer' => "ลูกค้า",
'customer_address' => "Customer Address",
'customer_discount' => "ส่วนลด",
'customer_email' => "Customer Email",
'customer_location' => "Customer Location",
'customer_mailchimp_status' => "สถานะของระบบส่งเมล์เมล์ชิม",
'customer_optional' => "(ต้องระบุวันที่ชำระเงิน)",
'customer_required' => "(ต้องระบุ)",
'customer_total' => "Total",
'customer_total_spent' => "",
'daily_sales' => "",
'date' => "วันที่ขาย",
'date_range' => "ระหว่างวันที่",
'date_required' => "กรุณากรอกวันที่ให้ถูกต้อง",
'date_type' => "กรุณากรอกข้อมูลในช่องวันที่",
'debit' => "บัตรประชารัฐ/เดบิตการ์ด",
'debit_filter' => "",
'delete' => "อนุญาตให้ลบ",
'delete_confirmation' => "แน่ใจหรือไม่ที่จะลบรายการขายนี้, ลบแล้วไม่สามารถเรียกกลับคืนใด้",
'delete_entire_sale' => "ลบการขายทั้งหมด",
'delete_successful' => "คุณลบการขายสำเร็จ",
'delete_unsuccessful' => "คุณลบการขายไม่สำเร็จ",
'description_abbrv' => "รายละเอียด",
'discard' => "ยกเลิก",
'discard_quote' => "",
'discount' => "ส่วนลด %",
'discount_included' => "% ส่วนลด",
'discount_short' => "%",
'due' => "วันครบกำหนด",
'due_filter' => "วันที่ครบกำหนด",
'edit' => "แก้ไข",
'edit_item' => "แก้ไขสินค้า",
'edit_sale' => "แก้ไขการขาย",
'email_receipt' => "อีเมลบิล",
'employee' => "พนักงาน",
'entry' => "การนำเข้า",
'error_editing_item' => "แก้ไขสินค้าล้มเหลว",
'negative_price_invalid' => "ราคาไม่สามารถเป็นค่าติดลบได้",
'negative_quantity_invalid' => "จำนวนไม่สามารถเป็นค่าติดลบได้",
'negative_discount_invalid' => "ส่วนลดไม่สามารถเป็นค่าติดลบได้",
'discount_percent_exceeds_100' => "ส่วนลดเปอร์เซ็นต์มีค่าได้ไม่เกิน 100%",
'discount_exceeds_item_total' => "ส่วนลดต้องไม่เกินจำนวนรายการขายทั้งหมด",
'negative_total_invalid' => "",
'find_or_scan_item' => "ค้นหาสินค้า",
'find_or_scan_item_or_receipt' => "ค้นหา หรือ แสกนรายการ หรือ ใบเสร็จ",
'giftcard' => "บัตรของขวัญ",
'giftcard_balance' => "ยอดคงเหลือบัตรของขวัญ",
'giftcard_filter' => "",
'giftcard_number' => "เลขที่บัตรของขวัญ",
'group_by_category' => "กลุ่มตามหมวดหมู่",
'group_by_type' => "กลุ่มตามประเภท",
'hsn' => "HSN",
'id' => "เลขที่ขาย",
'include_prices' => "รวมในราคา?",
'invoice' => "ใบแจ้งหนี้",
'invoice_confirm' => "ใบแจ้งหนี้นี้จะถูกส่งไปที่",
'invoice_enable' => "เลขที่ใบแจ้งหนี้",
'invoice_filter' => "ใบแจ้งหนี้",
'invoice_no_email' => "ลูกค้ารายนี้ไม่มีที่อยู่อีเมล",
'invoice_number' => "เลขใบแจ้งหนี้ #",
'invoice_number_duplicate' => "ใบแจ้งหนี้หมายเลข {0} จะต้องไม่ซ้ำกัน",
'invoice_sent' => "ส่งใบแจ้งหนี้ไปที่",
'invoice_total' => "ยอดรวมในใบแจ้งหนี้",
'invoice_type_custom_invoice' => "ใบแจ้งหนี้ที่กำหนดเอง (custom_invoice.php)",
'invoice_type_custom_tax_invoice' => "ใบกำกับภาษีที่กำหนดเอง (custom_tax_invoice.php)",
'invoice_type_invoice' => "ใบแจ้งหนี้ (invoice.php)",
'invoice_type_tax_invoice' => "ใบกำกับภาษี (tax_invoice.php)",
'invoice_unsent' => "ไม่สามารถส่งใบแจ้งหนี้ถึง",
'invoice_update' => "คำนวณใหม่",
'item_insufficient_of_stock' => "จำนวนสินค้าไม่เพียงพอ",
'item_name' => "ชื่อสินค้า",
'item_number' => "สินค้า #",
'item_out_of_stock' => "สินค้าจำหน่ายหมด",
'key_browser' => "ความช่วยเหลือ",
'key_cancel' => "ยกเลิกใบเสนอราคา/ใบแจ้งหนี้ /ใบการขาย นี้",
'key_customer_search' => "ค้นหาลูกค้า",
'key_finish_quote' => "จบใบเสนอราคา/ใบแจ้งหนี้โดยไม่ต้องชำระเงิน",
'key_finish_sale' => "เพิ่มการชำระเงินและใบแจ้งหนี้ /ใบรายการขาย",
'key_full' => "เปิดแบบเต็มหน้าจอ",
'key_function' => "ฟังก์ชั่น",
'key_help' => "คำสั่งลัดงานขาย",
'key_help_modal' => "เปิดหน้าต่างคำสั่งลัดงานขาย",
'key_in' => "ขยายเข้า",
'key_item_search' => "ค้นหารายการขาย",
'key_out' => "ขยายออก",
'key_payment' => "เพิ่มการชำระเงิน",
'key_print' => "พิมพ์หน้านี้",
'key_restore' => "คืนการแสดงผลแบบดั้งเดิม/ขยาย",
'key_search' => "ค้นหาตารางรายงาน",
'key_suspend' => "พักรายการขายปัจจุบัน",
'key_suspended' => "แสดงรายการขายที่พักไว้",
'key_system' => "ทางลัดระบบ",
'key_tendered' => "แก้ไขจำนวนเงินรับมา",
'key_title' => "ทางลัดคียบอร์ดงานขาย",
'mc' => "",
'mode' => "รูปแบบการลงทะเบียน",
'must_enter_numeric' => "จำนวนที่ถุกประมูลต้องใส่ข้อมุลที่เปนตัวเลข",
'must_enter_numeric_giftcard' => "เลขที่บัตรของขวัญ ต้องใส่ตัวเลขเท่านั้น",
'new_customer' => "ลูกค้าใหม่",
'new_item' => "สินค้าใหม่",
'no_description' => "ไม่ระบุรายละเอียด",
'no_filter' => "ทั้งหมด",
'no_items_in_cart' => "ไม่พบสินค้าในตระกร้า",
'no_sales_to_display' => "ไม่มีการขายที่จะแสดง",
'none_selected' => "คุณยังไม่ได้เลือกการขายที่จะลบ",
'nontaxed_ind' => " . ",
'not_authorized' => "การกระทำนี้ไม่ได้รับอนุญาต",
'one_or_multiple' => "การขาย",
'payment' => "รูปแบบชำระเงิน",
'payment_amount' => "จำนวน",
'payment_not_cover_total' => "จำนวนเงินที่ชำระต้องมากกว่าหรือเท่ากับยอดรวม",
'payment_type' => "ชำระโดย",
'payments' => "",
'payments_total' => "ยอดชำระแล้ว",
'price' => "ราคา",
'print_after_sale' => "พิมพ์บิลหลังการขาย",
'quantity' => "จำนวน",
'quantity_less_than_reorder_level' => "คำเตือน ถ้าจำนวนของไม่เพียงพอกับความต้องการหรือไม่ตรงกับยอดในบันชี ก็สามารถทำการขายได้ แต่ต้องเชคปริมานสินค้าคงคลัง",
'quantity_less_than_zero' => "คำเตือน: ถ้าจำนวนของไม่เพียงพอกับความต้องการหรือไม่ตรงกับยอดในบัญชี ก็สามารถทำการขายได้ แต่ต้องตรวจสอบปริมาญสินค้าคงคลังก่อน",
'quantity_of_items' => "ปริมาณของ {0} รายการ",
'quote' => "ใบเสนอราคา",
'quote_number' => "หมายเลขอ้างอิง",
'quote_number_duplicate' => "หมายเลขอ้างอิงต้องไม่ซ้ำกัน",
'quote_sent' => "ส่งการอ้างอิงถึง",
'quote_unsent' => "ส่งการอ้างอิงถึงผิดพลาด",
'receipt' => "บิลขาย",
'receipt_no_email' => "ลูกค้านี้ไม่มีที่อยู่อีเมล์",
'receipt_number' => "จุดขาย#",
'receipt_sent' => "ส่งใบเสร็จไปที่",
'receipt_unsent' => "ไม่สามารถส่งใบเสร็จไปที่",
'refund' => "ประเภทการยกเลิกการขาย",
'register' => "ลงทะเบียนขาย",
'remove_customer' => "ลบลูกค้า",
'remove_discount' => "",
'return' => "คืน",
'rewards' => "คะแนนสะสม",
'rewards_balance' => "คะแนนสะสมคงเหลือ",
'sale' => "ขาย",
'sale_by_invoice' => "การขายโดยใบแจ้งหนี้",
'sale_for_customer' => "ลูกค้า:",
'sale_time' => "เวลา",
'sales_tax' => "ภาษีการขาย",
'sales_total' => "",
'select_customer' => "เลือกลูกค้า (Optional)",
'send_invoice' => "ส่งใบแจ้งหนี้",
'send_quote' => "ส่งใบเสนอราคา",
'send_receipt' => "ส่งใบเสร็จ",
'send_work_order' => "ส่งคำสั่งงาน",
'serial' => "หมายเลขซีเรียล",
'service_charge' => "",
'show_due' => "",
'show_invoice' => "ใบแจ้งหนี้",
'show_receipt' => "ใบเสร็จ",
'start_typing_customer_name' => "เริ่มต้นพิมพ์ชื่อลูกค้า...",
'start_typing_item_name' => "เริ่มต้นพิมพ์ชื่อสินค้า หรือ สแกนบาร์โค๊ด...",
'stock' => "คลังสินค้า",
'stock_location' => "ที่เก็บ",
'sub_total' => "ยอดรวมย่อย",
'successfully_deleted' => "ลบการขายสมยูรณ์",
'successfully_restored' => "คุณกู้คืนสำเร็จแล้ว",
'successfully_suspended_sale' => "การขายของคุณถูกระงับเรียบร้อย",
'successfully_updated' => "อัพเดทการขายสมบูรณ์",
'suspend_sale' => "พักรายการ",
'suspended_doc_id' => "รหัสเอกสาร",
'suspended_sale_id' => "รหัสการขายที่ถูกพัก",
'suspended_sales' => "การขายที่พักไว้",
'table' => "โต๊ะ",
'takings' => "การขายประจำวัน",
'tax' => "ภาษี",
'tax_id' => "รหัสภาษี",
'tax_invoice' => "ใบกำกับภาษี",
'tax_percent' => "ภาษี %",
'taxed_ind' => "",
'total' => "ยอดรวม",
'total_tax_exclusive' => "ยอดไม่รวมภาษี",
'transaction_failed' => "การดำเนินการขายล้มเหลว",
'unable_to_add_item' => "เพิ่มรายการไปยังการขายล้มเหลว",
'unsuccessfully_deleted' => "ลบการขายไม่สำเร็จ",
'unsuccessfully_restored' => "การคืนค่ารายการขายล้มเหลว",
'unsuccessfully_suspended_sale' => "การขายของคุณถูกระงับเรียบร้อย",
'unsuccessfully_updated' => "อัพเดทการขายไม่สมบูรณ์",
'unsuspend' => "ยกเลิกการระงับ",
'unsuspend_and_delete' => "ยกเลิกการระงับ และ ลบ",
'update' => "แก้ไข",
'upi' => "ยูพีไอ",
'visa' => "",
'wholesale' => "",
'work_order' => "คำสั่งงาน",
'work_order_number' => "หมายเลขคำสั่งงาน",
'work_order_number_duplicate' => "หมายเลขคำสั่งงานต้องไม่ซ้ำกัน",
'work_order_sent' => "คำสั่งงานส่งถึง",
'work_order_unsent' => "ส่งคำสั่งงานล้มเหลว",
'selected_customer' => "ลูกค้าที่เลือก",
];

View File

@@ -82,4 +82,40 @@ class Email_lib
return $result;
}
/**
* Gets the mime type of the company logo file.
*
* @return string Mime type or empty string if logo doesn't exist
*/
public function getLogoMimeType(): string
{
$logo_path = FCPATH . 'uploads/' . $this->config['company_logo'];
if (!empty($this->config['company_logo']) && file_exists($logo_path)) {
$mimeType = mime_content_type($logo_path);
return $mimeType !== false ? $mimeType : '';
}
return '';
}
/**
* Builds an img tag for the company logo to use in email templates.
*
* @return string HTML img tag with base64-encoded logo, or empty string if no logo
*/
public function buildLogoImgTag(): string
{
$mimeType = $this->getLogoMimeType();
if ($mimeType === '') {
return '';
}
$logo_path = FCPATH . 'uploads/' . $this->config['company_logo'];
$logo_data = base64_encode(file_get_contents($logo_path));
return '<img id="image" src="data:' . $mimeType . ';base64,' . $logo_data . '" alt="company_logo">';
}
}

View File

@@ -2,7 +2,6 @@
namespace App\Libraries;
use CodeIgniter\Database\Exceptions\DatabaseException;
use CodeIgniter\Database\MigrationRunner;
use Config\Database;
use stdClass;
@@ -44,7 +43,9 @@ class MY_Migration extends MigrationRunner
$result = $builder->get()->getRow();
return $result ? $result->version : 0;
}
} catch (DatabaseException $e) {
} catch (\Exception $e) {
// Database not available yet (e.g. fresh install before schema).
// Catches mysqli_sql_exception which is not a DatabaseException.
return 0;
}
@@ -76,8 +77,9 @@ class MY_Migration extends MigrationRunner
$result = $builder->get()->getRow();
return $result ? $result->version : false;
}
} catch (DatabaseException $e) {
// Database doesn't exist yet or connection failed
} catch (\Exception $e) {
// Database not available yet (e.g. fresh install before schema).
// Catches mysqli_sql_exception which is not a DatabaseException.
}
return false;

View File

@@ -23,6 +23,19 @@ use ReflectionException;
*/
class Sale_lib
{
private const KEY_SHORTCUT_DEFAULTS = [
'cancel' => ['value' => '27 | ESC', 'code' => 27, 'label' => 'ESC'],
'items' => ['value' => '49 | ALT + 1', 'code' => 49, 'label' => 'ALT + 1'],
'customers' => ['value' => '50 | ALT + 2', 'code' => 50, 'label' => 'ALT + 2'],
'suspend' => ['value' => '51 | ALT + 3', 'code' => 51, 'label' => 'ALT + 3'],
'suspended' => ['value' => '52 | ALT + 4', 'code' => 52, 'label' => 'ALT + 4'],
'amount' => ['value' => '53 | ALT + 5', 'code' => 53, 'label' => 'ALT + 5'],
'payment' => ['value' => '54 | ALT + 6', 'code' => 54, 'label' => 'ALT + 6'],
'complete' => ['value' => '55 | ALT + 7', 'code' => 55, 'label' => 'ALT + 7'],
'finish' => ['value' => '56 | ALT + 8', 'code' => 56, 'label' => 'ALT + 8'],
'help' => ['value' => '57 | ALT + 9', 'code' => 57, 'label' => 'ALT + 9'],
];
private Attribute $attribute;
private Customer $customer;
private Dinner_table $dinner_table;
@@ -105,6 +118,44 @@ class Sale_lib
return $invoice_types;
}
/**
* Returns the available keyboard shortcut choices for the configuration screen.
*
* @return array<string, string>
*/
public function getKeyShortcutsOptions(): array
{
$keyShortcuts = [];
foreach (self::KEY_SHORTCUT_DEFAULTS as $shortcut) {
$keyShortcuts[$shortcut['value']] = $shortcut['label'];
}
return $keyShortcuts;
}
/**
* Returns parsed shortcut bindings from app_config with sensible defaults.
*
* @return array<string, array{value:string,code:int,label:string}>
*/
public function getKeyShortcuts(): array
{
$keyboardShortcuts = [];
foreach (self::KEY_SHORTCUT_DEFAULTS as $name => $default) {
$value = $this->config["key_$name"] ?? $default['value'];
$parts = array_map('trim', explode('|', $value, 2));
$keyboardShortcuts[$name] = [
'value' => $value,
'code' => (int)($parts[0] ?? $default['code']),
'label' => $parts[1] ?? $default['label']
];
}
return $keyboardShortcuts;
}
public static function isValidInvoiceType(string $invoice_type): bool
{
return in_array($invoice_type, self::ALLOWED_INVOICE_TYPES, true);

View File

@@ -65,8 +65,10 @@ class Item extends Model
public function exists(string $item_id, bool $ignore_deleted = false, bool $deleted = false): bool
{
$builder = $this->db->table('items');
$builder->groupStart();
$builder->where('item_id', $item_id);
$builder->orWhere('item_number', $item_id);
$builder->groupEnd();
if (!$ignore_deleted) {
$builder->where('deleted', $deleted);
@@ -389,9 +391,10 @@ class Item extends Model
public function get_item_id(string $item_number, bool $ignore_deleted = false, bool $deleted = false): bool|int
{
$builder = $this->db->table('items');
$builder->join('suppliers', 'suppliers.person_id = items.supplier_id', 'left');
$builder->groupStart();
$builder->where('item_number', $item_number);
$builder->orWhere('item_id', $item_number);
$builder->groupEnd();
if (!$ignore_deleted) {
$builder->where('items.deleted', $deleted);

View File

@@ -10,93 +10,75 @@
*/
?>
<div id="required_fields_message"><?= lang('Common.fields_required_message') ?></div>
<ul id="error_message_box" class="error_message_box"></ul>
<?= form_open("attributes/saveDefinition/$definition_id", ['id' => 'attribute_form']) ?>
<?= form_open("attributes/saveDefinition/$definition_id", ['id' => 'attribute_form', 'class' => 'form-horizontal']) ?>
<fieldset id="attribute_basic_info">
<ul id="error_message_box" class="alert alert-warning d-none"></ul>
<div class="form-group form-group-sm">
<?= form_label(lang('Attributes.definition_name'), 'definition_name', ['class' => 'required control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_input([
'name' => 'definition_name',
'id' => 'definition_name',
'class' => 'form-control input-sm',
'value' => esc($definition_info->definition_name)
]) ?>
</div>
<label for="definition_name" class="form-label"><?= lang('Attributes.definition_name'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="definition_name-icon"><i class="bi bi-star"></i></span>
<input type="text" class="form-control" name="definition_name" id="definition_name" aria-describedby="definition_name-icon" value="<?= esc($definition_info->definition_name); ?>">
</div>
<label for="definition_type" class="form-label"><?= lang('Attributes.definition_type'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="definition_type-icon"><i class="bi bi-list"></i></span>
<select class="form-select" name="definition_type" id="definition_type" aria-describedby="definition_type-icon">
<?php foreach (DEFINITION_TYPES as $key => $label): ?>
<option value="<?= $key ?>" <?= ($key === array_search($definition_info->definition_type, DEFINITION_TYPES)) ? 'selected' : '' ?>>
<?= $label ?>
</option>
<?php endforeach; ?>
</select>
</div>
<label for="definition_group" class="form-label"><?= lang('Attributes.definition_group'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="definition_group-icon"><i class="bi bi-collection"></i></span>
<select class="form-select" name="definition_group" id="definition_group" aria-describedby="definition_group-icon" <?= empty($definition_group) ? 'disabled' : '' ?>>
<?php foreach ($definition_group as $key => $label): ?>
<option value="<?= $key ?>" <?= ($key == $definition_info->definition_fk) ? 'selected' : '' ?>>
<?= $label ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="toggle-hide d-none">
<label for="definition_flags" class="form-label"><?= lang('Attributes.definition_flags'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="definition_flags-icon"><i class="bi bi-eyeglasses"></i></span>
<select class="form-select" name="definition_flags[]" id="definition_flags" aria-describedby="definition_flags-icon" multiple>
<?php foreach ($definition_flags as $key => $label): ?>
<option value="<?= $key ?>" <?= in_array($key, array_keys($selected_definition_flags)) ? 'selected' : '' ?>>
<?= $label ?>
</option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Attributes.definition_type'), 'definition_type', ['class' => 'required control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_dropdown('definition_type', DEFINITION_TYPES, array_search($definition_info->definition_type, DEFINITION_TYPES), 'id="definition_type" class="form-control"') ?>
</div>
<div class="toggle-hide d-none">
<label for="definition_unit" class="form-label"><?= lang('Attributes.definition_unit'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="definition_unit-icon"><i class="bi bi-flask"></i></span>
<input type="text" class="form-control" name="definition_unit" id="definition_unit" aria-describedby="definition_unit-icon" value="<?= esc($definition_info->definition_unit); ?>">
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Attributes.definition_group'), 'definition_group', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_dropdown(
'definition_group',
$definition_group,
$definition_info->definition_fk,
'id="definition_group" class="form-control" ' . (empty($definition_group) ? 'disabled="disabled"' : '')
) ?>
</div>
<div class="toggle-hide d-none">
<label for="definition_value" class="form-label"><?= lang('Attributes.definition_values'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="definition_value-icon"><i class="bi bi-list"></i></span>
<input type="text" class="form-control" name="definition_value" id="definition_value" aria-describedby="definition_value-icon">
<button type="button" class="btn btn-outline-secondary" id="add_attribute_value"><i class="bi bi-plus-circle"></i></button>
</div>
</div>
<div class="form-group form-group-sm hidden">
<?= form_label(lang('Attributes.definition_flags'), 'definition_flags', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<div class="input-group">
<?= form_multiselect('definition_flags[]', $definition_flags, array_keys($selected_definition_flags), [
'id' => 'definition_flags',
'class' => 'selectpicker show-menu-arrow',
'data-none-selected-text' => lang('Common.none_selected_text'),
'data-selected-text-format' => 'count > 1',
'data-style' => 'btn-default btn-sm',
'data-width' => 'fit'
]) ?>
</div>
</div>
</div>
<div class="toggle-hide d-none">
<ul class="list-group" id="definition_list_group"></ul>
</div>
<div class="form-group form-group-sm hidden">
<?= form_label(lang('Attributes.definition_unit'), 'definition_units', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<div class="input-group">
<?= form_input([
'name' => 'definition_unit',
'value' => esc($definition_info->definition_unit),
'class' => 'form-control input-sm',
'id' => 'definition_unit'
]) ?>
</div>
</div>
</div>
<div class="form-group form-group-sm hidden">
<?= form_label(lang('Attributes.definition_values'), 'definition_value', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<div class="input-group">
<?= form_input(['name' => 'definition_value', 'class' => 'form-control input-sm', 'id' => 'definition_value']) ?>
<span id="add_attribute_value" class="input-group-addon input-sm btn btn-default">
<span class="glyphicon glyphicon-plus-sign"></span>
</span>
</div>
</div>
</div>
<div class="form-group form-group-sm hidden">
<?= form_label('&nbsp;', 'definition_list_group', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<ul id="definition_list_group" class="list-group"></ul>
</div>
</div>
</fieldset>
<?= form_close() ?>
<script type="text/javascript">
@@ -125,8 +107,8 @@
if (definition_id == -1) {
$('#definition_name').prop("disabled", true);
$('#definition_type').prop("disabled", true);
$('#definition_group').parents('.form-group').toggleClass("hidden", true);
$('#definition_flags').parents('.form-group').toggleClass('hidden', true);
$('#definition_group').parents('.toggle-hide').toggleClass("d-none", true);
$('#definition_flags').parents('.toggle-hide').toggleClass("d-none", true);
}
}
disable_category_dropdown();
@@ -137,21 +119,23 @@
var is_no_group = $('#definition_type').val() !== '0';
var is_category_dropdown = definition_id == -1;
$('#definition_value, #definition_list_group').parents('.form-group').toggleClass('hidden', is_dropdown);
$('#definition_unit').parents('.form-group').toggleClass('hidden', is_decimal);
$('#definition_value, #definition_list_group').parents('.toggle-hide').toggleClass('d-none', is_dropdown);
$('#definition_unit').parents('.toggle-hide').toggleClass('d-none', is_decimal);
// Appropriately show definition flags if not category_dropdown
if (definition_id != -1) {
$('#definition_flags').parents('.form-group').toggleClass('hidden', !is_no_group);
$('#definition_flags').parents('.toggle-hide').toggleClass('d-none', !is_no_group);
}
};
$('#definition_type').change(show_hide_fields);
show_hide_fields();
$('.selectpicker').each(function() {
var $selectpicker = $(this);
$.fn.selectpicker.call($selectpicker, $selectpicker.data());
new TomSelect('#definition_flags', {
plugins: ['checkbox_options', 'remove_button'],
placeholder: '<?= lang('Common.none_selected_text') ?>',
hidePlaceholder: true,
closeAfterSelect: false,
});
var remove_attribute_value = function() {
@@ -192,7 +176,7 @@
}
}
$('#definition_list_group').append('<li class="list-group-item">' + DOMPurify.sanitize(value) + '<a href="javascript:void(0);"><span class="glyphicon glyphicon-trash pull-right"></span></a></li>')
$('#definition_list_group').append('<li class="list-group-item list-group-item-action d-flex justify-content-between">' + DOMPurify.sanitize(value) + '<a href="javascript:void(0);"><span class="text-danger"><i class="bi bi-trash"></i></span></a></li>')
.find(':last-child a').click(remove_attribute_value);
$('#definition_value').val('');
};

View File

@@ -7,96 +7,98 @@
*/
?>
<div class="form-group form-group-sm">
<?= form_label(lang('Attributes.definition_name'), 'definition_name_label', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_dropdown([
'name' => 'definition_name',
'options' => $definition_names,
'selected' => -1,
'class' => 'form-control',
'id' => 'definition_name'
]) ?>
</div>
<label for="definition_name" class="form-label"><?= lang('Attributes.definition_name'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-star"></i></span>
<select class="form-select" name="definition_name" id="definition_name">
<option value="-1" selected></option>
<?php foreach ($definition_names as $key => $value): ?>
<option value="<?= $key ?>"><?= $value ?></option>
<?php endforeach; ?>
</select>
</div>
<?php foreach ($definition_values as $definition_id => $definition_value) { ?>
<div class="form-group form-group-sm">
<?= form_label(esc($definition_value['definition_name']), esc($definition_value['definition_name']), ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<div class="input-group">
<?php
echo form_hidden("attribute_ids[$definition_id]", strval($definition_value['attribute_id']));
$attribute_value = $definition_value['attribute_value'];
<span class="attribute_added">
<?php
$attribute_value = $definition_value['attribute_value'];
switch ($definition_value['definition_type']) {
case DATE:
$value = (empty($attribute_value) || empty($attribute_value->attribute_date)) ? NOW : strtotime($attribute_value->attribute_date);
echo form_input([
'name' => "attribute_links[$definition_id]",
'value' => to_date($value),
'class' => 'form-control input-sm datetime',
'data-definition-id' => $definition_id,
'readonly' => 'true'
]);
break;
case DROPDOWN:
$selected_value = $definition_value['selected_value'];
echo form_dropdown([
'name' => "attribute_links[$definition_id]",
'options' => $definition_value['values'],
'selected' => $selected_value,
'class' => 'form-control',
'data-definition-id' => $definition_id
]);
break;
case TEXT:
$value = (empty($attribute_value) || empty($attribute_value->attribute_value)) ? $definition_value['selected_value'] : $attribute_value->attribute_value;
echo form_input([
'name' => "attribute_links[$definition_id]",
'value' => esc($value),
'class' => 'form-control valid_chars',
'data-definition-id' => $definition_id
]);
break;
case DECIMAL:
$value = (empty($attribute_value) || empty($attribute_value->attribute_decimal)) ? $definition_value['selected_value'] : $attribute_value->attribute_decimal;
echo form_input([
'name' => "attribute_links[$definition_id]",
'value' => to_decimals((float)$value),
'class' => 'form-control valid_chars',
'data-definition-id' => $definition_id
]);
break;
case CHECKBOX:
$value = (empty($attribute_value) || empty($attribute_value->attribute_value)) ? $definition_value['selected_value'] : $attribute_value->attribute_value;
switch ($definition_value['definition_type']) {
// Sends 0 if the box is unchecked instead of not sending anything.
echo form_input([
'type' => 'hidden',
'name' => "attribute_links[$definition_id]",
'id' => "attribute_links[$definition_id]",
'value' => 0,
'data-definition-id' => $definition_id
]);
echo form_checkbox([
'name' => "attribute_links[$definition_id]",
'id' => "attribute_links[$definition_id]",
'value' => 1,
'checked' => $value == 1,
'class' => 'checkbox-inline',
'data-definition-id' => $definition_id
]);
break;
}
?>
<span class="input-group-addon input-sm btn btn-default remove_attribute_btn">
<span class="glyphicon glyphicon-trash"></span>
</span>
case DATE:
$value = (empty($attribute_value) || empty($attribute_value->attribute_date)) ? NOW : strtotime($attribute_value->attribute_date);
?>
<label for="attribute_links[<?= $definition_id ?>]" class="form-label"><?= esc($definition_value['definition_name']) ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="attribute_links[<?= $definition_id ?>]-icon"><i class="bi bi-calendar2"></i></span>
<input type="hidden" name="attribute_ids[<?= $definition_id ?>]" value="<?= strval($definition_value['attribute_id']) ?>">
<input type="text" class="form-select datetime" name="attribute_links[<?= $definition_id ?>]" id="attribute_links[<?= $definition_id ?>]" aria-describedby="attribute_links[<?= $definition_id ?>]-icon" value="<?= to_date($value) ?>" data-definition-id="<?= $definition_id ?>" readonly>
<button type="button" class="btn btn-outline-danger remove_attribute_btn"><i class="bi bi-trash"></i></button>
</div>
</div>
</div>
<?php
break;
case DROPDOWN:
$selected_value = $definition_value['selected_value'];
?>
<label for="attribute_links[<?= $definition_id ?>]" class="form-label"><?= esc($definition_value['definition_name']) ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="attribute_links[<?= $definition_id ?>]-icon"><i class="bi bi-menu-down"></i></span>
<input type="hidden" name="attribute_ids[<?= $definition_id ?>]" value="<?= strval($definition_value['attribute_id']) ?>">
<select class="form-select" name="attribute_links[<?= $definition_id ?>]" id="attribute_links[<?= $definition_id ?>]" data-definition-id="<?= $definition_id ?>">
<?php foreach ($definition_value['values'] as $key => $val): ?>
<option value="<?= $key ?>" <?= $selected_value == $key ? 'selected' : '' ?>><?= $val ?></option>
<?php endforeach; ?>
</select>
<button type="button" class="btn btn-outline-danger remove_attribute_btn"><i class="bi bi-trash"></i></button>
</div>
<?php
break;
case TEXT:
$value = (empty($attribute_value) || empty($attribute_value->attribute_value)) ? $definition_value['selected_value'] : $attribute_value->attribute_value;
?>
<label for="attribute_links[<?= $definition_id ?>]" class="form-label"><?= esc($definition_value['definition_name']) ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="attribute_links[<?= $definition_id ?>]-icon"><i class="bi bi-type"></i></span>
<input type="hidden" name="attribute_ids[<?= $definition_id ?>]" value="<?= strval($definition_value['attribute_id']) ?>">
<input type="text" name="attribute_links[<?= $definition_id ?>]" id="attribute_links[<?= $definition_id ?>]" value="<?= esc($value) ?>" class="form-control valid_chars" data-definition-id="<?= $definition_id ?>">
<button type="button" class="btn btn-outline-danger remove_attribute_btn"><i class="bi bi-trash"></i></button>
</div>
<?php
break;
case DECIMAL:
$value = (empty($attribute_value) || empty($attribute_value->attribute_decimal)) ? $definition_value['selected_value'] : $attribute_value->attribute_decimal;
?>
<label for="attribute_links[<?= $definition_id ?>]" class="form-label"><?= esc($definition_value['definition_name']) ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="attribute_links[<?= $definition_id ?>]-icon"><i class="bi bi-dot"></i></span>
<input type="hidden" name="attribute_ids[<?= $definition_id ?>]" value="<?= strval($definition_value['attribute_id']) ?>">
<input type="text" name="attribute_links[<?= $definition_id ?>]" id="attribute_links[<?= $definition_id ?>]" value="<?= to_decimals((float)$value) ?>" class="form-control valid_chars" data-definition-id="<?= $definition_id ?>">
<button type="button" class="btn btn-outline-danger remove_attribute_btn"><i class="bi bi-trash"></i></button>
</div>
<?php
break;
case CHECKBOX:
$value = (empty($attribute_value) || empty($attribute_value->attribute_value)) ? $definition_value['selected_value'] : $attribute_value->attribute_value;
?>
<div class="d-flex justify-content-between">
<div class="form-check form-check-inline mb-3">
<input type="hidden" name="attribute_ids[<?= $definition_id ?>]" value="<?= strval($definition_value['attribute_id']) ?>">
<input type="hidden" name="attribute_links_h1[<?= $definition_id ?>]" id="attribute_links_h1<?= $definition_id ?>" value="0" data-definition-id="<?= $definition_id ?>">
<input type="checkbox" class="form-check-input" name="attribute_links[<?= $definition_id ?>]" id="attribute_links[<?= $definition_id ?>]" value="1" <?= $value == 1 ? 'checked' : '' ?> data-definition-id="<?= $definition_id ?>">
<label class="form-check-label" for="attribute_links[<?= $definition_id ?>]"><?= esc($definition_value['definition_name']) ?></label>
</div>
<button type="button" class="btn btn-outline-danger remove_attribute_btn"><i class="bi bi-trash"></i></button>
</div>
<?php
break;
}
?>
</span>
<?php } ?>
@@ -106,7 +108,7 @@
var enable_delete = function() {
$('.remove_attribute_btn').click(function() {
$(this).parents('.form-group').remove();
$(this).parents('.attribute_added').remove();
});
};
@@ -134,13 +136,13 @@
$("[name*='attribute_links'").each(function() {
var definition_id = $(this).data('definition-id');
var element = $(this);
// For checkboxes, use the visible checkbox, not the hidden input
if (element.attr('type') === 'hidden' && element.siblings('input[type="checkbox"]').length > 0) {
// Skip hidden inputs that have a corresponding checkbox
return;
}
// For checkboxes, get the checked state
if (element.attr('type') === 'checkbox') {
result[definition_id] = element.prop('checked') ? '1' : '0';

View File

@@ -8,6 +8,11 @@
<?= view('partial/header') ?>
<?php
$title_info['config_title'] = 'Attributes';
echo view('configs/config_header', $title_info);
?>
<script type="text/javascript">
$(document).ready(function() {
<?= view('partial/bootstrap_tables_locale') ?>
@@ -21,16 +26,16 @@
});
</script>
<div id="title_bar" class="btn-toolbar print_hide">
<button class="btn btn-info btn-sm pull-right modal-dlg" data-btn-submit="<?= lang('Common.submit') ?>" data-href="<?= esc("$controller_name/view") ?>" title="<?= lang(ucfirst($controller_name) . ".new") ?>">
<span class="glyphicon glyphicon-star">&nbsp;</span><?= lang(ucfirst($controller_name) . ".new") ?>
<div class="d-flex gap-2 justify-content-end d-print-none">
<button type="button" class="btn btn-primary modal-launch" data-btn-submit="<?= lang('Common.submit') ?>" data-href="<?= esc("$controller_name/view") ?>" title="<?= lang(ucfirst($controller_name) . ".new") ?>">
<i class="bi bi-star me-2"></i><?= lang(ucfirst($controller_name) . ".new") ?>
</button>
</div>
<div id="toolbar">
<div class="pull-left form-inline" role="toolbar">
<button id="delete" class="btn btn-default btn-sm print_hide">
<span class="glyphicon glyphicon-trash">&nbsp;</span><?= lang('Common.delete') ?>
<div class="d-flex gap-2">
<button type="button" class="btn btn-secondary d-print-none" id="delete">
<i class="bi bi-trash"></i><span class="d-none d-sm-inline ms-2"><?= lang('Common.delete') ?></span>
</button>
</div>
</div>

View File

@@ -11,31 +11,34 @@ $barcode_lib = new Barcode_lib();
<!doctype html>
<html lang="<?= current_language_code() ?>">
<head>
<meta charset="utf-8">
<title><?= lang('Items.generate_barcodes') ?></title>
<link rel="stylesheet" href="<?= base_url() ?>css/barcode_font.css">
<style>
.barcode svg {
height: <?= $barcode_config['barcode_height'] ?>px;
width: <?= $barcode_config['barcode_width'] ?>px;
}
</style>
</head>
<body class=<?= 'font_' . $barcode_lib->get_font_name($barcode_config['barcode_font']) ?> style="font-size: <?= $barcode_config['barcode_font_size'] ?>px;">
<table style="border-spacing: <?= $barcode_config['barcode_page_cellspacing'] ?>; width: <?= $barcode_config['barcode_page_width'] ?>%;">
<tr>
<?php
$count = 0;
foreach ($items as $item) {
if ($count % $barcode_config['barcode_num_in_row'] == 0 && $count != 0) {
echo '</tr><tr>';
}
echo '<td>' . $barcode_lib->display_barcode($item, $barcode_config) . '</td>';
$count++;
<head>
<meta charset="utf-8">
<title><?= esc(lang('Items.generate_barcodes')) ?></title>
<link rel="stylesheet" href="<?= esc(base_url('css/barcode_font.css'), 'url') ?>">
<style>
.barcode svg {
height: <?= (int) $barcode_config['barcode_height'] ?>px;
width: <?= (int) $barcode_config['barcode_width'] ?>px;
}
</style>
</head>
<body class="<?= esc('font_' . $barcode_lib->get_font_name($barcode_config['barcode_font']), 'attr') ?>" style="font-size: <?= (int) $barcode_config['barcode_font_size'] ?>px;">
<table style="border-spacing: <?= (int) $barcode_config['barcode_page_cellspacing'] ?>px; width: <?= (int) $barcode_config['barcode_page_width'] ?>%;">
<tr>
<?php
$count = 0;
foreach ($items as $item) {
if ($count % $barcode_config['barcode_num_in_row'] == 0 && $count != 0) {
echo '</tr><tr>';
}
?>
</tr>
</table>
</body>
echo '<td>' . $barcode_lib->display_barcode($item, $barcode_config) . '</td>';
$count++;
}
?>
</tr>
</table>
</body>
</html>

View File

@@ -23,7 +23,7 @@
<div class="col-xs-6">
<div class="input-group">
<span class="input-group-addon input-sm">
<span class="glyphicon glyphicon-calendar"></span>
<i class="bi bi-calendar2-check"></i>
</span>
<?= form_input([
'name' => 'open_date',
@@ -87,7 +87,7 @@
<div class="col-xs-6">
<div class="input-group">
<span class="input-group-addon input-sm">
<span class="glyphicon glyphicon-calendar"></span>
<i class="bi bi-calendar2-x"></i>
</span>
<?= form_input([
'name' => 'close_date',

View File

@@ -12,6 +12,11 @@
<?= view('partial/header') ?>
<?php
$title_info['config_title'] = 'Cashups';
echo view('configs/config_header', $title_info);
?>
<script type="text/javascript">
$(document).ready(function() {
// Load the preset datarange picker
@@ -46,29 +51,36 @@
<?= view('partial/print_receipt', ['print_after_sale' => false, 'selected_printer' => 'takings_printer']) ?>
<div id="title_bar" class="print_hide btn-toolbar">
<button onclick="printdoc()" class="btn btn-info btn-sm pull-right">
<span class="glyphicon glyphicon-print">&nbsp;</span><?= lang('Common.print') ?>
<div id="title_bar" class="d-flex gap-2 justify-content-end d-print-none">
<button type="button" class="btn btn-primary modal-launch" data-btn-submit="<?= lang('Common.submit') ?>" data-href="<?= "$controller_name/view" ?>" title="<?= lang(ucfirst($controller_name) . ".new") ?>">
<i class="bi bi-journal-check me-2"></i><?= lang(esc(ucfirst($controller_name)) . '.new') // TODO: String Interpolation ?>
</button>
<button class="btn btn-info btn-sm pull-right modal-dlg" data-btn-submit="<?= lang('Common.submit') ?>" data-href="<?= "$controller_name/view" ?>" title="<?= lang(ucfirst($controller_name) . ".new") ?>">
<span class="glyphicon glyphicon-tags">&nbsp;</span><?= lang(esc(ucfirst($controller_name)) . '.new') // TODO: String Interpolation ?>
<button type="button" class="btn btn-primary" onclick="window.print()" title="<?= lang('Common.print') ?>">
<i class="bi bi-printer me-2"></i><?= lang('Common.print') ?>
</button>
</div>
<div id="toolbar">
<div class="pull-left form-inline" role="toolbar">
<button id="delete" class="btn btn-default btn-sm print_hide">
<span class="glyphicon glyphicon-trash">&nbsp;</span><?= lang('Common.delete') ?>
<div class="d-flex gap-2">
<button type="button" id="delete" class="btn btn-secondary d-print-none">
<i class="bi bi-trash"></i><span class="d-none d-sm-inline ms-2"><?= lang('Common.delete') ?></span>
</button>
<?= form_input(['name' => 'daterangepicker', 'class' => 'form-control input-sm', 'id' => 'daterangepicker']) ?>
<?= form_multiselect('filters[]', $filters, $selected_filters ?? [], [
'id' => 'filters',
'data-none-selected-text' => lang('Common.none_selected_text'),
'class' => 'selectpicker show-menu-arrow',
'data-selected-text-format' => 'count > 1',
'data-style' => 'btn-default btn-sm',
'data-width' => 'fit'
]) ?>
<div class="input-group w-auto">
<span class="input-group-text" id="daterangepicker-icon"><i class="bi bi-calendar2-range"></i></span>
<input type="text" class="form-select" name="daterangepicker" id="daterangepicker" aria-describedby="daterangepicker-icon">
</div>
<div class="input-group w-auto">
<span class="input-group-text" id="filters-icon"><i class="bi bi-funnel"></i></span>
<select class="form-select" name="filters[]" id="filters" aria-describedby="filters-icon" multiple>
<?php foreach ($filters as $key => $label): ?>
<option value="<?= $key ?>" <?= in_array($key, $selected_filters ?? []) ? 'selected' : '' ?>>
<?= esc($label) ?>
</option>
<?php endforeach; ?>
</select>
</div>
</div>
</div>
@@ -77,3 +89,15 @@
</div>
<?= view('partial/footer') ?>
<script type="text/javascript">
new TomSelect('#filters', {
plugins: ['checkbox_options', 'remove_button'],
placeholder: '<?= lang('Common.none_selected_text') ?>',
hidePlaceholder: true,
closeAfterSelect: false,
onChange: function() {
$('#table').bootstrapTable('refresh');
}
});
</script>

View File

@@ -0,0 +1,124 @@
<?php
/**
*
*/
$beta = '<sup><span class="badge bg-secondary">BETA</span></sup>';
?>
<?= form_open('config/saveAppearance/', ['id' => 'appearance_config_form']) ?>
<?php
$title_info['config_title'] = 'Appearance';
echo view('configs/config_header', $title_info);
?>
<ul id="error_message_box" class="appearance_error_message_box alert alert-warning d-none"></ul>
<div class="row">
<div class="col-12 col-lg-6">
<label for="theme-change" class="form-label"><?= lang('Config.theme'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-binoculars"></i></span>
<select class="form-select" name="theme" id="theme-change">
<?php foreach ($themes as $value => $display): ?>
<option value="<?= $value ?>" <?= $config['theme'] == $value ? 'selected' : '' ?>><?= $display ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="col-12 col-lg-6">
<label for="login_form" class="form-label"><?= lang('Config.login_form'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-view-stacked"></i></span>
<select class="form-select" name="login_form" id="login_form">
<option value="floating_labels" <?= $config['login_form'] == 'floating_labels' ? 'selected' : '' ?>><?= lang('Config.floating_labels') ?></option>
<option value="input_groups" <?= $config['login_form'] == 'input_groups' ? 'selected' : '' ?>><?= lang('Config.input_groups') ?></option>
</select>
</div>
</div>
<div class="col-12 col-lg-6">
<label for="color_mode" class="form-label">Color Mode <?= $beta; ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="color-mode-icon"><i class="bi bi-palette"></i></span>
<select class="form-select" id="color_mode" name="color_mode" aria-describedby="color-mode-icon">
<option value="light" <?= $config['color_mode'] == 'light' ? 'selected' : '' ?>>Light</option>
<option value="dark" <?= $config['color_mode'] == 'dark' ? 'selected' : '' ?>>Dark</option>
</select>
</div>
</div>
<div class="col-12 col-lg-6">
<label for="notify_position" class="form-label"><?= lang('Config.notify_alignment'); ?></label>
<div class="row" id="notify_position">
<div class="col-6 mb-3">
<div class="input-group">
<span class="input-group-text"><i class="bi bi-arrow-down-up"></i></span>
<select class="form-select" name="notify_vertical_position">
<option value="top" <?= $config['notify_vertical_position'] == 'top' ? 'selected' : '' ?>><?= lang('Config.top') ?></option>
<option value="bottom" <?= $config['notify_vertical_position'] == 'bottom' ? 'selected' : '' ?>><?= lang('Config.bottom') ?></option>
</select>
</div>
</div>
<div class="col-6 mb-3">
<div class="input-group">
<span class="input-group-text"><i class="bi bi-arrow-left-right"></i></span>
<select class="form-select" name="notify_horizontal_position">
<option value="left" <?= $config['notify_horizontal_position'] == 'left' ? 'selected' : '' ?>><?= lang('Config.left') ?></option>
<option value="center" <?= $config['notify_horizontal_position'] == 'center' ? 'selected' : '' ?>><?= lang('Config.center') ?></option>
<option value="right" <?= $config['notify_horizontal_position'] == 'right' ? 'selected' : '' ?>><?= lang('Config.right') ?></option>
</select>
</div>
</div>
</div>
</div>
<div class="col-12 col-lg-6">
<label for="config_menu_position" class="form-label">Configuration Menu Position</label>
<div class="input-group mb-3">
<span class="input-group-text" id="config-menu-position-icon"><i class="bi bi-distribute-horizontal"></i></span>
<select class="form-select" id="config_menu_position" name="config_menu_position" aria-describedby="config-menu-position-icon">
<option value="start" <?= $config['config_menu_position'] == 'start' ? 'selected' : '' ?>>Start</option>
<option value="end" <?= $config['config_menu_position'] == 'end' ? 'selected' : '' ?>>End</option>
</select>
</div>
</div>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="responsive_design" name="responsive_design" value="responsive_design" <?= $config['responsive_design'] == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="responsive_design">Responsive Design <?= $beta; ?></label>
</div>
<div class="d-flex justify-content-end">
<button type="submit" class="btn btn-primary" name="submit_appearance"><?= lang('Common.submit'); ?></button>
</div>
<?= form_close() ?>
<script type="application/javascript">
// Validation and submit handling
$(document).ready(function() {
$('#appearance_config_form').validate($.extend(form_support.handler, {
submitHandler: function(form) {
$(form).ajaxSubmit({
success: function(response) {
$.notify({
icon: 'bi bi-bell-fill',
message: response.message + '&nbsp;<em>Click to refresh.</em>',
url: 'javascript:window.location.reload();',
target: '_self'
}, {
type: response.success ? 'success' : 'danger'
})
},
dataType: 'json'
});
},
errorLabelContainer: '.appearance_error_message_box'
}));
});
</script>

View File

@@ -6,251 +6,194 @@
*/
?>
<?= form_open('config/saveBarcode/', ['id' => 'barcode_config_form', 'class' => 'form-horizontal']) ?>
<div id="config_wrapper">
<fieldset id="config_info">
<?= form_open('config/saveBarcode/', ['id' => 'barcode_config_form']) ?>
<div id="required_fields_message"><?= lang('Common.fields_required_message') ?></div>
<ul id="barcode_error_message_box" class="error_message_box"></ul>
<?php
$title_info['config_title'] = lang('Config.barcode_configuration');
echo view('configs/config_header', $title_info);
?>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.barcode_type'), 'barcode_type', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_dropdown(
'barcode_type',
$support_barcode,
$config['barcode_type'],
'class="form-control input-sm"'
) ?>
</div>
<ul id="error_message_box" class="barcode_error_message_box alert alert-warning d-none"></ul>
<div class="row">
<div class="col-12 col-lg-6">
<label for="barcode_type" class="form-label"><?= lang('Config.barcode_type'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-braces"></i></span>
<select class="form-select" name="barcode_type" id="barcode_type">
<?php foreach ($support_barcode as $key => $value): ?>
<option value="<?= $key ?>" <?= $config['barcode_type'] == $key ? 'selected' : '' ?>><?= $value ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.barcode_width'), 'barcode_width', ['class' => 'control-label col-xs-2 required']) ?>
<div class="col-xs-2">
<?= form_input([
'step' => '5',
'max' => '350',
'min' => '60',
'type' => 'number',
'name' => 'barcode_width',
'id' => 'barcode_width',
'class' => 'form-control input-sm required',
'value' => $config['barcode_width']
]) ?>
</div>
<div class="col-6 col-lg-3">
<label for="barcode_width" class="form-label"><?= lang('Config.barcode_width'); ?><sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-arrows"></i></span>
<input type="number" class="form-control" step="5" max="350" min="60" name="barcode_width" id="barcode_width" value="<?= $config['barcode_width'] ?>" required>
<span class="input-group-text">px</span>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.barcode_height'), 'barcode_height', ['class' => 'control-label col-xs-2 required']) ?>
<div class="col-xs-2">
<?= form_input([
'type' => 'number',
'min' => 10,
'max' => 120,
'name' => 'barcode_height',
'id' => 'barcode_height',
'class' => 'form-control input-sm required',
'value' => $config['barcode_height']
]) ?>
</div>
<div class="col-6 col-lg-3">
<label for="barcode_height" class="form-label"><?= lang('Config.barcode_height'); ?><sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-arrows-vertical"></i></span>
<input type="number" class="form-control" min="10" max="120" name="barcode_height" id="barcode_height" value="<?= $config['barcode_height'] ?>" required>
<span class="input-group-text">px</span>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.barcode_font'), 'barcode_font', ['class' => 'control-label col-xs-2 required']) ?>
<div class="col-sm-2">
<?= form_dropdown(
'barcode_font',
$barcode_fonts,
$config['barcode_font'],
'class="form-control input-sm" required'
) ?>
</div>
<div class="col-sm-2">
<?= form_input([
'type' => 'number',
'min' => '1',
'max' => '30',
'name' => 'barcode_font_size',
'id' => 'barcode_font_size',
'class' => 'form-control input-sm required',
'value' => $config['barcode_font_size']
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.allow_duplicate_barcodes'), 'allow_duplicate_barcodes', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-1">
<?= form_checkbox([
'name' => 'allow_duplicate_barcodes',
'id' => 'allow_duplicate_barcodes',
'value' => 'allow_duplicate_barcodes',
'checked' => $config['allow_duplicate_barcodes'] == 1
]) ?>
&nbsp;
<label class="control-label">
<span class="glyphicon glyphicon-warning-sign" data-toggle="tooltip" data-placement="right" title="<?= lang('Config.barcode_tooltip') ?>"></span>
</label>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.barcode_content'), 'barcode_content', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-8">
<label class="radio-inline">
<?= form_radio([
'name' => 'barcode_content',
'value' => 'id',
'checked' => $config['barcode_content'] == 'id'
]) ?>
<?= lang('Config.barcode_id') ?>
</label>
<label class="radio-inline">
<?= form_radio([
'name' => 'barcode_content',
'value' => 'number',
'checked' => $config['barcode_content'] == 'number'
]) ?>
<?= lang('Config.barcode_number') ?>
</label>
&nbsp;
&nbsp;
<label class="checkbox-inline">
<?= form_checkbox([
'name' => 'barcode_generate_if_empty',
'value' => 'barcode_generate_if_empty',
'checked' => $config['barcode_generate_if_empty'] == 1
]) ?>
<?= lang('Config.barcode_generate_if_empty') ?>
</label>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.barcode_formats'), 'barcode_formats', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-4">
<?php
$barcode_formats = json_decode(config('OSPOS')->settings['barcode_formats']);
echo form_dropdown([
'name' => 'barcode_formats[]',
'id' => 'barcode_formats',
'options' => !empty($barcode_formats) ? array_combine($barcode_formats, $barcode_formats) : [],
'multiple' => 'multiple',
'data-role' => 'tagsinput'
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.barcode_layout'), 'barcode_layout', ['class' => 'control-label col-xs-2']) ?>
<div class="col-sm-10">
<div class="form-group form-group-sm row">
<label class="control-label col-sm-1"><?= lang('Config.barcode_first_row') . ' ' ?></label>
<div class="col-sm-2">
<?= form_dropdown(
'barcode_first_row',
[
'not_show' => lang('Config.none'),
'name' => lang('Items.name'),
'category' => lang('Items.category'),
'cost_price' => lang('Items.cost_price'),
'unit_price' => lang('Items.unit_price'),
'company_name' => lang('Suppliers.company_name')
],
$config['barcode_first_row'],
['class' => 'form-control input-sm']
); ?>
</div>
<label class="control-label col-sm-1"><?= lang('Config.barcode_second_row') . ' ' ?></label>
<div class="col-sm-2">
<?= form_dropdown(
'barcode_second_row',
[
'not_show' => lang('Config.none'),
'name' => lang('Items.name'),
'category' => lang('Items.category'),
'cost_price' => lang('Items.cost_price'),
'unit_price' => lang('Items.unit_price'),
'item_code' => lang('Items.item_number'),
'company_name' => lang('Suppliers.company_name')
],
$config['barcode_second_row'],
['class' => 'form-control input-sm']
) ?>
</div>
<label class="control-label col-sm-1"><?= lang('Config.barcode_third_row') . ' ' ?></label>
<div class="col-sm-2">
<?= form_dropdown(
'barcode_third_row',
[
'not_show' => lang('Config.none'),
'name' => lang('Items.name'),
'category' => lang('Items.category'),
'cost_price' => lang('Items.cost_price'),
'unit_price' => lang('Items.unit_price'),
'item_code' => lang('Items.item_number'),
'company_name' => lang('Suppliers.company_name')
],
$config['barcode_third_row'],
['class' => 'form-control input-sm']
) ?>
</div>
</div>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.barcode_number_in_row'), 'barcode_num_in_row', ['class' => 'control-label col-xs-2 required']) ?>
<div class="col-xs-2">
<?= form_input([
'name' => 'barcode_num_in_row',
'id' => 'barcode_num_in_row',
'class' => 'form-control input-sm required',
'value' => $config['barcode_num_in_row']
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.barcode_page_width'), 'barcode_page_width', ['class' => 'control-label col-xs-2 required']) ?>
<div class="col-sm-2">
<div class="input-group">
<?= form_input([
'name' => 'barcode_page_width',
'id' => 'barcode_page_width',
'class' => 'form-control input-sm required',
'value' => $config['barcode_page_width']
]) ?>
<span class="input-group-addon input-sm">%</span>
</div>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.barcode_page_cellspacing'), 'barcode_page_cellspacing', ['class' => 'control-label col-xs-2 required']) ?>
<div class="col-sm-2">
<div class="input-group">
<?= form_input([
'name' => 'barcode_page_cellspacing',
'id' => 'barcode_page_cellspacing',
'class' => 'form-control input-sm required',
'value' => $config['barcode_page_cellspacing']
]) ?>
<span class="input-group-addon input-sm">px</span>
</div>
</div>
</div>
<?= form_submit([
'name' => 'submit_barcode',
'id' => 'submit_barcode',
'value' => lang('Common.submit'),
'class' => 'btn btn-primary btn-sm pull-right'
]) ?>
</fieldset>
</div>
</div>
<div class="row">
<div class="col-6 col-lg-3">
<label for="barcode_font" class="form-label"><?= lang('Config.barcode_font'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-fonts"></i></span>
<select class="form-select" id="barcode_font" name="barcode_font" required>
<?php foreach ($barcode_fonts as $key => $value): ?>
<option value="<?= $key ?>" <?= $config['barcode_font'] == $key ? 'selected' : '' ?>><?= $value ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="col-6 col-lg-3">
<label for="barcode_font_size" class="form-label">Font Size<sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-arrows-angle-expand"></i></span>
<input type="number" class="form-control" min="1" max="30" name="barcode_font_size" id="barcode_font_size" value="<?= $config['barcode_font_size'] ?>" required>
<span class="input-group-text">px</span>
</div>
</div>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="allow_duplicate_barcodes" name="allow_duplicate_barcodes" value="allow_duplicate_barcodes" <?= $config['allow_duplicate_barcodes'] == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="allow_duplicate_barcodes"><?= lang('Config.allow_duplicate_barcodes'); ?></label>
<div class="form-text"><i class="bi bi-info-square pe-1"></i><?= lang('Config.barcode_tooltip') ?></div>
</div>
<label for="barcode_content" class="form-label"><?= lang('Config.barcode_content'); ?></label>
<div class="row mb-3">
<div class="col-12">
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="barcode_content" id="barcode_content_id" value="id" <?= $config['barcode_content'] == 'id' ? 'checked' : '' ?>>
<label class="form-check-label" for="barcode_content_id"><?= lang('Config.barcode_id') ?></label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="barcode_content" id="barcode_content_number" value="number" <?= $config['barcode_content'] == 'number' ? 'checked' : '' ?>>
<label class="form-check-label" for="barcode_content_number"><?= lang('Config.barcode_number') ?></label>
</div>
<div class="form-check form-check-inline form-switch">
<input class="form-check-input" type="checkbox" role="switch" id="barcode_generate_if_empty" name="barcode_generate_if_empty" value="barcode_generate_if_empty" <?= $config['barcode_generate_if_empty'] == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="barcode_generate_if_empty"><?= lang('Config.barcode_generate_if_empty'); ?></label>
</div>
</div>
</div>
<div class="row">
<div class="col-12 col-lg-6">
<label for="barcode_formats" class="form-label"><?= lang('Config.barcode_formats'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-code-square"></i></span>
<!-- <?php
$barcode_formats = json_decode(config('OSPOS')->settings['barcode_formats']);
$options = !empty($barcode_formats) ? array_combine($barcode_formats, $barcode_formats) : [];
?>
<select class="form-select" id="barcode_formats" name="barcode_formats[]" data-role="tagsinput" multiple>
<?php foreach ($options as $value): ?>
<option value="<?= $value ?>" <?= in_array($value, $barcode_formats) ? 'selected' : '' ?>><?= $value ?></option>
<?php endforeach; ?>
</select> -->
<input type="text" class="form-control" disabled>
</div>
</div>
</div>
<div class="row">
<label for="barcode_layout" class="form-label"><?= lang('Config.barcode_layout'); ?></label>
<div class="col-6 col-lg-3">
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-1-square"></i></span>
<select name="barcode_first_row" class="form-select">
<option value="not_show" <?= $config['barcode_first_row'] == 'not_show' ? 'selected' : '' ?>><?= lang('Config.none') ?></option>
<option value="name" <?= $config['barcode_first_row'] == 'name' ? 'selected' : '' ?>><?= lang('Items.name') ?></option>
<option value="category" <?= $config['barcode_first_row'] == 'category' ? 'selected' : '' ?>><?= lang('Items.category') ?></option>
<option value="cost_price" <?= $config['barcode_first_row'] == 'cost_price' ? 'selected' : '' ?>><?= lang('Items.cost_price') ?></option>
<option value="unit_price" <?= $config['barcode_first_row'] == 'unit_price' ? 'selected' : '' ?>><?= lang('Items.unit_price') ?></option>
<option value="company_name" <?= $config['barcode_first_row'] == 'company_name' ? 'selected' : '' ?>><?= lang('Suppliers.company_name') ?></option>
</select>
</div>
</div>
<div class="col-6 col-lg-3">
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-2-square"></i></span>
<select name="barcode_second_row" class="form-select">
<option value="not_show" <?= $config['barcode_second_row'] == 'not_show' ? 'selected' : '' ?>><?= lang('Config.none') ?></option>
<option value="name" <?= $config['barcode_second_row'] == 'name' ? 'selected' : '' ?>><?= lang('Items.name') ?></option>
<option value="category" <?= $config['barcode_second_row'] == 'category' ? 'selected' : '' ?>><?= lang('Items.category') ?></option>
<option value="cost_price" <?= $config['barcode_second_row'] == 'cost_price' ? 'selected' : '' ?>><?= lang('Items.cost_price') ?></option>
<option value="unit_price" <?= $config['barcode_second_row'] == 'unit_price' ? 'selected' : '' ?>><?= lang('Items.unit_price') ?></option>
<option value="item_code" <?= $config['barcode_second_row'] == 'item_code' ? 'selected' : '' ?>><?= lang('Items.item_number') ?></option>
<option value="company_name" <?= $config['barcode_second_row'] == 'company_name' ? 'selected' : '' ?>><?= lang('Suppliers.company_name') ?></option>
</select>
</div>
</div>
<div class="col-6 col-lg-3">
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-3-square"></i></span>
<select name="barcode_third_row" class="form-select">
<option value="not_show" <?= $config['barcode_third_row'] == 'not_show' ? 'selected' : '' ?>><?= lang('Config.none') ?></option>
<option value="name" <?= $config['barcode_third_row'] == 'name' ? 'selected' : '' ?>><?= lang('Items.name') ?></option>
<option value="category" <?= $config['barcode_third_row'] == 'category' ? 'selected' : '' ?>><?= lang('Items.category') ?></option>
<option value="cost_price" <?= $config['barcode_third_row'] == 'cost_price' ? 'selected' : '' ?>><?= lang('Items.cost_price') ?></option>
<option value="unit_price" <?= $config['barcode_third_row'] == 'unit_price' ? 'selected' : '' ?>><?= lang('Items.unit_price') ?></option>
<option value="item_code" <?= $config['barcode_third_row'] == 'item_code' ? 'selected' : '' ?>><?= lang('Items.item_number') ?></option>
<option value="company_name" <?= $config['barcode_third_row'] == 'company_name' ? 'selected' : '' ?>><?= lang('Suppliers.company_name') ?></option>
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-6 col-lg-3">
<label for="barcode_num_in_row" class="form-label"><?= lang('Config.barcode_number_in_row'); ?><sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-123"></i></span>
<input type="number" name="barcode_num_in_row" id="barcode_num_in_row" class="form-control" value="<?= $config['barcode_num_in_row'] ?>" required>
</div>
</div>
<div class="col-6 col-lg-3">
<label for="barcode_page_width" class="form-label"><?= lang('Config.barcode_page_width'); ?><sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-arrows"></i></span>
<input type="number" min="0" max="100" name="barcode_page_width" id="barcode_page_width" class="form-control" value="<?= $config['barcode_page_width'] ?>" required>
<span class="input-group-text"><i class="bi bi-percent"></i></span>
</div>
</div>
<div class="col-6 col-lg-3">
<label for="barcode_page_cellspacing" class="form-label"><?= lang('Config.barcode_page_cellspacing'); ?><sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-distribute-horizontal"></i></span>
<input type="number" name="barcode_page_cellspacing" id="barcode_page_cellspacing" class="form-control" value="<?= $config['barcode_page_cellspacing'] ?>" required>
<span class="input-group-text">px</span>
</div>
</div>
</div>
<div class="d-flex justify-content-end">
<button type="submit" class="btn btn-primary" name="submit_barcode"><?= lang('Common.submit'); ?></button>
</div>
<?= form_close() ?>
<script type="text/javascript">
@@ -258,7 +201,7 @@
$(document).ready(function() {
$('#barcode_config_form').validate($.extend(form_support.handler, {
errorLabelContainer: "#barcode_error_message_box",
errorLabelContainer: ".barcode_error_message_box",
rules: {
barcode_width: {

View File

@@ -0,0 +1,5 @@
<div class="d-flex">
<h4 class="flex-grow-1 fw-bold"><?= $config_title; ?></h4>
<h5 class="link-secondary d-print-none" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Learn more in our docs"><i class="bi bi-journal-arrow-up"></i></h5>
</div>
<hr class="mt-0 d-print-none">

View File

@@ -4,136 +4,85 @@
*/
?>
<?= form_open('config/saveEmail/', ['id' => 'email_config_form', 'enctype' => 'multipart/form-data', 'class' => 'form-horizontal']) ?>
<div id="config_wrapper">
<fieldset id="config_info">
<?= form_open('config/saveEmail/', ['id' => 'email_config_form', 'enctype' => 'multipart/form-data']) ?>
<div id="required_fields_message"><?= lang('Common.fields_required_message') ?></div>
<ul id="email_error_message_box" class="error_message_box"></ul>
<?php
$title_info['config_title'] = lang('Config.email_configuration');
echo view('configs/config_header', $title_info);
?>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.email_protocol'), 'protocol', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_dropdown(
'protocol',
[
'mail' => 'mail',
'sendmail' => 'sendmail',
'smtp' => 'smtp'
],
$config['protocol'],
'class="form-control input-sm" id="protocol"'
) ?>
</div>
<ul id="error_message_box" class="email_error_message_box alert alert-warning d-none"></ul>
<div class="row">
<div class="col-12 col-lg-6">
<label for="protocol" class="form-label"><?= lang('Config.email_protocol'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-mailbox"></i></span>
<?= form_dropdown('protocol', array('mail' => 'Mail', 'sendmail' => 'Sendmail', 'smtp' => 'SMTP'), $config['protocol'], array('class' => 'form-select', 'id' => 'protocol')); ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.email_mailpath'), 'mailpath', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-4">
<?= form_input([
'name' => 'mailpath',
'id' => 'mailpath',
'class' => 'form-control input-sm',
'value' => $config['mailpath']
]) ?>
</div>
<div class="col-12 col-lg-6">
<label for="mailpath" class="form-label"><?= lang('Config.email_mailpath'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-braces"></i></span>
<input type="text" name="mailpath" class="form-control" id="mailpath" value="<?= $config['mailpath']; ?>">
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.email_smtp_host'), 'smtp_host', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_input([
'name' => 'smtp_host',
'id' => 'smtp_host',
'class' => 'form-control input-sm',
'value' => $config['smtp_host']
]) ?>
</div>
<div class="col-12 col-lg-6">
<label for="smtp_host" class="form-label"><?= lang('Config.email_smtp_host'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-database"></i></span>
<input type="text" name="smtp_host" class="form-control" id="smtp_host" value="<?= $config['smtp_host']; ?>">
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.email_smtp_port'), 'smtp_port', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_input([
'name' => 'smtp_port',
'id' => 'smtp_port',
'class' => 'form-control input-sm',
'value' => $config['smtp_port']
]) ?>
</div>
<div class="col-12 col-lg-6">
<label for="smtp_port" class="form-label"><?= lang('Config.email_smtp_port'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-door-open"></i></span>
<input type="number" name="smtp_port" class="form-control" id="smtp_port" value="<?= $config['smtp_port']; ?>">
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.email_smtp_crypto'), 'smtp_crypto', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_dropdown(
'smtp_crypto',
[
'' => 'None',
'tls' => 'TLS',
'ssl' => 'SSL'
],
$config['smtp_crypto'],
'class="form-control input-sm" id="smtp_crypto"'
) ?>
</div>
<div class="col-12 col-lg-6">
<label for="smtp_crypto" class="form-label"><?= lang('Config.email_smtp_crypto'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-shield-lock"></i></span>
<?= form_dropdown('smtp_crypto', array('' => 'None', 'tls' => 'TLS', 'ssl' => 'SSL'), $config['smtp_crypto'], array('class' => 'form-select', 'id' => 'smtp_crypto')); ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.email_smtp_timeout'), 'smtp_timeout', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_input([
'name' => 'smtp_timeout',
'id' => 'smtp_timeout',
'class' => 'form-control input-sm',
'value' => $config['smtp_timeout']
]) ?>
</div>
<div class="col-12 col-lg-6">
<label for="smtp_timeout" class="form-label"><?= lang('Config.email_smtp_timeout'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-stopwatch"></i></span>
<input type="number" name="smtp_timeout" class="form-control" id="smtp_timeout" value="<?= $config['smtp_timeout']; ?>">
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.email_smtp_user'), 'smtp_user', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-4">
<div class="input-group">
<span class="input-group-addon input-sm">
<span class="glyphicon glyphicon-user"></span>
</span>
<?= form_input([
'name' => 'smtp_user',
'id' => 'smtp_user',
'class' => 'form-control input-sm',
'value' => $config['smtp_user']
]) ?>
</div>
</div>
<div class="col-12 col-lg-6">
<label for="smtp_user" class="form-label"><?= lang('Config.email_smtp_user'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-person"></i></span>
<input type="text" name="smtp_user" class="form-control" id="smtp_user" value="<?= $config['smtp_user']; ?>">
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.email_smtp_pass'), 'smtp_pass', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-4">
<div class="input-group">
<span class="input-group-addon input-sm">
<span class="glyphicon glyphicon-asterisk"></span>
</span>
<?= form_password([
'name' => 'smtp_pass',
'id' => 'smtp_pass',
'class' => 'form-control input-sm',
'value' => $config['smtp_pass']
]) ?>
</div>
</div>
<div class="col-12 col-lg-6">
<label for="smtp_pass" class="form-label"><?= lang('Config.email_smtp_pass'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-lock"></i></span>
<input type="password" name="smtp_pass" class="form-control" id="smtp_pass" value="<?= $config['smtp_pass']; ?>">
</div>
<?= form_submit([
'name' => 'submit_email',
'id' => 'submit_email',
'value' => lang('Common.submit'),
'class' => 'btn btn-primary btn-sm pull-right'
]) ?>
</fieldset>
</div>
</div>
<div class="d-flex justify-content-end">
<button type="submit" class="btn btn-primary" name="submit_email"><?= lang('Common.submit'); ?></button>
</div>
<?= form_close() ?>
<script type="text/javascript">
@@ -162,6 +111,7 @@
},
success: function(response) {
$.notify({
icon: 'bi bi-bell-fill',
message: response.message
}, {
type: response.success ? 'success' : 'danger'
@@ -173,7 +123,7 @@
});
},
errorLabelContainer: '#email_error_message_box'
errorLabelContainer: '.email_error_message_box'
}));
});
</script>

View File

@@ -9,459 +9,209 @@
*/
?>
<?= form_open('config/saveGeneral/', ['id' => 'general_config_form', 'enctype' => 'multipart/form-data', 'class' => 'form-horizontal']) ?>
<div id="config_wrapper">
<fieldset id="config_info">
<?= form_open('config/saveGeneral/', ['id' => 'general_config_form', 'enctype' => 'multipart/form-data']) ?>
<div id="required_fields_message"><?= lang('Common.fields_required_message') ?></div>
<ul id="general_error_message_box" class="error_message_box"></ul>
<?php
$title_info['config_title'] = lang('Config.general_configuration');
echo view('configs/config_header', $title_info);
?>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.theme'), 'theme', ['class' => 'control-label col-xs-2']) ?>
<div class="col-sm-10">
<div class="form-group form-group-sm row">
<div class="col-sm-3">
<?= form_dropdown(
'theme',
$themes,
$config['theme'],
'class="form-control input-sm" id="theme-change"'
) ?>
</div>
<div class="col-sm-7">
<a href="<?= 'https://bootswatch.com/3/' . ('bootstrap' == ($config['theme']) ? 'default' : esc($config['theme'])) ?>" target="_blank" rel=”noopener”>
<span><?= lang('Config.theme_preview') . ' ' . ucfirst(esc($config['theme'])) . ' ' ?></span>
<span class="glyphicon glyphicon-new-window"></span>
</a>
</div>
</div>
</div>
<ul id="error_message_box" class="general_error_message_box alert alert-warning d-none"></ul>
<div class="row">
<div class="col-12 col-sm-6 col-xxl-3">
<label for="default_sales_discount" class="form-label"><?= lang('Config.default_sales_discount') ?><sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-cart-dash"></i></span>
<input class="form-control" type="number" min="0" max="100" name="default_sales_discount" id="default_sales_discount" value="<?= $config['default_sales_discount'] ?>" required>
<input type="radio" class="btn-check" name="default_sales_discount_type" id="dsd_type_1" value="1" <?= $config['default_sales_discount_type'] == 1 ? 'checked' : '' ?>>
<label class="btn btn-outline-primary fw-semibold" for="dsd_type_1"><?= $config['currency_symbol'] ?></label>
<input type="radio" class="btn-check" name="default_sales_discount_type" id="dsd_type_0" value="0" <?= $config['default_sales_discount_type'] == 0 ? 'checked' : '' ?>>
<label class="btn btn-outline-primary fw-semibold" for="dsd_type_0">%</label>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.login_form'), 'login_form', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_dropdown(
'login_form',
[
'floating_labels' => lang('Config.floating_labels'),
'input_groups' => lang('Config.input_groups')
],
$config['login_form'],
'class="form-control input-sm"'
) ?>
</div>
<div class="col-12 col-sm-6 col-xxl-3">
<label for="default_receivings_discount" class="form-label"><?= lang('Config.default_receivings_discount') ?><sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-bag-dash"></i></span>
<input class="form-control" type="number" min="0" max="100" name="default_receivings_discount" id="default_receivings_discount" value="<?= $config['default_receivings_discount'] ?>" required>
<input type="radio" class="btn-check" name="default_receivings_discount_type" id="drd_type_1" value="1" <?= $config['default_receivings_discount_type'] == 1 ? 'checked' : '' ?>>
<label class="btn btn-outline-primary fw-semibold" for="drd_type_1"><?= $config['currency_symbol'] ?></label>
<input type="radio" class="btn-check" name="default_receivings_discount_type" id="drd_type_0" value="0" <?= $config['default_receivings_discount_type'] == 0 ? 'checked' : '' ?>>
<label class="btn btn-outline-primary fw-semibold" for="drd_type_0">%</label>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.default_sales_discount'), 'default_sales_discount', ['class' => 'control-label col-xs-2 required']) ?>
<div class="col-xs-2">
<div class="input-group">
<?= form_input([
'name' => 'default_sales_discount',
'id' => 'default_sales_discount',
'class' => 'form-control input-sm required',
'type' => 'number',
'min' => 0,
'max' => 100,
'value' => $config['default_sales_discount']
]) ?>
<span class="input-group-btn">
<?= form_checkbox([
'id' => 'default_sales_discount_type',
'name' => 'default_sales_discount_type',
'value' => 1,
'data-toggle' => 'toggle',
'data-size' => 'normal',
'data-onstyle' => 'success',
'data-on' => '<b>' . $config['currency_symbol'] . '</b>',
'data-off' => '<b>%</b>',
'checked' => $config['default_sales_discount_type'] == 1
]) ?>
</span>
</div>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.default_receivings_discount'), 'default_receivings_discount', ['class' => 'control-label col-xs-2 required']) ?>
<div class="col-xs-2">
<div class="input-group">
<?= form_input([
'name' => 'default_receivings_discount',
'id' => 'default_receivings_discount',
'class' => 'form-control input-sm required',
'type' => 'number',
'min' => 0,
'max' => 100,
'value' => $config['default_receivings_discount']
]) ?>
<span class="input-group-btn">
<?= form_checkbox([
'id' => 'default_receivings_discount_type',
'name' => 'default_receivings_discount_type',
'value' => 1,
'data-toggle' => 'toggle',
'data-size' => 'normal',
'data-onstyle' => 'success',
'data-on' => '<b>' . $config['currency_symbol'] . '</b>',
'data-off' => '<b>%</b>',
'checked' => $config['default_receivings_discount_type'] == 1
]) ?>
</span>
</div>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.enforce_privacy'), 'enforce_privacy', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-1">
<?= form_checkbox([
'name' => 'enforce_privacy',
'id' => 'enforce_privacy',
'value' => 'enforce_privacy',
'checked' => $config['enforce_privacy'] == 1
]) ?>
&nbsp;
<label class="control-label">
<span class="glyphicon glyphicon-info-sign" data-toggle="tooltip" data-placement="right" title="<?= lang('Config.enforce_privacy_tooltip') ?>"></span>
</label>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.receiving_calculate_average_price'), 'receiving_calculate_average_price', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-1">
<?= form_checkbox([
'name' => 'receiving_calculate_average_price',
'id' => 'receiving_calculate_average_price',
'value' => 'receiving_calculate_average_price',
'checked' => $config['receiving_calculate_average_price'] == 1
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.lines_per_page'), 'lines_per_page', ['class' => 'control-label col-xs-2 required']) ?>
<div class="col-xs-2">
<?= form_input([
'name' => 'lines_per_page',
'id' => 'lines_per_page',
'class' => 'form-control input-sm required',
'type' => 'number',
'min' => 10,
'max' => 1000,
'value' => $config['lines_per_page']
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.notify_alignment'), 'notify_horizontal_position', ['class' => 'control-label col-xs-2']) ?>
<div class="col-sm-10">
<div class="form-group form-group-sm row">
<div class="col-sm-2">
<?= form_dropdown(
'notify_vertical_position',
[
'top' => lang('Config.top'),
'bottom' => lang('Config.bottom')
],
$config['notify_vertical_position'],
'class="form-control input-sm"'
) ?>
</div>
<div class="col-sm-2">
<?= form_dropdown(
'notify_horizontal_position',
[
'left' => lang('Config.left'),
'center' => lang('Config.center'),
'right' => lang('Config.right')
],
$config['notify_horizontal_position'],
'class="form-control input-sm"'
) ?>
</div>
</div>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.image_restrictions'), 'image_restrictions', ['class' => 'control-label col-xs-2']) ?>
<div class="col-sm-10">
<div class="form-group form-group-sm row">
<div class="col-sm-2">
<div class="input-group">
<span class="input-group-addon input-sm">
<span class="glyphicon glyphicon-resize-horizontal"></span>
</span>
<?= form_input([
'name' => 'image_max_width',
'id' => 'image_max_width',
'class' => 'form-control input-sm required',
'type' => 'number',
'min' => 128,
'max' => 3840,
'value' => $config['image_max_width'],
'data-toggle' => 'tooltip',
'data-placement' => 'top',
'title' => lang('Config.image_max_width_tooltip')
]) ?>
</div>
</div>
<div class="col-sm-2">
<div class="input-group">
<span class="input-group-addon input-sm">
<span class="glyphicon glyphicon-resize-vertical"></span>
</span>
<?= form_input([
'name' => 'image_max_height',
'id' => 'image_max_height',
'class' => 'form-control input-sm required',
'type' => 'number',
'min' => 128,
'max' => 3840,
'value' => $config['image_max_height'],
'data-toggle' => 'tooltip',
'data-placement' => 'top',
'title' => lang('Config.image_max_height_tooltip')
]) ?>
</div>
</div>
<div class="col-sm-2">
<div class="input-group">
<span class="input-group-addon input-sm">
<span class="glyphicon glyphicon-hdd"></span>
</span>
<?= form_input([
'name' => 'image_max_size',
'id' => 'image_max_size',
'class' => 'form-control input-sm required',
'type' => 'number',
'min' => 128,
'max' => 2048,
'value' => $config['image_max_size'],
'data-toggle' => 'tooltip',
'data-placement' => 'top',
'title' => lang('Config.image_max_size_tooltip')
]) ?>
</div>
</div>
<div class="col-sm-4">
<div class="input-group">
<span class="input-group-addon input-sm"><?= lang('Config.image_allowed_file_types') ?></span>
<?= form_multiselect([
'name' => 'image_allowed_types[]',
'options' => $image_allowed_types,
'selected' => $selected_image_allowed_types,
'id' => 'image_allowed_types',
'class' => 'selectpicker show-menu-arrow',
'data-none-selected-text' => lang('Common.none_selected_text'),
'data-selected-text-format' => 'count > 1',
'data-style' => 'btn-default btn-sm',
'data-width' => '100%'
]) ?>
</div>
</div>
</div>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.gcaptcha_enable'), 'gcaptcha_enable', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-1">
<?= form_checkbox([
'name' => 'gcaptcha_enable',
'id' => 'gcaptcha_enable',
'value' => 'gcaptcha_enable',
'checked' => $config['gcaptcha_enable'] == 1
]) ?>
<label class="control-label">
<a href="https://www.google.com/recaptcha/admin" target="_blank">
<span class="glyphicon glyphicon-info-sign" data-toggle="tooltip" data-placement="right" title="<?= lang('Config.gcaptcha_tooltip') ?>"></span>
</a>
</label>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.gcaptcha_site_key'), 'config_gcaptcha_site_key', ['class' => 'required control-label col-xs-2', 'id' => 'config_gcaptcha_site_key']) ?>
<div class="col-xs-4">
<?= form_input([
'name' => 'gcaptcha_site_key',
'id' => 'gcaptcha_site_key',
'class' => 'form-control input-sm required',
'value' => $config['gcaptcha_site_key']
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.gcaptcha_secret_key'), 'config_gcaptcha_secret_key', ['class' => 'required control-label col-xs-2', 'id' => 'config_gcaptcha_secret_key']) ?>
<div class="col-xs-4">
<?= form_input([
'name' => 'gcaptcha_secret_key',
'id' => 'gcaptcha_secret_key',
'class' => 'form-control input-sm required',
'value' => $config['gcaptcha_secret_key']
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.suggestions_layout'), 'suggestions_layout', ['class' => 'control-label col-xs-2']) ?>
<div class="col-sm-10">
<div class="form-group form-group-sm row">
<div class="col-sm-3">
<div class="input-group">
<span class="input-group-addon input-sm"><?= lang('Config.suggestions_first_column') ?></span>
<?= form_dropdown(
'suggestions_first_column',
[
'name' => lang('Items.name'),
'item_number' => lang('Items.number_information'),
'unit_price' => lang('Items.unit_price'),
'cost_price' => lang('Items.cost_price')
],
$config['suggestions_first_column'],
'class="form-control input-sm"'
) ?>
</div>
</div>
<div class="col-sm-3">
<div class="input-group">
<span class="input-group-addon input-sm"><?= lang('Config.suggestions_second_column') ?></span>
<?= form_dropdown(
'suggestions_second_column',
[
'' => lang('Config.none'),
'name' => lang('Items.name'),
'item_number' => lang('Items.number_information'),
'unit_price' => lang('Items.unit_price'),
'cost_price' => lang('Items.cost_price')
],
$config['suggestions_second_column'],
'class="form-control input-sm"'
) ?>
</div>
</div>
<div class="col-sm-3">
<div class="input-group">
<span class="input-group-addon input-sm"><?= lang('Config.suggestions_third_column') ?></span>
<?= form_dropdown(
'suggestions_third_column',
[
'' => lang('Config.none'),
'name' => lang('Items.name'),
'item_number' => lang('Items.number_information'),
'unit_price' => lang('Items.unit_price'),
'cost_price' => lang('Items.cost_price')
],
$config['suggestions_third_column'],
'class="form-control input-sm"'
) ?>
</div>
</div>
</div>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.giftcard_number'), 'giftcard_number', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-8">
<label class="radio-inline">
<?= form_radio([
'name' => 'giftcard_number',
'value' => 'series',
'checked' => $config['giftcard_number'] == 'series'
]) ?>
<?= lang('Config.giftcard_series') ?>
</label>
<label class="radio-inline">
<?= form_radio([
'name' => 'giftcard_number',
'value' => 'random',
'checked' => $config['giftcard_number'] == 'random'
]) ?>
<?= lang('Config.giftcard_random') ?>
</label>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.derive_sale_quantity'), 'derive_sale_quantity', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-1">
<?= form_checkbox([
'name' => 'derive_sale_quantity',
'id' => 'derive_sale_quantity',
'value' => 'derive_sale_quantity',
'checked' => $config['derive_sale_quantity'] == 1
]) ?>
&nbsp;
<label class="control-label">
<span class="glyphicon glyphicon-info-sign" data-toggle="tooltip" data-placement="right" title="<?= lang('Config.derive_sale_quantity_tooltip') ?>"></span>
</label>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.show_office_group'), 'show_office_group', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-1">
<?= form_checkbox([
'name' => 'show_office_group',
'id' => 'show_office_group',
'value' => 'show_office_group',
'checked' => $show_office_group > 0
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.multi_pack_enabled'), 'multi_pack_enabled', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-1">
<?= form_checkbox([
'name' => 'multi_pack_enabled',
'id' => 'multi_pack_enabled',
'value' => 'multi_pack_enabled',
'checked' => $config['multi_pack_enabled'] == 1
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.include_hsn'), 'include_hsn', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-1">
<?= form_checkbox([
'name' => 'include_hsn',
'id' => 'include_hsn',
'value' => 'include_hsn',
'checked' => $config['include_hsn'] == 1
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.category_dropdown'), 'category_dropdown', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-1">
<?= form_checkbox([
'name' => 'category_dropdown',
'id' => 'category_dropdown',
'value' => 'category_dropdown',
'checked' => $config['category_dropdown'] == 1
]) ?>
</div>
</div>
<?= form_submit([
'name' => 'submit_general',
'id' => 'submit_general',
'value' => lang('Common.submit'),
'class' => 'btn btn-primary btn-sm pull-right'
]) ?>
</fieldset>
</div>
</div>
<div class="row">
<div class="col-12 col-sm-6 col-xxl-3">
<label for="lines_per_page" class="form-label"><?= lang('Config.lines_per_page'); ?><sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-list"></i></span>
<input type="number" min="10" max="1000" name="lines_per_page" class="form-control" id="lines_per_page" value="<?= $config['lines_per_page']; ?>" required>
</div>
</div>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="enforce_privacy" name="enforce_privacy" <?= $config['enforce_privacy'] == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="enforce_privacy"><?= lang('Config.enforce_privacy'); ?></label>
<div class="form-text"><i class="bi bi-info-square pe-1"></i><?= lang('Config.enforce_privacy_tooltip') ?></div>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="receiving_calculate_average_price" name="receiving_calculate_average_price" <?= $config['receiving_calculate_average_price'] == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="receiving_calculate_average_price"><?= lang('Config.receiving_calculate_average_price'); ?></label>
</div>
<div class="row">
<label class="form-label"><?= lang('Config.image_restrictions'); ?></label>
<div class="col-12 col-sm-6 col-xl-3">
<div class="input-group mb-3" data-bs-toggle="tooltip" title="<?= lang('Config.image_max_width_tooltip'); ?>">
<span class="input-group-text"><i class="bi bi-arrows"></i></span>
<input type="number" min="128" max="3840" name="image_max_width" id="image_max_width" class="form-control" value="<?= $config['image_max_width']; ?>" required>
<span class="input-group-text">px</span>
</div>
</div>
<div class="col-12 col-sm-6 col-xl-3">
<div class="input-group mb-3" data-bs-toggle="tooltip" title="<?= lang('Config.image_max_height_tooltip'); ?>">
<span class="input-group-text"><i class="bi bi-arrows-vertical"></i></span>
<input type="number" min="128" max="3840" name="image_max_height" id="image_max_height" class="form-control" value="<?= $config['image_max_height']; ?>" required>
<span class="input-group-text">px</span>
</div>
</div>
<div class="col-12 col-sm-6 col-xl-3">
<div class="input-group mb-3" data-bs-toggle="tooltip" title="<?= lang('Config.image_max_size_tooltip'); ?>">
<span class="input-group-text"><i class="bi bi-hdd"></i></span>
<input type="number" min="128" max="2048" name="image_max_size" id="image_max_size" class="form-control" value="<?= $config['image_max_size']; ?>" required>
<span class="input-group-text">kb</span>
</div>
</div>
<div class="col-12 col-sm-6 col-xl-3">
<div class="input-group mb-3" data-bs-toggle="tooltip" title="<?= lang('Config.image_allowed_file_types'); ?>">
<span class="input-group-text"><i class="bi bi-images"></i></span>
<select name="image_allowed_types[]" id="image_allowed_types" class="form-select" multiple placeholder="<?= lang('Config.image_allowed_file_types'); ?>" required>
<?php foreach($image_allowed_types as $type): ?>
<option value="<?= $type; ?>" <?= in_array($type, $selected_image_allowed_types) ? 'selected' : ''; ?>>
<?= $type; ?>
</option>
<?php endforeach; ?>
</select>
</div>
</div>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" name="gcaptcha_enable" id="gcaptcha_enable" value="gcaptcha_enable" <?= $config['gcaptcha_enable'] == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="gcaptcha_enable"><?= lang('Config.gcaptcha_enable') ?></label>
<a class="d-inline-block" href="https://google.com/recaptcha/admin" target="_blank" rel="noopener"><i class="bi bi-link-45deg link-secondary"></i></a>
<div class="form-text"><i class="bi bi-info-square pe-1"></i><?= lang('Config.gcaptcha_tooltip') ?></div>
</div>
<div class="row mb-3">
<div class="col-12 col-lg-6">
<label for="gcaptcha_site_key" class="form-label"><?= lang('Config.gcaptcha_site_key') ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-key"></i></span>
<input type="text" class="form-control" name="gcaptcha_site_key" id="gcaptcha_site_key" required>
</div>
</div>
<div class="col-12 col-lg-6">
<label for="gcaptcha_secret_key" class="form-label"><?= lang('Config.gcaptcha_secret_key') ?></label>
<div class="input-group">
<span class="input-group-text"><i class="bi bi-stars"></i></span>
<input type="text" class="form-control" name="gcaptcha_secret_key" id="gcaptcha_secret_key" required>
</div>
</div>
</div>
<div class="row" id="suggestions_layout">
<label for="suggestions_layout" class="form-label"><?= lang('Config.suggestions_layout'); ?></label>
<div class="col-12 col-sm-6 col-xl-4 col-xxl-3 mb-3">
<div class="input-group">
<span class="input-group-text"><i class="bi bi-layout-three-columns"></i>&nbsp;1.</span>
<select class="form-select" name="suggestions_first_column">
<option value="name" <?= $config['suggestions_first_column'] == 'name' ? 'selected' : '' ?>><?= lang('Items.name') ?></option>
<option value="item_number" <?= $config['suggestions_first_column'] == 'item_number' ? 'selected' : '' ?>><?= lang('Items.number_information') ?></option>
<option value="unit_price" <?= $config['suggestions_first_column'] == 'unit_price' ? 'selected' : '' ?>><?= lang('Items.unit_price') ?></option>
<option value="cost_price" <?= $config['suggestions_first_column'] == 'cost_price' ? 'selected' : '' ?>><?= lang('Items.cost_price') ?></option>
</select>
</div>
</div>
<div class="col-12 col-sm-6 col-xl-4 col-xxl-3 mb-3">
<div class="input-group">
<span class="input-group-text"><i class="bi bi-layout-three-columns"></i>&nbsp;2.</span>
<select class="form-select" name="suggestions_second_column">
<option value="" <?= $config['suggestions_second_column'] == null ? 'selected' : '' ?>><?= lang('Config.none') ?></option>
<option value="name" <?= $config['suggestions_second_column'] == 'name' ? 'selected' : '' ?>><?= lang('Items.name') ?></option>
<option value="item_number" <?= $config['suggestions_second_column'] == 'item_number' ? 'selected' : '' ?>><?= lang('Items.number_information') ?></option>
<option value="unit_price" <?= $config['suggestions_second_column'] == 'unit_price' ? 'selected' : '' ?>><?= lang('Items.unit_price') ?></option>
<option value="cost_price" <?= $config['suggestions_second_column'] == 'cost_price' ? 'selected' : '' ?>><?= lang('Items.cost_price') ?></option>
</select>
</div>
</div>
<div class="col-12 col-sm-6 col-xl-4 col-xxl-3 mb-3">
<div class="input-group">
<span class="input-group-text"><i class="bi bi-layout-three-columns"></i>&nbsp;3.</span>
<select class="form-select" name="suggestions_third_column">
<option value="" <?= $config['suggestions_third_column'] == null ? 'selected' : '' ?>><?= lang('Config.none') ?></option>
<option value="name" <?= $config['suggestions_third_column'] == 'name' ? 'selected' : '' ?>><?= lang('Items.name') ?></option>
<option value="item_number" <?= $config['suggestions_third_column'] == 'item_number' ? 'selected' : '' ?>><?= lang('Items.number_information') ?></option>
<option value="unit_price" <?= $config['suggestions_third_column'] == 'unit_price' ? 'selected' : '' ?>><?= lang('Items.unit_price') ?></option>
<option value="cost_price" <?= $config['suggestions_third_column'] == 'cost_price' ? 'selected' : '' ?>><?= lang('Items.cost_price') ?></option>
</select>
</div>
</div>
</div>
<label for="giftcard_number" class="form-label"><?= lang('Config.giftcard_number'); ?></label>
<div class="mb-3">
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="giftcard_number" id="giftcard_series" value="series" <?= $config['giftcard_number'] == 'series' ? 'checked' : '' ?>>
<label class="form-check-label" for="giftcard_series"><?= lang('Config.giftcard_series') ?></label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="giftcard_number" id="giftcard_random" value="random" <?= $config['giftcard_number'] == 'random' ? 'checked' : '' ?>>
<label class="form-check-label" for="giftcard_random"><?= lang('Config.giftcard_random') ?></label>
</div>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="derive_sale_quantity" name="derive_sale_quantity" value="derive_sale_quantity" <?= $config['derive_sale_quantity'] == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="derive_sale_quantity"><?= lang('Config.derive_sale_quantity'); ?></label>
<div class="form-text"><i class="bi bi-info-square pe-1"></i><?= lang('Config.derive_sale_quantity_tooltip') ?></div>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="show_office_group" name="show_office_group" value="show_office_group" <?= $show_office_group > 0 ? 'checked' : '' ?>>
<label class="form-check-label" for="show_office_group"><?= lang('Config.show_office_group'); ?></label>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="multi_pack_enabled" name="multi_pack_enabled" value="multi_pack_enabled" <?= $config['multi_pack_enabled'] == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="multi_pack_enabled"><?= lang('Config.multi_pack_enabled'); ?></label>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="include_hsn" name="include_hsn" value="include_hsn" <?= $config['include_hsn'] == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="include_hsn"><?= lang('Config.include_hsn'); ?></label>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="category_dropdown" name="category_dropdown" value="category_dropdown" <?= $config['category_dropdown'] == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="category_dropdown"><?= lang('Config.category_dropdown'); ?></label>
</div>
<div class="d-flex justify-content-end">
<button type="submit" class="btn btn-primary" name="submit_general"><?= lang('Common.submit'); ?></button>
</div>
<?= form_close() ?>
<script type="text/javascript">
@@ -484,7 +234,7 @@
$('#general_config_form').validate($.extend(form_support.handler, {
errorLabelContainer: "#general_error_message_box",
errorLabelContainer: ".general_error_message_box",
rules: {
lines_per_page: {
@@ -528,6 +278,7 @@
},
success: function(response) {
$.notify({
icon: 'bi bi-bell-fill',
message: response.message
}, {
type: response.success ? 'success' : 'danger'

View File

@@ -6,152 +6,110 @@
*/
?>
<?= form_open('config/saveInfo/', ['id' => 'info_config_form', 'enctype' => 'multipart/form-data', 'class' => 'form-horizontal']) ?>
<div id="config_wrapper">
<fieldset id="config_info">
<?= form_open('config/saveInfo/', ['id' => 'info_config_form', 'enctype' => 'multipart/form-data', 'class' => 'needs-validation']) ?> <!-- TODO-BS5 add is-invalid and invalid-feeback from BS5 to boxes -->
<div id="required_fields_message"><?= lang('Common.fields_required_message') ?></div>
<ul id="info_error_message_box" class="error_message_box"></ul>
<?php
$title_info['config_title'] = lang('Config.info_configuration');
echo view('configs/config_header', $title_info);
?>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.company'), 'company', ['class' => 'control-label col-xs-2 required']) ?>
<div class="col-xs-6">
<div class="input-group">
<span class="input-group-addon input-sm">
<span class="glyphicon glyphicon-home"></span>
</span>
<?= form_input([
'name' => 'company',
'id' => 'company',
'class' => 'form-control input-sm required',
'value' => $config['company']
]) ?>
</div>
</div>
<ul id="error_message_box" class="info_error_message_box alert alert-warning d-none"></ul>
<div class="row">
<div class="col-12 col-lg-6">
<label for="info-company" class="form-label"><?= lang('Config.company'); ?><sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-shop-window"></i></span>
<input type="text" class="form-control" name="company" id="info-company" value="<?= $config['company']; ?>" required> <!-- TODO-BS5 invalid-feedback makes input borders not rounded? -->
<div class="invalid-feedback"><?= lang('Config.company_required') ?></div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.company_logo'), 'company_logo', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-6">
<div class="fileinput <?= $logo_exists ? 'fileinput-exists' : 'fileinput-new' ?>" data-provides="fileinput">
<div class="fileinput-new thumbnail" style="width: 200px; height: 200px;"></div>
<div class="fileinput-preview fileinput-exists thumbnail" style="max-width: 200px; max-height: 200px;">
<img data-src="holder.js/100%x100%" alt="<?= esc(lang('Config.company_logo')) ?>" src="<?= $logo_src ?>" style="max-height: 100%; max-width: 100%;">
</div>
<div>
<span class="btn btn-default btn-sm btn-file">
<span class="fileinput-new"><?= lang('Config.company_select_image') ?></span>
<span class="fileinput-exists"><?= lang('Config.company_change_image') ?></span>
<input type="file" name="company_logo">
</span>
<a href="#" class="btn btn-default btn-sm fileinput-exists" data-dismiss="fileinput"><?= lang('Config.company_remove_image') ?></a>
</div>
</div>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.address'), 'address', ['class' => 'control-label col-xs-2 required']) ?>
<div class="col-xs-6">
<?= form_textarea([
'name' => 'address',
'id' => 'address',
'class' => 'form-control input-sm required',
'value' => $config['address']
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.website'), 'website', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-6">
<div class="input-group">
<span class="input-group-addon input-sm">
<span class="glyphicon glyphicon-globe"></span>
</span>
<?= form_input([
'name' => 'website',
'id' => 'website',
'class' => 'form-control input-sm',
'value' => $config['website']
]) ?>
</div>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Common.email'), 'email', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-6">
<div class="input-group">
<span class="input-group-addon input-sm">
<span class="glyphicon glyphicon-envelope"></span>
</span>
<?= form_input([
'name' => 'email',
'id' => 'email',
'type' => 'email',
'class' => 'form-control input-sm',
'value' => $config['email']
]) ?>
</div>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.phone'), 'phone', ['class' => 'control-label col-xs-2 required']) ?>
<div class="col-xs-6">
<div class="input-group">
<span class="input-group-addon input-sm">
<span class="glyphicon glyphicon-phone-alt"></span>
</span>
<?= form_input([
'name' => 'phone',
'id' => 'phone',
'class' => 'form-control input-sm required',
'value' => $config['phone']
]) ?>
</div>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.fax'), 'fax', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-6">
<div class="input-group">
<span class="input-group-addon input-sm">
<span class="glyphicon glyphicon-phone-alt"></span>
</span>
<?= form_input([
'name' => 'fax',
'id' => 'fax',
'class' => 'form-control input-sm',
'value' => $config['fax']
]) ?>
</div>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Common.return_policy'), 'return_policy', ['class' => 'control-label col-xs-2 required']) ?>
<div class="col-xs-6">
<?= form_textarea([
'name' => 'return_policy',
'id' => 'return_policy',
'class' => 'form-control input-sm required',
'value' => $config['return_policy']
]) ?>
</div>
</div>
<?= form_submit([
'name' => 'submit_info',
'id' => 'submit_info',
'value' => lang('Common.submit'),
'class' => 'btn btn-primary btn-sm pull-right'
]) ?>
</fieldset>
</div>
</div>
<div class="row mb-3">
<label for="info-company_logo" class="form-label"><?= lang('Config.company_logo'); ?></label>
<div class="col-12 col-lg-6">
<div id="info-company_logo" class="w-100 fileinput <?= $logo_exists ? 'fileinput-exists' : 'fileinput-new'; ?>" data-provides="fileinput">
<div class="input-group mb-3" aria-describedby="company-logo-desc">
<span class="input-group-text"><i class="bi bi-image"></i></span>
<div class="fileinput-new form-control rounded-end mb-0" style="height: 200px; cursor: default;"></div>
<div class="fileinput-exists fileinput-preview img-thumbnail form-control rounded-end mb-0 bg-light mh-100" style="height: 200px; cursor: default; background-size: 40px 40px; background-position: 0 0, 20px 20px; background-image: linear-gradient(45deg, white 25%, transparent 25%, transparent 75%, white 75%, white), linear-gradient(45deg, white 25%, transparent 25%, transparent 75%, white 75%, white);">
<img class="mh-100 mw-100" data-src="holder.js/100%x100%" alt="<?= esc(lang('Config.company_logo')) ?>" src="<?= $logo_src ?>">
</div>
</div>
<div type="button" class="btn btn-secondary btn-file me-2">
<span class="fileinput-new"><i class="bi bi-hand-index me-2"></i><?= lang('Config.company_select_image') ?></span>
<span class="fileinput-exists"><i class="bi bi-images me-2"></i><?= lang('Config.company_change_image') ?></span>
<input type="file" name="company_logo">
</div>
<a type="button" class="btn btn-outline-secondary fileinput-exists" data-dismiss="fileinput">
<i class="bi bi-eraser me-2"></i><?= lang('Config.company_remove_image') ?>
</a>
</div>
</div>
<div class="col-12 col-lg-6 form-text d-none d-lg-block" id="company-logo-desc">
<ul class="list-unstyled">
<li>&raquo; Supported file formats; gif, png, jpg</li> <!-- TODO-BS5 add to translations -->
<li>&raquo; Max upload size of 100kb</li> <!-- TODO-BS5 add to translations -->
<li>&raquo; Max dimensions of 200x200px</li> <!-- TODO-BS5 add to translations -->
</ul>
</div>
</div>
<label for="info-address" class="form-label"><?= lang('Config.address'); ?><sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-house"></i></span>
<textarea class="form-control" name="address" id="info-address" rows="10" required><?= $config['address']; ?></textarea>
<div class="invalid-feedback"><?= lang('Config.address_required') ?></div>
</div>
<div class="row">
<div class="col-12 col-lg-6">
<label for="info-website" class="form-label"><?= lang('Config.website'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-globe"></i></span>
<input class="form-control" name="website" id="info-website" value="<?= $config['website']; ?>">
</div>
</div>
<div class="col-12 col-lg-6">
<label for="info-email" class="form-label"><?= lang('Config.email'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-at"></i></span>
<input type="email" class="form-control" name="email" id="info-email" value="<?= $config['email']; ?>">
<div class="invalid-feedback"><?= lang('Common.email_invalid_format') ?></div>
</div>
</div>
<div class="col-12 col-lg-6">
<label for="info-phone" class="form-label"><?= lang('Config.phone'); ?><sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-telephone"></i></span>
<input type="tel" class="form-control" name="phone" id="info-phone" value="<?= $config['phone']; ?>" required>
<div class="invalid-feedback"><?= lang('Config.phone_required') ?></div>
</div>
</div>
<div class="col-12 col-lg-6">
<label for="info-fax" class="form-label"><?= lang('Config.fax'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-printer"></i></span>
<input type="tel" class="form-control" name="fax" id="info-fax" value="<?= $config['fax']; ?>">
</div>
</div>
</div>
<label for="info-return_policy" class="form-label"><?= lang('Common.return_policy'); ?><sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-box-arrow-in-down-left"></i></span>
<textarea class="form-control" name="return_policy" id="info-return_policy" rows="10" required><?= $config['return_policy']; ?></textarea>
<div class="invalid-feedback"><?= lang('Config.return_policy_required') ?></div>
</div>
<div class="d-flex justify-content-end">
<button type="submit" class="btn btn-primary" name="submit_info"><?= lang('Common.submit'); ?></button>
</div>
<?= form_close() ?>
<script type="text/javascript">
@@ -167,7 +125,7 @@
$('#info_config_form').validate($.extend(form_support.handler, {
errorLabelContainer: "#info_error_message_box",
errorLabelContainer: ".info_error_message_box",
rules: {
company: "required",

View File

@@ -5,64 +5,55 @@
*/
?>
<?= form_open('config/saveMailchimp/', ['id' => 'mailchimp_config_form', 'enctype' => 'multipart/form-data', 'class' => 'form-horizontal']) ?>
<div id="config_wrapper">
<fieldset id="config_info">
<?= form_open('config/saveMailchimp/', ['id' => 'mailchimp_config_form', 'enctype' => 'multipart/form-data']) ?>
<div id="required_fields_message"><?= lang('Common.fields_required_message') ?></div>
<div id="integrations_header"><?= lang('Config.mailchimp_configuration') ?></div>
<ul id="mailchimp_error_message_box" class="error_message_box"></ul>
<?php
$title_info['config_title'] = lang('Config.integrations_configuration');
echo view('configs/config_header', $title_info);
?>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.mailchimp_api_key'), 'mailchimp_api_key', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-4">
<div class="input-group">
<span class="input-group-addon input-sm">
<span class="glyphicon glyphicon-cloud"></span>
</span>
<?= form_input([
'name' => 'mailchimp_api_key',
'id' => 'mailchimp_api_key',
'class' => 'form-control input-sm',
'value' => $mailchimp['api_key']
]) ?>
</div>
</div>
<div class="col-xs-1">
<label class="control-label">
<a href="https://eepurl.com/b9a05b" target="_blank">
<span class="glyphicon glyphicon-info-sign" data-toggle="tooltip" data-placement="right" title="<?= lang('Config.mailchimp_tooltip') ?>"></span>
</a>
</label>
</div>
<legend class="fs-5"><?= lang('Config.mailchimp_configuration') ?></legend>
<ul id="error_message_box" class="mailchimp_error_message_box alert alert-warning d-none"></ul>
<div class="row">
<div class="col-12 col-lg-6">
<label for="mailchimp_api_key" class="form-label">
<?= lang('Config.mailchimp_api_key'); ?>
<!--<a href="https://eepurl.com/dyijVH" target="_blank" rel="noopener">
<i class="bi bi-info-circle-fill text-secondary" data-bs-toggle="tooltip" title="<?= lang('Config.mailchimp_tooltip'); ?>"></i>
</a>-->
</label>
<div class="input-group">
<span class="input-group-text" id="mailchimp-api-key-icon"><i class="bi bi-key"></i></span>
<input type="text" class="form-control" name="mailchimp_api_key" id="mailchimp_api_key" aria-describedby="mailchimp-api-key-icon" value="<?= $mailchimp['api_key']; ?>">
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.mailchimp_lists'), 'mailchimp_list_id', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-4">
<div class="input-group">
<span class="input-group-addon input-sm">
<span class="glyphicon glyphicon-user"></span>
</span>
<?= form_dropdown(
'mailchimp_list_id',
$mailchimp['lists'],
$mailchimp['list_id'],
'id="mailchimp_list_id" class="form-control input-sm"'
) ?>
</div>
</div>
<div class="form-text mb-3">
<a class="link-secondary" href="https://eepurl.com/dyijVH" target="_blank" rel="noopener">
<i class="bi bi-info-square pe-1"></i><?= lang('Config.mailchimp_tooltip') ?>
</a>
</div>
</div>
<?= form_submit([
'name' => 'submit_mailchimp',
'id' => 'submit_mailchimp',
'value' => lang('Common.submit'),
'class' => 'btn btn-primary btn-sm pull-right'
]) ?>
</fieldset>
<div class="col-12 col-lg-6">
<label for="mailchimp_list_id" class="form-label"><?= lang('Config.mailchimp_lists'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="mailchimp-lists-icon"><i class="bi bi-list-stars"></i></span>
<select class="form-select" id="mailchimp_list_id" aria-describedby="mailchimp-lists-icon" <?= $mailchimp['api_key'] == null ? 'disabled' : '' ?>>
<option>Choose...</option>
<?php foreach($mailchimp['lists'] as $value => $display_text): ?>
<option value="<?= $value; ?>" <?= $value == $mailchimp['list_id'] ? 'selected' : ''; ?>>
<?= $display_text; ?>
</option>
<?php endforeach; ?>
</select>
</div>
</div>
</div>
<div class="d-flex justify-content-end">
<button type="submit" class="btn btn-primary" name="sumbit_mailchimp"><?= lang('Common.submit'); ?></button>
</div>
<?= form_close() ?>
<script type="text/javascript">
@@ -74,6 +65,7 @@
},
function(response) {
$.notify({
icon: 'bi bi-bell-fill',
message: response.message
}, {
type: response.success ? 'success' : 'danger'
@@ -102,7 +94,7 @@
});
},
errorLabelContainer: '#mailchimp_error_message_box'
errorLabelContainer: '.mailchimp_error_message_box'
}));
});
</script>

View File

@@ -6,193 +6,135 @@
*/
?>
<?= form_open('config/saveInvoice/', ['id' => 'invoice_config_form', 'class' => 'form-horizontal']) ?>
<div id="config_wrapper">
<fieldset id="config_info">
<?= form_open('config/saveInvoice/', ['id' => 'invoice_config_form']) ?>
<div id="required_fields_message"><?= lang('Common.fields_required_message') ?></div>
<ul id="invoice_error_message_box" class="error_message_box"></ul>
<?php
$title_info['config_title'] = lang('Config.invoice_configuration');
echo view('configs/config_header', $title_info);
?>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.invoice_enable'), 'invoice_enable', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-1">
<?= form_checkbox([
'name' => 'invoice_enable',
'value' => 'invoice_enable',
'id' => 'invoice_enable',
'checked' => $config['invoice_enable'] == 1
]) ?>
</div>
</div>
<ul id="error_message_box" class="invoice_error_message_box alert alert-warning d-none"></ul>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.invoice_type'), 'invoice_type', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-3">
<?= form_dropdown(
'invoice_type',
$invoice_type_options,
$config['invoice_type'],
'class="form-control input-sm"'
) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.recv_invoice_format'), 'recv_invoice_format', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_input([
'name' => 'recv_invoice_format',
'id' => 'recv_invoice_format',
'class' => 'form-control input-sm',
'value' => $config['recv_invoice_format']
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.invoice_default_comments'), 'invoice_default_comments', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-5">
<?= form_textarea([
'name' => 'invoice_default_comments',
'id' => 'invoice_default_comments',
'class' => 'form-control input-sm',
'value' => $config['invoice_default_comments']
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.invoice_email_message'), 'invoice_email_message', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-5">
<?= form_textarea([
'name' => 'invoice_email_message',
'id' => 'invoice_email_message',
'class' => 'form-control input-sm',
'value' => $config['invoice_email_message']
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.line_sequence'), 'line_sequence', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_dropdown(
'line_sequence',
$line_sequence_options,
$config['line_sequence'],
'class="form-control input-sm"'
) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.sales_invoice_format'), 'sales_invoice_format', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_input([
'name' => 'sales_invoice_format',
'id' => 'sales_invoice_format',
'class' => 'form-control input-sm',
'value' => $config['sales_invoice_format']
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.last_used_invoice_number'), 'last_used_invoice_number', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_input([
'type' => 'number',
'name' => 'last_used_invoice_number',
'id' => 'last_used_invoice_number',
'class' => 'form-control input-sm required',
'value' => $config['last_used_invoice_number']
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.sales_quote_format'), 'sales_quote_format', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_input([
'name' => 'sales_quote_format',
'id' => 'sales_quote_format',
'class' => 'form-control input-sm',
'value' => $config['sales_quote_format']
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.last_used_quote_number'), 'last_used_quote_number', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_input([
'type' => 'number',
'name' => 'last_used_quote_number',
'id' => 'last_used_quote_number',
'class' => 'form-control input-sm required',
'value' => $config['last_used_quote_number']
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.quote_default_comments'), 'quote_default_comments', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-5">
<?= form_textarea([
'name' => 'quote_default_comments',
'id' => 'quote_default_comments',
'class' => 'form-control input-sm',
'value' => $config['quote_default_comments']
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.work_order_enable'), 'work_order_enable', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-1">
<?= form_checkbox([
'name' => 'work_order_enable',
'value' => 'work_order_enable',
'id' => 'work_order_enable',
'checked' => $config['work_order_enable'] == 1
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.work_order_format'), 'work_order_format', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_input([
'name' => 'work_order_format',
'id' => 'work_order_format',
'class' => 'form-control input-sm',
'value' => $config['work_order_format']
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.last_used_work_order_number'), 'last_used_work_order_number', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_input([
'type' => 'number',
'name' => 'last_used_work_order_number',
'id' => 'last_used_work_order_number',
'class' => 'form-control input-sm required',
'value' => $config['last_used_work_order_number']
]) ?>
</div>
</div>
<?= form_submit([
'name' => 'submit_invoice',
'id' => 'submit_invoice',
'value' => lang('Common.submit'),
'class' => 'btn btn-primary btn-sm pull-right'
]) ?>
</fieldset>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="invoice_enable" name="invoice_enable" value="invoice_enable" <?= $config['invoice_enable'] == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="invoice_enable"><?= lang('Config.invoice_enable'); ?></label>
</div>
<div class="row">
<div class="col-12 col-lg-6">
<label for="invoice_type" class="form-label"><?= lang('Config.invoice_type'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-file-code"></i></span>
<select class="form-select" name="invoice_type">
<?php foreach ($invoice_type_options as $key => $value): ?>
<option value="<?= $key ?>" <?= $key == $config['invoice_type'] ? 'selected' : '' ?>><?= $value ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="col-12 col-lg-6">
<label for="recv_invoice_format" class="form-label"><?= lang('Config.recv_invoice_format'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-braces"></i></span>
<input type="text" class="form-control" name="recv_invoice_format" id="recv_invoice_format" value="<?= $config['recv_invoice_format']; ?>">
</div>
</div>
</div>
<label for="invoice_default_comments" class="form-label"><?= lang('Config.invoice_default_comments'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-file-text"></i></span>
<textarea class="form-control" name="invoice_default_comments" id="invoice_default_comments" rows="10" required><?= $config['invoice_default_comments']; ?></textarea>
</div>
<label for="invoice_email_message" class="form-label"><?= lang('Config.invoice_email_message'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-envelope-paper"></i></span>
<textarea class="form-control" name="invoice_email_message" id="invoice_email_message" rows="10" required><?= $config['invoice_email_message']; ?></textarea>
</div>
<div class="row">
<div class="col-12 col-lg-6">
<label for="line_sequence" class="form-label"><?= lang('Config.line_sequence'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-list-ol"></i></span>
<select class="form-select" name="line_sequence">
<?php foreach ($line_sequence_options as $key => $value): ?>
<option value="<?= $key ?>" <?= $key == $config['line_sequence'] ? 'selected' : '' ?>><?= $value ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-12 col-lg-6">
<label for="sales_invoice_format" class="form-label"><?= lang('Config.sales_invoice_format'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-braces"></i></span>
<input type="text" class="form-control" name="sales_invoice_format" id="sales_invoice_format" value="<?= $config['sales_invoice_format']; ?>">
</div>
</div>
<div class="col-12 col-lg-6">
<label for="last_used_invoice_number" class="form-label"><?= lang('Config.last_used_invoice_number'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-123"></i></span>
<input type="number" class="form-control" name="last_used_invoice_number" id="last_used_invoice_number" value="<?= $config['last_used_invoice_number']; ?>">
</div>
</div>
<div class="col-12 col-lg-6">
<label for="sales_quote_format" class="form-label"><?= lang('Config.sales_quote_format'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-braces"></i></span>
<input type="text" class="form-control" name="sales_quote_format" id="sales_quote_format" value="<?= $config['sales_quote_format']; ?>">
</div>
</div>
<div class="col-12 col-lg-6">
<label for="last_used_quote_number" class="form-label"><?= lang('Config.last_used_quote_number'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-123"></i></span>
<input type="number" class="form-control" name="last_used_quote_number" id="last_used_quote_number" value="<?= $config['last_used_quote_number']; ?>">
</div>
</div>
</div>
<label for="quote_default_comments" class="form-label"><?= lang('Config.quote_default_comments'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-file-text"></i></span>
<textarea class="form-control" name="quote_default_comments" id="quote_default_comments" rows="10" required><?= $config['quote_default_comments']; ?></textarea>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="work_order_enable" name="work_order_enable" value="work_order_enable" <?= $config['work_order_enable'] == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="work_order_enable"><?= lang('Config.work_order_enable'); ?></label>
</div>
<div class="row">
<div class="col-12 col-lg-6">
<label for="work_order_format" class="form-label"><?= lang('Config.work_order_format'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-braces"></i></span>
<input type="text" class="form-control" name="work_order_format" id="work_order_format" value="<?= $config['work_order_format']; ?>">
</div>
</div>
<div class="col-12 col-lg-6">
<label for="last_used_work_order_number" class="form-label"><?= lang('Config.last_used_work_order_number'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-123"></i></span>
<input type="number" class="form-control" name="last_used_work_order_number" id="last_used_work_order_number" value="<?= $config['last_used_work_order_number']; ?>">
</div>
</div>
</div>
<div class="d-flex justify-content-end">
<button type="submit" class="btn btn-primary" name="submit_invoice"><?= lang('Common.submit'); ?></button>
</div>
<?= form_close() ?>
<script type="text/javascript">
@@ -225,7 +167,7 @@
$("#invoice_config_form").validate($.extend(form_support.handler, {
errorLabelContainer: "#invoice_error_message_box",
errorLabelContainer: ".invoice_error_message_box",
submitHandler: function(form) {
$(form).ajaxSubmit({
@@ -235,6 +177,7 @@
},
success: function(response) {
$.notify({
icon: 'bi bi-bell-fill',
message: response.message
}, {
type: response.success ? 'success' : 'danger'

View File

@@ -4,29 +4,25 @@
*/
?>
<?= form_open('', ['id' => 'license_config_form', 'enctype' => 'multipart/form-data', 'class' => 'form-horizontal']) ?>
<div id="config_wrapper">
<fieldset>
<?= form_open('', ['id' => 'license_config_form', 'enctype' => 'multipart/form-data']) ?>
<?php
$counter = 0;
foreach ($licenses as $license) {
?>
<div class="form-group form-group-sm">
<?= form_label($license['title'], 'license', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-6">
<?= form_textarea([
'name' => 'license',
'id' => 'license_' . $counter++, // TODO: String Interpolation
'class' => 'form-control font-monospace',
'rows' => '14',
'readonly' => '',
'value' => $license['text']
]) ?>
</div>
</div>
<?php } ?>
<?php
$title_info['config_title'] = lang('Config.license_configuration');
echo view('configs/config_header', $title_info);
?>
<?php
$license_i = 0;
foreach ($licenses as $license) {
?>
<div class="mb-3 mx-3 mx-lg-0">
<label for="license_<?= $license_i; ?>" class="form-label"><?= $license['title']; ?></label>
<textarea name="license" rows="10" id="license_<?= $license_i; ?>" class="form-control font-monospace" style="font-size: .875rem;" readonly><?= $license['text']; ?></textarea>
</div>
<?php
$license_i++; // Increment counter
} ?>
</fieldset>
</div>
<?= form_close() ?>

View File

@@ -5,285 +5,245 @@
* @var string $controller_name
* @var array $config
*/
$beta = '<sup><span class="badge bg-secondary">BETA</span></sup>';
?>
<?= form_open('config/saveLocale/', ['id' => 'locale_config_form', 'class' => 'form-horizontal']) ?>
<div id="config_wrapper">
<fieldset id="config_info">
<?= form_open('config/saveLocale/', ['id' => 'locale_config_form']) ?>
<div id="required_fields_message"><?= lang('Common.fields_required_message') ?></div>
<ul id="locale_error_message_box" class="error_message_box"></ul>
<?php
$title_info['config_title'] = lang('Config.locale_configuration');
echo view('configs/config_header', $title_info);
?>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.number_locale'), 'number_locale', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-1">
<?= form_input([
'name' => 'number_locale',
'id' => 'number_locale',
'class' => 'form-control input-sm',
'value' => $config['number_locale']
]) ?>
<?= form_hidden(['name' => 'save_number_locale', 'value' => $config['number_locale']]) ?>
</div>
<div class="col-xs-2">
<label class="control-label">
<a href="https://github.com/opensourcepos/opensourcepos/wiki/Localisation-support" target="_blank">
<span class="glyphicon glyphicon-info-sign" data-toggle="tooltip" data-placement="right" title="<?= lang('Config.number_locale_tooltip') ?>"></span>
</a>
<span id="number_locale_example">
&nbsp;&nbsp;<?= to_currency(1234567890.12300) ?>
</span>
</label>
</div>
<ul id="error_message_box" class="locale_error_message_box alert alert-warning d-none"></ul>
<div class="row">
<div class="col-12 col-sm-6 col-xxl-3">
<label for="number_locale" class="form-label"><?= lang('Config.number_locale') ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-globe-americas"></i></span>
<input type="text" class="form-control" name="number_locale" id="number_locale" value="<?= $config['number_locale'] ?>">
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.thousands_separator'), 'thousands_separator', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_checkbox([
'name' => 'thousands_separator',
'id' => 'thousands_separator',
'value' => 'thousands_separator',
'checked' => $config['thousands_separator'] == 1
]) ?>
</div>
<div class="col-12 col-sm-6 col-xxl-3">
<label for="number_locale_example" class="form-label">Localization Example</label>
<div class="mb-3" id="number_locale_example">
<?= to_currency(1234567890.12300) ?>&nbsp;
<a href="https://github.com/opensourcepos/opensourcepos/wiki/Localisation-support" target="_blank" rel="noopener">
<i class="bi bi-link-45deg link-secondary" data-bs-toggle="tooltip" title="<?= lang('Config.number_locale_tooltip'); ?>"></i>
</a>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.currency_symbol'), 'currency_symbol', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-1">
<?= form_input([
'name' => 'currency_symbol',
'id' => 'currency_symbol',
'class' => 'form-control input-sm number_locale',
'value' => $config['currency_symbol']
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.currency_code'), 'currency_code', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-1">
<?= form_input([
'name' => 'currency_code',
'id' => 'currency_code',
'class' => 'form-control input-sm number_locale',
'value' => $currency_code
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.currency_decimals'), 'currency_decimals', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_dropdown(
'currency_decimals',
[
'0' => '0',
'1' => '1',
'2' => '2'
],
$config['currency_decimals'],
['class' => 'form-control input-sm']
) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.tax_decimals'), 'tax_decimals', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_dropdown(
'tax_decimals',
[
'0' => '0',
'1' => '1',
'2' => '2',
'3' => '3',
'4' => '4'
],
$config['tax_decimals'],
['class' => 'form-control input-sm']
) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.quantity_decimals'), 'quantity_decimals', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_dropdown(
'quantity_decimals',
[
'0' => '0',
'1' => '1',
'2' => '2',
'3' => '3'
],
$config['quantity_decimals'],
['class' => 'form-control input-sm']
) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.cash_decimals'), 'cash_decimals', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_dropdown(
'cash_decimals',
[
'-1' => '-1',
'0' => '0',
'1' => '1',
'2' => '2'
],
$config['cash_decimals'],
['class' => 'form-control input-sm']
) ?>
</div>
<div class="col-xs-1">
<label class="control-label">
<span class="glyphicon glyphicon-info-sign" data-toggle="tooltip" data-placement="right" title="<?= lang('Config.cash_decimals_tooltip') ?>"></span>
</label>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.cash_rounding'), 'cash_rounding_code', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_dropdown(
'cash_rounding_code',
$rounding_options,
$config['cash_rounding_code'],
'class="form-control input-sm"'
) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.payment_options_order'), 'payment_options_order', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-4">
<?= form_dropdown(
'payment_options_order',
[
'cashdebitcredit' => lang('Sales.cash') . ' / ' . lang('Sales.debit') . ' / ' . lang('Sales.credit'),
'debitcreditcash' => lang('Sales.debit') . ' / ' . lang('Sales.credit') . ' / ' . lang('Sales.cash'),
'debitcashcredit' => lang('Sales.debit') . ' / ' . lang('Sales.cash') . ' / ' . lang('Sales.credit'),
'creditdebitcash' => lang('Sales.credit') . ' / ' . lang('Sales.debit') . ' / ' . lang('Sales.cash'),
'creditcashdebit' => lang('Sales.credit') . ' / ' . lang('Sales.cash') . ' / ' . lang('Sales.debit')
],
$config['payment_options_order'],
'class="form-control input-sm"'
) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.country_codes'), 'country_codes', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-1">
<?= form_input([
'name' => 'country_codes',
'class' => 'form-control input-sm',
'value' => $config['country_codes']
]) ?>
</div>
<div class="col-xs-1">
<label class="control-label">
<a href="https://wiki.openstreetmap.org/wiki/Nominatim/Country_Codes" target="_blank">
<span class="glyphicon glyphicon-info-sign" data-toggle="tooltip" data-placement="right" title="<?= lang('Config.country_codes_tooltip'); ?>"></span>
</a>
</label>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.language'), 'language', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-4">
<?= form_dropdown(
'language',
get_languages(),
current_language_code(true) . ':' . current_language(true),
['class' => 'form-control input-sm']
) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.timezone'), 'timezone', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-4">
<?= form_dropdown(
'timezone',
get_timezones(),
$config['timezone'] ? $config['timezone'] : date_default_timezone_get(),
['class' => 'form-control input-sm']
) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.datetimeformat'), 'datetimeformat', ['class' => 'control-label col-xs-2']) ?>
<div class="col-sm-2">
<?= form_dropdown(
'dateformat',
get_dateformats(),
$config['dateformat'],
['class' => 'form-control input-sm']
) ?>
</div>
<div class="col-sm-2">
<?= form_dropdown(
'timeformat',
get_timeformats(),
$config['timeformat'],
['class' => 'form-control input-sm']
) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.date_or_time_format'), 'date_or_time_format', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_checkbox([
'name' => 'date_or_time_format',
'id' => 'date_or_time_format',
'value' => 'date_or_time_format',
'checked' => $config['date_or_time_format'] == 1
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.financial_year'), 'financial_year', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_dropdown(
'financial_year',
[
'1' => lang('Config.financial_year_jan'),
'2' => lang('Config.financial_year_feb'),
'3' => lang('Config.financial_year_mar'),
'4' => lang('Config.financial_year_apr'),
'5' => lang('Config.financial_year_may'),
'6' => lang('Config.financial_year_jun'),
'7' => lang('Config.financial_year_jul'),
'8' => lang('Config.financial_year_aug'),
'9' => lang('Config.financial_year_sep'),
'10' => lang('Config.financial_year_oct'),
'11' => lang('Config.financial_year_nov'),
'12' => lang('Config.financial_year_dec')
],
$config['financial_year'],
['class' => 'form-control input-sm']
) ?>
</div>
</div>
<?= form_submit([
'name' => 'submit_locale',
'id' => 'submit_locale',
'value' => lang('Common.submit'),
'class' => 'btn btn-primary btn-sm pull-right'
]) ?>
</fieldset>
</div>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="thousands_separator" name="thousands_separator" value="thousands_separator" <?= $config['thousands_separator'] == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="thousands_separator"><?= lang('Config.thousands_separator'); ?></label>
</div>
<div class="row">
<div class="col-12 col-sm-6 col-xxl-3">
<label for="currency_symbol" class="form-label"><?= lang('Config.currency_symbol') ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-currency-exchange"></i></span>
<input type="text" class="form-control" name="currency_symbol" id="currency_symbol" value="<?= $config['currency_symbol'] ?>">
</div>
</div>
<div class="col-12 col-sm-6 col-xxl-3">
<label for="currency_code" class="form-label"><?= lang('Config.currency_code') ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-cash"></i></span>
<input type="text" class="form-control" name="currency_code" id="currency_code" value="<?= $currency_code ?>">
</div>
</div>
</div>
<div class="row">
<div class="col-12 col-sm-6 col-xxl-3">
<label for="currency_decimals" class="form-label"><?= lang('Config.currency_decimals') ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-coin"></i></span>
<select class="form-select" name="currency_decimals" id="currency_decimals">
<option value="0" <?= $config['currency_decimals'] == '0' ? 'selected' : '' ?>>0</option>
<option value="1" <?= $config['currency_decimals'] == '1' ? 'selected' : '' ?>>1</option>
<option value="2" <?= $config['currency_decimals'] == '2' ? 'selected' : '' ?>>2</option>
</select>
</div>
</div>
<div class="col-12 col-sm-6 col-xxl-3">
<label for="tax_decimals" class="form-label"><?= lang('Config.tax_decimals') ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-archive"></i></span>
<select class="form-select" name="tax_decimals" id="tax_decimals">
<option value="0" <?= $config['tax_decimals'] == '0' ? 'selected' : '' ?>>0</option>
<option value="1" <?= $config['tax_decimals'] == '1' ? 'selected' : '' ?>>1</option>
<option value="2" <?= $config['tax_decimals'] == '2' ? 'selected' : '' ?>>2</option>
<option value="3" <?= $config['tax_decimals'] == '3' ? 'selected' : '' ?>>3</option>
<option value="4" <?= $config['tax_decimals'] == '4' ? 'selected' : '' ?>>4</option>
</select>
</div>
</div>
<div class="col-12 col-sm-6 col-xxl-3">
<label for="quantity_decimals" class="form-label"><?= lang('Config.quantity_decimals') ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-123"></i></span>
<select class="form-select" name="quantity_decimals" id="quantity_decimals">
<option value="0" <?= $config['quantity_decimals'] == '0' ? 'selected' : '' ?>>0</option>
<option value="1" <?= $config['quantity_decimals'] == '1' ? 'selected' : '' ?>>1</option>
<option value="2" <?= $config['quantity_decimals'] == '2' ? 'selected' : '' ?>>2</option>
<option value="3" <?= $config['quantity_decimals'] == '3' ? 'selected' : '' ?>>3</option>
</select>
</div>
</div>
<div class="col-12 col-sm-6 col-xxl-3">
<label for="cash_decimals" class="form-label"><?= lang('Config.cash_decimals') ?>
<i class="bi bi-info-circle-fill text-secondary" data-bs-toggle="tooltip" title="<?= lang('Config.cash_decimals_tooltip'); ?>"></i>
</label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-cash-coin"></i></span>
<select class="form-select" name="cash_decimals" id="cash_decimals">
<option value="0" <?= $config['cash_decimals'] == '0' ? 'selected' : '' ?>>0</option>
<option value="1" <?= $config['cash_decimals'] == '1' ? 'selected' : '' ?>>1</option>
<option value="2" <?= $config['cash_decimals'] == '2' ? 'selected' : '' ?>>2</option>
</select>
</div>
</div>
<div class="col-12 col-sm-6 col-xxl-3">
<label for="cash_rounding_code" class="form-label"><?= lang('Config.cash_rounding') ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-arrow-repeat"></i></span>
<select class="form-select" name="cash_rounding_code" id="cash_rounding_code">
<?php foreach ($rounding_options as $code => $label): ?>
<option value="<?= $code ?>" <?= $config['cash_rounding_code'] == $code ? 'selected' : '' ?>><?= $label ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-12 col-lg-6">
<label for="payment_options_order" class="form-label"><?= lang('Config.payment_options_order') ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-credit-card"></i></span>
<select class="form-select" name="payment_options_order" id="payment_options_order">
<option value="cashdebitcredit" <?= $config['payment_options_order'] == 'cashdebitcredit' ? 'selected' : '' ?>><?= lang('Sales.cash') ?> / <?= lang('Sales.debit') ?> / <?= lang('Sales.credit') ?></option>
<option value="debitcreditcash" <?= $config['payment_options_order'] == 'debitcreditcash' ? 'selected' : '' ?>><?= lang('Sales.debit') ?> / <?= lang('Sales.credit') ?> / <?= lang('Sales.cash') ?></option>
<option value="debitcashcredit" <?= $config['payment_options_order'] == 'debitcashcredit' ? 'selected' : '' ?>><?= lang('Sales.debit') ?> / <?= lang('Sales.cash') ?> / <?= lang('Sales.credit') ?></option>
<option value="creditdebitcash" <?= $config['payment_options_order'] == 'creditdebitcash' ? 'selected' : '' ?>><?= lang('Sales.credit') ?> / <?= lang('Sales.debit') ?> / <?= lang('Sales.cash') ?></option>
<option value="creditcashdebit" <?= $config['payment_options_order'] == 'creditcashdebit' ? 'selected' : '' ?>><?= lang('Sales.credit') ?> / <?= lang('Sales.cash') ?> / <?= lang('Sales.debit') ?></option>
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-12 col-lg-6">
<label for="country_codes" class="form-label">
<?= lang('Config.country_codes') ?>
<a href="https://wiki.openstreetmap.org/wiki/Nominatim/Country_Codes" target="_blank" rel="noopener">
<i class="bi bi-link-45deg text-secondary" data-bs-toggle="tooltip" title="<?= lang('Config.country_codes_tooltip'); ?>"></i>
</a>
</label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-code"></i></span>
<input type="text" class="form-control" name="country_codes" id="country_codes" value="<?= $config['country_codes'] ?>">
</div>
</div>
</div>
<div class="row">
<div class="col-12 col-lg-6">
<label for="language" class="form-label"><?= lang('Config.language') ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-translate"></i></span>
<select class="form-select" name="language" id="language">
<?php foreach (get_languages() as $value => $label): ?>
<option value="<?= esc($value) ?>" <?= $value === current_language_code(true) . ':' . current_language(true) ? 'selected' : '' ?>><?= esc($label) ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="rtl_language" name="rtl_language" value="rtl_language" <?= $config['rtl_language'] == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="rtl_language">RTL Language <?= $beta; ?></label>
</div>
<div class="row">
<div class="col-12 col-lg-6">
<label for="timezone" class="form-label"><?= lang('Config.timezone') ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-clock"></i></span>
<?= form_dropdown(
'timezone',
get_timezones(),
$config['timezone'] ? $config['timezone'] : date_default_timezone_get(),
['class' => 'form-select']
) ?>
</div>
</div>
<div class="col-12 col-lg-6">
<label for="datetimeformat" class="form-label"><?= lang('Config.datetimeformat') ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-calendar2"></i></span>
<?= form_dropdown(
'dateformat',
get_dateformats(),
$config['dateformat'],
['class' => 'form-select']
) ?>
<?= form_dropdown(
'timeformat',
get_timeformats(),
$config['timeformat'],
['class' => 'form-select']
) ?>
</div>
</div>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="date_or_time_format" name="date_or_time_format" value="date_or_time_format" <?= $config['date_or_time_format'] == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="date_or_time_format"><?= lang('Config.date_or_time_format'); ?></label>
</div>
<div class="row">
<div class="col-12 col-lg-6">
<label for="financial_year" class="form-label"><?= lang('Config.financial_year') ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-calendar2-month"></i></span>
<select class="form-select" name="financial_year" id="financial_year">
<option value="1" <?= ($config['financial_year'] == '1' ? 'selected' : ''); ?>><?= lang('Config.financial_year_jan'); ?></option>
<option value="2" <?= ($config['financial_year'] == '2' ? 'selected' : ''); ?>><?= lang('Config.financial_year_feb'); ?></option>
<option value="3" <?= ($config['financial_year'] == '3' ? 'selected' : ''); ?>><?= lang('Config.financial_year_mar'); ?></option>
<option value="4" <?= ($config['financial_year'] == '4' ? 'selected' : ''); ?>><?= lang('Config.financial_year_apr'); ?></option>
<option value="5" <?= ($config['financial_year'] == '5' ? 'selected' : ''); ?>><?= lang('Config.financial_year_may'); ?></option>
<option value="6" <?= ($config['financial_year'] == '6' ? 'selected' : ''); ?>><?= lang('Config.financial_year_jun'); ?></option>
<option value="7" <?= ($config['financial_year'] == '7' ? 'selected' : ''); ?>><?= lang('Config.financial_year_jul'); ?></option>
<option value="8" <?= ($config['financial_year'] == '8' ? 'selected' : ''); ?>><?= lang('Config.financial_year_aug'); ?></option>
<option value="9" <?= ($config['financial_year'] == '9' ? 'selected' : ''); ?>><?= lang('Config.financial_year_sep'); ?></option>
<option value="10" <?= ($config['financial_year'] == '10' ? 'selected' : ''); ?>><?= lang('Config.financial_year_oct'); ?></option>
<option value="11" <?= ($config['financial_year'] == '11' ? 'selected' : ''); ?>><?= lang('Config.financial_year_nov'); ?></option>
<option value="12" <?= ($config['financial_year'] == '12' ? 'selected' : ''); ?>><?= lang('Config.financial_year_dec'); ?></option>
</select>
</div>
</div>
</div>
<div class="d-flex justify-content-end">
<button type="submit" class="btn btn-primary" name="submit_locale"><?= lang('Common.submit'); ?></button>
</div>
<?= form_close() ?>
<script type="text/javascript">
@@ -354,7 +314,7 @@
}
},
errorLabelContainer: '#locale_error_message_box'
errorLabelContainer: '.locale_error_message_box'
}));
});
</script>

View File

@@ -1,79 +1,66 @@
<?php
$tabs = [
['id' => 'info', 'icon' => 'bi-shop', 'label' => lang('Config.info'), 'title' => lang('Config.info_configuration')],
['id' => 'general', 'icon' => 'bi-sliders', 'label' => lang('Config.general'), 'title' => lang('Config.general_configuration')],
['id' => 'appearance', 'icon' => 'bi-eye', 'label' => 'Appearance', 'title' => 'Appearance Configuration'],
['id' => 'locale', 'icon' => 'bi-translate', 'label' => lang('Config.locale'), 'title' => lang('Config.locale_configuration')],
['id' => 'tax', 'icon' => 'bi-piggy-bank', 'label' => lang('Config.tax'), 'title' => lang('Config.tax_configuration')],
['id' => 'barcode', 'icon' => 'bi-upc-scan', 'label' => lang('Config.barcode'), 'title' => lang('Config.barcode_configuration')],
['id' => 'stock', 'icon' => 'bi-truck', 'label' => lang('Config.location'), 'title' => lang('Config.location_configuration')],
['id' => 'receipt', 'icon' => 'bi-receipt', 'label' => lang('Config.receipt'), 'title' => lang('Config.receipt_configuration')],
['id' => 'invoice', 'icon' => 'bi-file-text', 'label' => lang('Config.invoice'), 'title' => lang('Config.invoice_configuration')],
['id' => 'shortcuts', 'icon' => 'bi-shift', 'label' => lang('Config.shortcuts'), 'title' => lang('Config.shortcuts_configuration')],
['id' => 'reward', 'icon' => 'bi-trophy', 'label' => lang('Config.reward'), 'title' => lang('Config.reward_configuration')],
['id' => 'table', 'icon' => 'bi-cup-straw', 'label' => lang('Config.table'), 'title' => lang('Config.table_configuration')],
['id' => 'email', 'icon' => 'bi-envelope', 'label' => lang('Config.email'), 'title' => lang('Config.email_configuration')],
['id' => 'message', 'icon' => 'bi-chat', 'label' => lang('Config.message'), 'title' => lang('Config.message_configuration')],
['id' => 'integrations', 'icon' => 'bi-gear-wide-connected', 'label' => lang('Config.integrations'), 'title' => lang('Config.integrations_configuration')],
['id' => 'system', 'icon' => 'bi-info-circle', 'label' => lang('Config.system_info'), 'title' => lang('Config.system_info'), 'view' => 'configs/system_info'],
['id' => 'license', 'icon' => 'bi-journal-check', 'label' => lang('Config.license'), 'title' => lang('Config.license_configuration')],
];
?>
<?= view('partial/header') ?>
<script type="text/javascript">
dialog_support.init("a.modal-dlg");
</script>
<script type="text/javascript" src="resources/clipboard/clipboard.min.js"></script>
<ul class="nav nav-tabs" data-tabs="tabs">
<li class="active" role="presentation">
<a data-toggle="tab" href="#info_tab" title="<?= lang('Config.info_configuration') ?>"><?= lang('Config.info') ?></a>
</li>
<li role="presentation">
<a data-toggle="tab" href="#general_tab" title="<?= lang('Config.general_configuration') ?>"><?= lang('Config.general') ?></a>
</li>
<li role="presentation">
<a data-toggle="tab" href="#tax_tab" title="<?= lang('Config.tax_configuration') ?>"><?= lang('Config.tax') ?></a>
</li>
<li role="presentation">
<a data-toggle="tab" href="#locale_tab" title="<?= lang('Config.locale_configuration') ?>"><?= lang('Config.locale') ?></a>
</li>
<li role="presentation">
<a data-toggle="tab" href="#barcode_tab" title="<?= lang('Config.barcode_configuration') ?>"><?= lang('Config.barcode') ?></a>
</li>
<li role="presentation">
<a data-toggle="tab" href="#stock_tab" title="<?= lang('Config.location_configuration') ?>"><?= lang('Config.location') ?></a>
</li>
<li role="presentation">
<a data-toggle="tab" href="#receipt_tab" title="<?= lang('Config.receipt_configuration') ?>"><?= lang('Config.receipt') ?></a>
</li>
<li role="presentation">
<a data-toggle="tab" href="#invoice_tab" title="<?= lang('Config.invoice_configuration') ?>"><?= lang('Config.invoice') ?></a>
</li>
<li role="presentation">
<a data-toggle="tab" href="#reward_tab" title="<?= lang('Config.reward_configuration') ?>"><?= lang('Config.reward') ?></a>
</li>
<li role="presentation">
<a data-toggle="tab" href="#table_tab" title="<?= lang('Config.table_configuration') ?>"><?= lang('Config.table') ?></a>
</li>
<li role="presentation">
<a data-toggle="tab" href="#system_tab" title="<?= lang('Config.system_conf') ?>"><?= lang('Config.system_conf') ?></a>
</li>
</ul>
<div class="row">
<div class="col-lg-3 <?= $config['config_menu_position'] == 'start' ? '' : 'order-lg-2' ?>">
<div class="list-group d-none d-lg-block" role="tablist">
<?php foreach ($tabs as $i => $tab): ?>
<button type="button" class="list-group-item list-group-item-action text-truncate <?= $i === 0 ? 'active' : '' ?>" id="<?= $tab['id'] ?>-tab" data-bs-toggle="tab" data-bs-target="#<?= $tab['id'] ?>" role="tab" title="<?= $tab['title'] ?>">
<i class="bi <?= $tab['icon'] ?> me-2"></i><?= $tab['label'] ?>
</button>
<?php endforeach ?>
</div>
<div class="tab-content">
<div class="tab-pane fade in active" id="info_tab">
<?= view('configs/info_config') ?>
<div class="nav dropdown d-lg-none mb-3">
<button type="button" class="btn btn-primary w-100 dropdown-toggle text-truncate" id="configs-dropdown" data-bs-toggle="dropdown" aria-expanded="false">
<?= lang('Config.info') ?>
</button>
<ul class="dropdown-menu w-100" aria-labelledby="configs-dropdown">
<?php foreach ($tabs as $i => $tab): ?>
<li>
<a class="dropdown-item py-2 text-truncate <?= $i === 0 ? 'active' : '' ?>" data-bs-toggle="tab" data-bs-target="#<?= $tab['id'] ?>" role="tab" title="<?= $tab['title'] ?>">
<i class="bi <?= $tab['icon'] ?> me-2"></i><?= $tab['label'] ?>
</a>
</li>
<?php endforeach ?>
</ul>
</div>
</div>
<div class="tab-pane" id="general_tab">
<?= view('configs/general_config') ?>
</div>
<div class="tab-pane" id="tax_tab">
<?= view('configs/tax_config') ?>
</div>
<div class="tab-pane" id="locale_tab">
<?= view('configs/locale_config') ?>
</div>
<div class="tab-pane" id="barcode_tab">
<?= view('configs/barcode_config') ?>
</div>
<div class="tab-pane" id="stock_tab">
<?= view('configs/stock_config') ?>
</div>
<div class="tab-pane" id="receipt_tab">
<?= view('configs/receipt_config') ?>
</div>
<div class="tab-pane" id="invoice_tab">
<?= view('configs/invoice_config') ?>
</div>
<div class="tab-pane" id="reward_tab">
<?= view('configs/reward_config') ?>
</div>
<div class="tab-pane" id="table_tab">
<?= view('configs/table_config') ?>
</div>
<div class="tab-pane" id="system_tab">
<?= view('configs/system_config') ?>
<div class="col-lg-9 order-lg-1">
<div class="tab-content">
<?php foreach ($tabs as $i => $tab): ?>
<div class="tab-pane <?= $i === 0 ? 'active' : '' ?>" id="<?= $tab['id'] ?>" role="tabpanel" aria-labelledby="<?= $tab['id'] ?>-tab">
<?= view($tab['view'] ?? 'configs/' . $tab['id'] . '_config') ?>
</div>
<?php endforeach ?>
</div>
</div>
</div>
<script type="text/javascript" src="js/bs-tab_anchor_linking.js"></script>
<script type="text/javascript" src="js/bs-validation.js"></script>
<?= view('partial/footer') ?>

View File

@@ -4,86 +4,51 @@
*/
?>
<?= form_open('config/saveMessage/', ['id' => 'message_config_form', 'enctype' => 'multipart/form-data', 'class' => 'form-horizontal']) ?>
<div id="config_wrapper">
<fieldset id="config_info">
<?= form_open('config/saveMessage/', ['id' => 'message_config_form', 'enctype' => 'multipart/form-data']) ?>
<div id="required_fields_message"><?= lang('Common.fields_required_message') ?></div>
<ul id="message_error_message_box" class="error_message_box"></ul>
<?php
$title_info['config_title'] = lang('Config.message_configuration');
echo view('configs/config_header', $title_info);
?>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.msg_uid'), 'msg_uid', ['class' => 'control-label col-xs-2 required']) ?>
<div class="col-xs-4">
<div class="input-group">
<span class="input-group-addon input-sm">
<span class="glyphicon glyphicon-user"></span>
</span>
<?= form_input([
'name' => 'msg_uid',
'id' => 'msg_uid',
'class' => 'form-control input-sm required',
'value' => $config['msg_uid']
]) ?>
</div>
</div>
<ul id="error_message_box" class="message_error_message_box alert alert-warning d-none"></ul>
<div class="row">
<div class="col-12 col-lg-6 mb-3">
<label for="msg_uid" class="form-label"><?= lang('Config.msg_uid'); ?><sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup></label>
<div class="input-group">
<span class="input-group-text" id="msg_uid-icon"><i class="bi bi-person"></i></span>
<input type="text" class="form-control" name="msg_uid" id="msg_uid" aria-describedby="msg_uid-icon" required value="<?= $config['msg_uid']; ?>">
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.msg_pwd'), 'msg_pwd', ['class' => 'control-label col-xs-2 required']) ?>
<div class="col-xs-4">
<div class="input-group">
<span class="input-group-addon input-sm">
<span class="glyphicon glyphicon-lock"></span>
</span>
<?= form_password([
'name' => 'msg_pwd',
'id' => 'msg_pwd',
'class' => 'form-control input-sm required',
'value' => $config['msg_pwd']
]) ?>
</div>
</div>
<div class="col-12 col-lg-6 mb-3">
<label for="msg_pwd" class="form-label"><?= lang('Config.msg_pwd'); ?><sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup></label>
<div class="input-group">
<span class="input-group-text" id="msg_pwd-icon"><i class="bi bi-lock"></i></span>
<input type="password" class="form-control" name="msg_pwd" id="msg_pwd" aria-describedby="msg_pwd-icon" required value="<?= $config['msg_pwd']; ?>">
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.msg_src'), 'msg_src', ['class' => 'control-label col-xs-2 required']) ?>
<div class="col-xs-4">
<div class="input-group">
<span class="input-group-addon input-sm">
<span class="glyphicon glyphicon-bullhorn"></span>
</span>
<?= form_input([
'name' => 'msg_src',
'id' => 'msg_src',
'class' => 'form-control input-sm required',
'value' => $config['msg_src'] == null ? $config['company'] : $config['msg_src']
]) ?>
</div>
</div>
<div class="col-12 col-lg-6 mb-3">
<label for="msg_src" class="form-label"><?= lang('Config.msg_src'); ?><sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup></label>
<div class="input-group">
<span class="input-group-text" id="msg_src-icon"><i class="bi bi-megaphone"></i></span>
<input type="text" class="form-control" name="msg_src" id="msg_src" aria-describedby="msg_src-icon" required value="<?= $config['msg_src'] == null ? $config['company'] : $config['msg_src']; ?>">
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.msg_msg'), 'msg_msg', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-4">
<?= form_textarea([
'name' => 'msg_msg',
'id' => 'msg_msg',
'class' => 'form-control input-sm',
'value' => $config['msg_msg'],
'placeholder' => lang('Config.msg_msg_placeholder')
]) ?>
</div>
</div>
<?= form_submit([
'name' => 'submit_message',
'id' => 'submit_message',
'value' => lang('Common.submit'),
'class' => 'btn btn-primary btn-sm pull-right'
]) ?>
</fieldset>
</div>
</div>
<label for="msg_msg" class="form-label"><?= lang('Config.msg_msg'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-chat-quote"></i></span>
<textarea class="form-control" name="msg_msg" id="msg_msg" rows="10" placeholder="<?= lang('Config.msg_msg_placeholder'); ?>"><?= esc($config['msg_msg']); ?></textarea>
</div>
<div class="d-flex justify-content-end">
<button type="submit" class="btn btn-primary" name="submit_message"><?= lang('Common.submit'); ?></button>
</div>
<?= form_close() ?>
<script type="text/javascript">
@@ -91,7 +56,7 @@
$(document).ready(function() {
$('#message_config_form').validate($.extend(form_support.handler, {
errorLabelContainer: "#message_error_message_box",
errorLabelContainer: ".message_error_message_box",
rules: {
msg_uid: "required",

View File

@@ -4,334 +4,199 @@
*/
?>
<?= form_open('config/saveReceipt/', ['id' => 'receipt_config_form', 'class' => 'form-horizontal']) ?>
<div id="config_wrapper">
<fieldset id="config_info">
<?= form_open('config/saveReceipt/', ['id' => 'receipt_config_form']) ?>
<div id="required_fields_message"><?= lang('Common.fields_required_message') ?></div>
<ul id="receipt_error_message_box" class="error_message_box"></ul>
<?php
$title_info['config_title'] = lang('Config.receipt_configuration');
echo view('configs/config_header', $title_info);
?>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.receipt_template'), 'receipt_template', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_dropdown(
'receipt_template',
[
'receipt_default' => lang('Config.receipt_default'),
'receipt_short' => lang('Config.receipt_short')
],
$config['receipt_template'],
'class="form-control input-sm"'
) ?>
</div>
<ul id="error_message_box" class="receipt_error_message_box alert alert-warning d-none"></ul>
<div class="row">
<div class="col-12 col-lg-6">
<label for="receipt_template" class="form-label"><?= lang('Config.receipt_template'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-file-code"></i></span>
<select class="form-select" name="receipt_template">
<option value="receipt_default" <?= $config['receipt_template'] == 'receipt_default' ? 'selected' : '' ?>><?= lang('Config.receipt_default') ?></option>
<option value="receipt_short" <?= $config['receipt_template'] == 'receipt_short' ? 'selected' : '' ?>><?= lang('Config.receipt_short') ?></option>
</select>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.receipt_font_size'), 'receipt_font_size', ['class' => 'control-label col-xs-2 required']) ?>
<div class="col-xs-2">
<div class="input-group">
<?= form_input([
'type' => 'number',
'min' => '0',
'max' => '20',
'name' => 'receipt_font_size',
'id' => 'receipt_font_size',
'class' => 'form-control input-sm required',
'value' => $config['receipt_font_size']
]) ?>
<span class="input-group-addon input-sm">px</span>
</div>
</div>
<div class="col-6 col-lg-3">
<label for="receipt_font_size" class="form-label"><?= lang('Config.receipt_font_size'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-arrows-angle-expand"></i></span>
<input type="number" class="form-control" name="receipt_font_size" id="receipt_font_size" value="<?= $config['receipt_font_size']; ?>">
<span class="input-group-text">px</span>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.print_delay_autoreturn'), 'print_delay_autoreturn', ['class' => 'control-label col-xs-2 required']) ?>
<div class="col-xs-2">
<div class="input-group">
<?= form_input([
'type' => 'number',
'min' => '0',
'max' => '30',
'name' => 'print_delay_autoreturn',
'id' => 'print_delay_autoreturn',
'class' => 'form-control input-sm required',
'value' => $config['print_delay_autoreturn']
]) ?>
<span class="input-group-addon input-sm">s</span>
</div>
</div>
<div class="col-6 col-lg-3">
<label for="print_delay_autoreturn" class="form-label"><?= lang('Config.print_delay_autoreturn'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-stopwatch"></i></span>
<input type="number" class="form-control" name="print_delay_autoreturn" id="print_delay_autoreturn" value="<?= $config['print_delay_autoreturn']; ?>">
<span class="input-group-text">s</span>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.email_receipt_check_behaviour'), 'email_receipt_check_behaviour', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-8">
<label class="radio-inline">
<?= form_radio([
'name' => 'email_receipt_check_behaviour',
'value' => 'always',
'checked' => $config['email_receipt_check_behaviour'] == 'always'
]) ?>
<?= lang('Config.email_receipt_check_behaviour_always') ?>
</label>
<label class="radio-inline">
<?= form_radio([
'name' => 'email_receipt_check_behaviour',
'value' => 'never',
'checked' => $config['email_receipt_check_behaviour'] == 'never'
]) ?>
<?= lang('Config.email_receipt_check_behaviour_never') ?>
</label>
<label class="radio-inline">
<?= form_radio([
'name' => 'email_receipt_check_behaviour',
'value' => 'last',
'checked' => $config['email_receipt_check_behaviour'] == 'last'
]) ?>
<?= lang('Config.email_receipt_check_behaviour_last') ?>
</label>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.print_receipt_check_behaviour'), 'print_receipt_check_behaviour', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-8">
<label class="radio-inline">
<?= form_radio([
'name' => 'print_receipt_check_behaviour',
'value' => 'always',
'checked' => $config['print_receipt_check_behaviour'] == 'always'
]) ?>
<?= lang('Config.print_receipt_check_behaviour_always') ?>
</label>
<label class="radio-inline">
<?= form_radio([
'name' => 'print_receipt_check_behaviour',
'value' => 'never',
'checked' => $config['print_receipt_check_behaviour'] == 'never'
]) ?>
<?= lang('Config.print_receipt_check_behaviour_never') ?>
</label>
<label class="radio-inline">
<?= form_radio([
'name' => 'print_receipt_check_behaviour',
'value' => 'last',
'checked' => $config['print_receipt_check_behaviour'] == 'last'
]) ?>
<?= lang('Config.print_receipt_check_behaviour_last') ?>
</label>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.receipt_show_company_name'), 'receipt_show_company_name', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-1">
<?= form_checkbox([
'name' => 'receipt_show_company_name',
'value' => 'receipt_show_company_name',
'id' => 'receipt_show_company_name',
'checked' => $config['receipt_show_company_name'] == 1
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.receipt_show_taxes'), 'receipt_show_taxes', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-1">
<?= form_checkbox([
'name' => 'receipt_show_taxes',
'value' => 'receipt_show_taxes',
'id' => 'receipt_show_taxes',
'checked' => $config['receipt_show_taxes'] == 1
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.receipt_show_tax_ind'), 'receipt_show_tax_ind', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-1">
<?= form_checkbox([
'name' => 'receipt_show_tax_ind',
'value' => 'receipt_show_tax_ind',
'id' => 'receipt_show_tax_ind',
'checked' => $config['receipt_show_tax_ind'] == 1
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.receipt_show_total_discount'), 'receipt_show_total_discount', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-1">
<?= form_checkbox([
'name' => 'receipt_show_total_discount',
'value' => 'receipt_show_total_discount',
'id' => 'receipt_show_total_discount',
'checked' => $config['receipt_show_total_discount'] == 1
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.receipt_show_description'), 'receipt_show_description', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-1">
<?= form_checkbox([
'name' => 'receipt_show_description',
'value' => 'receipt_show_description',
'id' => 'receipt_show_description',
'checked' => $config['receipt_show_description'] == 1
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.receipt_show_serialnumber'), 'receipt_show_serialnumber', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-1">
<?= form_checkbox([
'name' => 'receipt_show_serialnumber',
'value' => 'receipt_show_serialnumber',
'id' => 'receipt_show_serialnumber',
'checked' => $config['receipt_show_serialnumber'] == 1
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.print_silently'), 'print_silently', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-1">
<?= form_checkbox([
'name' => 'print_silently',
'id' => 'print_silently',
'value' => 'print_silently',
'checked' => $config['print_silently'] == 1
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.print_header'), 'print_header', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-1">
<?= form_checkbox([
'name' => 'print_header',
'id' => 'print_header',
'value' => 'print_header',
'checked' => $config['print_header'] == 1
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.print_footer'), 'print_footer', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-1">
<?= form_checkbox([
'name' => 'print_footer',
'id' => 'print_footer',
'value' => 'print_footer',
'checked' => $config['print_footer'] == 1
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.receipt_printer'), 'config_receipt_printer', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_dropdown('receipt_printer', [], ' ', 'id="receipt_printer" class="form-control"') ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.invoice_printer'), 'config_invoice_printer', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_dropdown('invoice_printer', [], ' ', 'id="invoice_printer" class="form-control"') ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.takings_printer'), 'config_takings_printer', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_dropdown('takings_printer', [], ' ', 'id="takings_printer" class="form-control"') ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.print_top_margin'), 'print_top_margin', ['class' => 'control-label col-xs-2 required']) ?>
<div class="col-xs-2">
<div class="input-group">
<?= form_input([
'type' => 'number',
'min' => '0',
'max' => '20',
'name' => 'print_top_margin',
'id' => 'print_top_margin',
'class' => 'form-control input-sm required',
'value' => $config['print_top_margin']
]) ?>
<span class="input-group-addon input-sm">px</span>
</div>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.print_left_margin'), 'print_left_margin', ['class' => 'control-label col-xs-2 required']) ?>
<div class="col-xs-2">
<div class="input-group">
<?= form_input([
'type' => 'number',
'min' => '0',
'max' => '20',
'name' => 'print_left_margin',
'id' => 'print_left_margin',
'class' => 'form-control input-sm required',
'value' => $config['print_left_margin']
]) ?>
<span class="input-group-addon input-sm">px</span>
</div>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.print_bottom_margin'), 'print_bottom_margin', ['class' => 'control-label col-xs-2 required']) ?>
<div class="col-xs-2">
<div class="input-group">
<?= form_input([
'type' => 'number',
'min' => '0',
'max' => '20',
'name' => 'print_bottom_margin',
'id' => 'print_bottom_margin',
'class' => 'form-control input-sm required',
'value' => $config['print_bottom_margin']
]) ?>
<span class="input-group-addon input-sm">px</span>
</div>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.print_right_margin'), 'print_right_margin', ['class' => 'control-label col-xs-2 required']) ?>
<div class="col-xs-2">
<div class="input-group">
<?= form_input([
'type' => 'number',
'min' => '0',
'max' => '20',
'name' => 'print_right_margin',
'id' => 'print_right_margin',
'class' => 'form-control input-sm required',
'value' => $config['print_right_margin']
]) ?>
<span class="input-group-addon input-sm">px</span>
</div>
</div>
</div>
<?= form_submit([
'name' => 'submit_receipt',
'id' => 'submit_receipt',
'value' => lang('Common.submit'),
'class' => 'btn btn-primary btn-sm pull-right'
]) ?>
</fieldset>
</div>
</div>
<label for="email_receipt_check_behaviour" class="form-label"><?= lang('Config.email_receipt_check_behaviour'); ?></label>
<div class="row mb-3">
<div class="col-12">
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="email_receipt_check_behaviour" id="email_receipt_check_behaviour_always" value="always" <?= $config['email_receipt_check_behaviour'] == 'always' ? 'checked' : '' ?>>
<label class="form-check-label" for="email_receipt_check_behaviour_always"><?= lang('Config.email_receipt_check_behaviour_always') ?></label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="email_receipt_check_behaviour" id="email_receipt_check_behaviour_never" value="never" <?= $config['email_receipt_check_behaviour'] == 'never' ? 'checked' : '' ?>>
<label class="form-check-label" for="email_receipt_check_behaviour_never"><?= lang('Config.email_receipt_check_behaviour_never') ?></label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="email_receipt_check_behaviour" id="email_receipt_check_behaviour_last" value="last" <?= $config['email_receipt_check_behaviour'] == 'last' ? 'checked' : '' ?>>
<label class="form-check-label" for="email_receipt_check_behaviour_last"><?= lang('Config.email_receipt_check_behaviour_last') ?></label>
</div>
</div>
</div>
<label for="print_receipt_check_behaviour" class="form-label"><?= lang('Config.print_receipt_check_behaviour'); ?></label>
<div class="row mb-3">
<div class="col-12">
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="print_receipt_check_behaviour" id="print_receipt_check_behaviour_always" value="always" <?= $config['print_receipt_check_behaviour'] == 'always' ? 'checked' : '' ?>>
<label class="form-check-label" for="print_receipt_check_behaviour_always"><?= lang('Config.print_receipt_check_behaviour_always') ?></label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="print_receipt_check_behaviour" id="print_receipt_check_behaviour_never" value="never" <?= $config['print_receipt_check_behaviour'] == 'never' ? 'checked' : '' ?>>
<label class="form-check-label" for="print_receipt_check_behaviour_never"><?= lang('Config.print_receipt_check_behaviour_never') ?></label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="print_receipt_check_behaviour" id="print_receipt_check_behaviour_last" value="last" <?= $config['print_receipt_check_behaviour'] == 'last' ? 'checked' : '' ?>>
<label class="form-check-label" for="print_receipt_check_behaviour_last"><?= lang('Config.print_receipt_check_behaviour_last') ?></label>
</div>
</div>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="receipt_show_company_name" name="receipt_show_company_name" value="receipt_show_company_name" <?= $config['receipt_show_company_name'] == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="receipt_show_company_name"><?= lang('Config.receipt_show_company_name'); ?></label>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="receipt_show_taxes" name="receipt_show_taxes" value="receipt_show_taxes" <?= $config['receipt_show_taxes'] == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="receipt_show_taxes"><?= lang('Config.receipt_show_taxes'); ?></label>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="receipt_show_tax_ind" name="receipt_show_tax_ind" value="receipt_show_tax_ind" <?= $config['receipt_show_tax_ind'] == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="receipt_show_tax_ind"><?= lang('Config.receipt_show_tax_ind'); ?></label>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="receipt_show_total_discount" name="receipt_show_total_discount" value="receipt_show_total_discount" <?= $config['receipt_show_total_discount'] == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="receipt_show_total_discount"><?= lang('Config.receipt_show_total_discount'); ?></label>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="receipt_show_description" name="receipt_show_description" value="receipt_show_description" <?= $config['receipt_show_description'] == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="receipt_show_description"><?= lang('Config.receipt_show_description'); ?></label>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="receipt_show_serialnumber" name="receipt_show_serialnumber" value="receipt_show_serialnumber" <?= $config['receipt_show_serialnumber'] == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="receipt_show_serialnumber"><?= lang('Config.receipt_show_serialnumber'); ?></label>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="print_silently" name="print_silently" value="print_silently" <?= $config['print_silently'] == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="print_silently"><?= lang('Config.print_silently'); ?></label>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="print_header" name="print_header" value="print_header" <?= $config['print_header'] == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="print_header"><?= lang('Config.print_header'); ?></label>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="print_footer" name="print_footer" value="print_footer" <?= $config['print_footer'] == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="print_footer"><?= lang('Config.print_footer'); ?></label>
</div>
<div class="row">
<div class="col-12 col-lg-6">
<label for="receipt_printer" class="form-label"><?= lang('Config.receipt_printer'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-printer"></i></span>
<select class="form-select" name="receipt_printer" id="receipt_printer"></select>
</div>
</div>
<div class="col-12 col-lg-6">
<label for="invoice_printer" class="form-label"><?= lang('Config.invoice_printer'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-printer"></i></span>
<select class="form-select" name="invoice_printer" id="invoice_printer"></select>
</div>
</div>
<div class="col-12 col-lg-6">
<label for="takings_printer" class="form-label"><?= lang('Config.takings_printer'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-printer"></i></span>
<select class="form-select" name="takings_printer" id="takings_printer"></select>
</div>
</div>
</div>
<div class="row">
<div class="col-6 col-lg-3">
<label for="print_top_margin" class="form-label"><?= lang('Config.print_top_margin'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-arrow-bar-down"></i></span>
<input type="number" class="form-control" name="print_top_margin" id="print_top_margin" value="<?= $config['print_top_margin']; ?>">
<span class="input-group-text">px</span>
</div>
</div>
<div class="col-6 col-lg-3">
<label for="print_left_margin" class="form-label"><?= lang('Config.print_left_margin'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-arrow-bar-right"></i></span>
<input type="number" class="form-control" name="print_left_margin" id="print_left_margin" value="<?= $config['print_left_margin']; ?>">
<span class="input-group-text">px</span>
</div>
</div>
<div class="col-6 col-lg-3">
<label for="print_bottom_margin" class="form-label"><?= lang('Config.print_bottom_margin'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-arrow-bar-up"></i></span>
<input type="number" class="form-control" name="print_bottom_margin" id="print_bottom_margin" value="<?= $config['print_bottom_margin']; ?>">
<span class="input-group-text">px</span>
</div>
</div>
<div class="col-6 col-lg-3">
<label for="print_right_margin" class="form-label"><?= lang('Config.print_right_margin'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-arrow-bar-left"></i></span>
<input type="number" class="form-control" name="print_right_margin" id="print_right_margin" value="<?= $config['print_right_margin']; ?>">
<span class="input-group-text">px</span>
</div>
</div>
</div>
<div class="d-flex justify-content-end">
<button type="submit" class="btn btn-primary" name="submit_receipt"><?= lang('Common.submit'); ?></button>
</div>
<?= form_close() ?>
<script type="text/javascript">
@@ -370,6 +235,7 @@
},
success: function(response) {
$.notify({
icon: 'bi bi-bell-fill',
message: response.message
}, {
type: response.success ? 'success' : 'danger'
@@ -379,7 +245,7 @@
});
},
errorLabelContainer: "#receipt_error_message_box",
errorLabelContainer: ".receipt_error_message_box",
rules: {
print_top_margin: {

View File

@@ -5,38 +5,28 @@
*/
?>
<?= form_open('config/saveRewards/', ['id' => 'reward_config_form', 'class' => 'form-horizontal']) ?>
<div id="config_wrapper">
<fieldset id="config_info">
<?= form_open('config/saveRewards/', ['id' => 'reward_config_form']) ?>
<div id="required_fields_message"><?= lang('Common.fields_required_message') ?></div>
<ul id="reward_error_message_box" class="error_message_box"></ul>
<?php
$title_info['config_title'] = lang('Config.reward_configuration');
echo view('configs/config_header', $title_info);
?>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.customer_reward_enable'), 'customer_reward_enable', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-1">
<?= form_checkbox([
'name' => 'customer_reward_enable',
'value' => 'customer_reward_enable',
'id' => 'customer_reward_enable',
'checked' => $config['customer_reward_enable'] == 1
]) ?>
</div>
</div>
<ul id="error_message_box" class="reward_error_message_box alert alert-warning d-none"></ul>
<div id="customer_rewards">
<?= view('partial/customer_rewards', ['customer_rewards' => $customer_rewards]) ?>
</div>
<?= form_submit([
'name' => 'submit_reward',
'id' => 'submit_reward',
'value' => lang('Common.submit'),
'class' => 'btn btn-primary btn-sm pull-right'
]) ?>
</fieldset>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="customer_reward_enable" name="customer_reward_enable" value="customer_reward_enable" <?= $config['customer_reward_enable'] == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="customer_reward_enable"><?= lang('Config.customer_reward_enable'); ?></label>
</div>
<div class="row" id="customer_rewards">
<?= view('partial/customer_rewards', ['customer_rewards' => $customer_rewards]) ?>
</div>
<div class="d-flex justify-content-end">
<button type="submit" class="btn btn-primary" name="submit_reward"><?= lang('Common.submit'); ?></button>
</div>
<?= form_close() ?>
<script type="text/javascript">
@@ -76,9 +66,9 @@
var new_block = block.insertAfter($(this).parent());
var new_block_id = 'customer_reward_' + ++id;
var new_block_id_next = 'reward_points_' + id;
$(new_block).find('label').html("<?= lang('Config.customer_reward') ?> " + ++table_count).attr('for', new_block_id).attr('class', 'control-label col-xs-2');
$(new_block).find("input[id='" + previous_id + "']").attr('id', new_block_id).removeAttr('disabled').attr('name', new_block_id).attr('class', 'form-control input-sm').val('');
$(new_block).find("input[id='" + previous_id_next + "']").attr('id', new_block_id_next).removeAttr('disabled').attr('name', new_block_id_next).attr('class', 'form-control input-sm').val('');
$(new_block).find('label').html("<?= lang('Config.customer_reward') ?> " + ++table_count).attr('for', new_block_id).attr('class', 'control-label col-xs-2'); // TODO-BS5 change classes from bs3 to bs5
$(new_block).find("input[id='" + previous_id + "']").attr('id', new_block_id).removeAttr('disabled').attr('name', new_block_id).attr('class', 'form-control input-sm').val(''); // TODO-BS5 change classes from bs3 to bs5
$(new_block).find("input[id='" + previous_id_next + "']").attr('id', new_block_id_next).removeAttr('disabled').attr('name', new_block_id_next).attr('class', 'form-control input-sm').val(''); // TODO-BS5 change classes from bs3 to bs5
hide_show_remove();
};
@@ -119,6 +109,7 @@
},
success: function(response) {
$.notify({
icon: 'bi bi-bell-fill',
message: response.message
}, {
type: response.success ? 'success' : 'danger'
@@ -129,7 +120,7 @@
});
},
errorLabelContainer: "#reward_error_message_box",
errorLabelContainer: ".reward_error_message_box",
rules: {
<?php

View File

@@ -0,0 +1,79 @@
<?php
/**
* @var array $config
* @var array $keyboardShortcutOptions
* @var array $keyboardShortcuts
*/
$keyboardShortcuts ??= [];
$keyboardShortcutOptions ??= [];
$config ??= [];
$shortcutLabels = [
'cancel' => lang('Sales.key_cancel'),
'items' => lang('Sales.key_item_search'),
'customers' => lang('Sales.key_customer_search'),
'suspend' => lang('Sales.key_suspend'),
'suspended' => lang('Sales.key_suspended'),
'amount' => lang('Sales.key_tendered'),
'payment' => lang('Sales.key_payment'),
'complete' => lang('Sales.key_finish_sale'),
'finish' => lang('Sales.key_finish_quote'),
'help' => lang('Sales.key_help_modal')
];
?>
<?= form_open('config/saveShortcuts', ['id' => 'shortcuts_config_form']) ?>
<?php
$title_info['config_title'] = lang('Config.shortcuts_configuration');
echo view('configs/config_header', $title_info);
?>
<ul id="error_message_box" class="shortcuts_error_message_box alert alert-warning d-none"></ul>
<div class="row">
<?php foreach ($shortcutLabels as $name => $label): ?>
<div class="col-12 col-lg-6">
<?= form_label($label, 'key_' . $name, ['class' => 'form-label']) ?>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-keyboard"></i></span>
<?php $keyboardShortcutSelectedValue = $keyboardShortcuts[$name]['value'] ?? ''; ?>
<?= form_dropdown('key_' . $name, $keyboardShortcutOptions, $keyboardShortcutSelectedValue, 'class="form-select"') ?>
</div>
</div>
<?php endforeach; ?>
</div>
<div class="d-flex justify-content-end">
<button type="submit" class="btn btn-primary" name="submit_shortcuts"><?= lang('Common.submit'); ?></button>
</div>
<?= form_close() ?>
<script type="text/javascript">
$('#shortcuts_config_form').validate($.extend(form_support.handler, {
submitHandler: function(form) {
$(form).ajaxSubmit({
success: function(response) {
$.notify({
message: response.message
}, {
type: response.success ? 'success' : 'danger'
});
},
error: function(xhr) {
const rawMessage = xhr.responseJSON?.message ?? xhr.responseText ?? <?= json_encode(lang('Config.shortcuts_save_error')) ?>;
$.notify({
message: DOMPurify.sanitize(rawMessage)
}, {
type: 'danger'
});
},
dataType: 'json'
});
},
errorLabelContainer: '.shortcuts_error_message_box'
}));
</script>

View File

@@ -4,26 +4,23 @@
*/
?>
<?= form_open('config/saveLocations/', ['id' => 'location_config_form', 'class' => 'form-horizontal']) ?>
<div id="config_wrapper">
<fieldset id="config_info">
<?= form_open('config/saveLocations/', ['id' => 'location_config_form']) ?>
<div id="required_fields_message"><?= lang('Common.fields_required_message') ?></div>
<ul id="stock_error_message_box" class="error_message_box"></ul>
<?php
$title_info['config_title'] = lang('Config.location_configuration');
echo view('configs/config_header', $title_info);
?>
<div id="stock_locations">
<?= view('partial/stock_locations', ['stock_locations' => $stock_locations]) ?>
</div>
<ul id="error_message_box" class="stock_error_message_box alert alert-warning d-none"></ul>
<?= form_submit([
'name' => 'submit_stock',
'id' => 'submit_stock',
'value' => lang('Common.submit'),
'class' => 'btn btn-primary btn-sm pull-right'
]) ?>
</fieldset>
<div id="stock_locations">
<?= view('partial/stock_locations', ['stock_locations' => $stock_locations]) ?>
</div>
<div class="d-flex justify-content-end">
<button type="submit" class="btn btn-primary" name="submit_stock"><?= lang('Common.submit'); ?></button>
</div>
<?= form_close() ?>
<script type="text/javascript">
@@ -43,8 +40,8 @@
var block = $(this).parent().clone(true);
var new_block = block.insertAfter($(this).parent());
var new_block_id = 'stock_location[]';
$(new_block).find('label').html("<?= lang('Config.stock_location') ?> " + ++location_count).attr('for', new_block_id).attr('class', 'control-label col-xs-2');
$(new_block).find('input').attr('id', new_block_id).removeAttr('disabled').attr('name', new_block_id).attr('class', 'form-control input-sm').val('');
$(new_block).find('label').html("<?= lang('Config.stock_location') ?> " + ++location_count).attr('for', new_block_id).attr('class', 'control-label col-xs-2'); // TODO-BS5 change classes from bs3 to bs5
$(new_block).find('input').attr('id', new_block_id).removeAttr('disabled').attr('name', new_block_id).attr('class', 'form-control input-sm').val(''); // TODO-BS5 change classes from bs3 to bs5
hide_show_remove();
};
@@ -79,6 +76,7 @@
$(form).ajaxSubmit({
success: function(response) {
$.notify({
icon: 'bi bi-bell-fill',
message: response.message
}, {
type: response.success ? 'success' : 'danger'
@@ -89,7 +87,7 @@
});
},
errorLabelContainer: "#stock_error_message_box",
errorLabelContainer: ".stock_error_message_box",
rules: {
<?php

View File

@@ -1,17 +0,0 @@
<br>
<div class="container-fluid">
<ul class="nav nav-tabs" id="myTabs" data-toggle="tab">
<li class="active"><a href="#system_tabs" data-toggle="tab" title="<?= lang('Config.system_conf') ?>"><?= lang('Config.system_conf') ?></a></li>
<li><a href="#email_tabs" data-toggle="tab" title="<?= lang('Config.email_configuration') ?>"><?= lang('Config.email') ?></a></li>
<li><a href="#message_tabs" data-toggle="tab" title="<?= lang('Config.message_configuration') ?>"><?= lang('Config.message') ?></a></li>
<li><a href="#integrations_tabs" data-toggle="tab" title="<?= lang('Config.integrations_configuration') ?>"><?= lang('Config.integrations') ?></a></li>
<li><a href="#license_tabs" data-toggle="tab" title="<?= lang('Config.license_configuration') ?>"><?= lang('Config.license') ?></a></li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="system_tabs"><?= view('configs/system_info') ?></div>
<div class="tab-pane" id="email_tabs"><?= view('configs/email_config') ?></div>
<div class="tab-pane" id="message_tabs"><?= view('configs/message_config') ?></div>
<div class="tab-pane" id="integrations_tabs"><?= view('configs/integrations_config') ?></div>
<div class="tab-pane" id="license_tabs"><br><?= view('configs/license_config') ?></div>
</div>
</div>

View File

@@ -6,48 +6,97 @@
use Config\OSPOS;
$logs = WRITEPATH . 'logs/';
$uploads = FCPATH . 'uploads/';
$images = FCPATH . 'uploads/item_pics/';
$importCustomers = WRITEPATH . '/uploads/importCustomers.csv'; //TODO: This variable does not follow naming conventions for the project.
$bullet = '&raquo;' . '&nbsp;';
$divider = ' &middot;' . '&nbsp;';
$enabled = '<span class="text-success">&#10003; Enabled</span>';
$disabled = '<span class="text-danger">&#10007; Disabled</span>';
$writable = '<span class="text-success">&#10003; Writable</span>';
$notwritable = '<span class="text-danger">&#10007; Not Writable</span>';
$readable = '<span class="text-success">&#10003; Readable</span>';
$notreadable = '<span class="text-danger">&#10007; Not Readable</span>';
$permissions_check = '<span class="text-success">&#10003; Security Check Passed</span>';
$permissions_fail = '<span class="text-danger">&#10007; Vulnerable or Incorrect Permissions</span>';
?>
<style>
a:hover {
cursor: pointer;
}
<?php
$title_info['config_title'] = lang('Config.system_info');
echo view('configs/config_header', $title_info);
?>
hidden {
visibility: hidden;
}
</style>
<div class="mb-3"><?= lang('Config.server_notice'); ?></div>
<script type="text/javascript" src="js/clipboard.min.js"></script>
<form id="copy-issue">
<div id="config_wrapper" class="col-sm-12">
<?= lang('Config.server_notice') ?>
<div class="container">
<div class="row">
<div class="col-sm-2" style="text-align: left;"><br>
<p style="min-height: 14.7em; font-weight: bold;">General Info</p>
<p style="min-height: 10.5em; font-weight: bold;">User Setup</p><br>
<p style="font-weight: bold;">Permissions</p>
<?php
if (!((substr(decoct(fileperms($logs)), -4) == 750)
&& (substr(decoct(fileperms($uploads)), -4) == 750)
&& (substr(decoct(fileperms($images)), -4) == 750)
&& ((substr(decoct(fileperms($importCustomers)), -4) == 640)
|| (substr(decoct(fileperms($importCustomers)), -4) == 660)))) {
echo '<div class="card border-danger-subtle mb-4">
<div class="card-header bg-danger-subtle border-danger-subtle fw-bold"><i class="bi bi-exclamation-circle"></i> ' . lang('Config.security_issue') . '</div>
<div class="card-body">
<p class="card-text">' . lang('Config.perm_risk') . '</p>
<ul class="list-unstyled mb-0">';
}
if (substr(decoct(fileperms($logs)), -4) != 750) {
echo '<li class="card-text">' . $bullet . '<code>writable/logs</code> ' . lang('Config.is_writable') . '</li>';
}
if (substr(decoct(fileperms($uploads)), -4) != 750) {
echo '<li class="card-text">' . $bullet . '<code>public/uploads</code> ' . lang('Config.is_writable') . '</li>';
}
if (substr(decoct(fileperms($images)), -4) != 750) {
echo '<li class="card-text">' . $bullet . '<code>public/uploads/item_pics</code> ' . lang('Config.is_writable') . '</li>';
}
if (!((substr(decoct(fileperms($importCustomers)), -4) == 640)
|| (substr(decoct(fileperms($importCustomers)), -4) == 660))) {
echo '<li class="card-text">' . $bullet . '<code>importCustomers.csv</code> ' . lang('Config.is_readable') . '</li>';
}
echo '</div></div>';
?>
<div class="row mb-3">
<label for="general-info" class="col-12 col-lg-2 form-label fw-bold">General Info</label>
<div class="col-12 col-lg-10" id="general-info">
<?= lang('Config.ospos_info') . ':&nbsp;' . esc(config('App')->application_version) . '&nbsp;-&nbsp;' . esc(substr(config(OSPOS::class)->commit_sha1, 0, 6)); ?><br>
<div>Language Code: <?= current_language_code(); ?></div><br>
<div id="time-error" class="row mb-3 d-none">
<div class="col-12 text-danger"><?= lang('Config.timezone_error'); ?></div>
<div class="col-6">
<label for="timezone"><?= lang('Config.user_timezone'); ?></label>
<div id="timezone"></div>
</div>
<div class="col-6">
<label for="ostimezone"><?= lang('Config.os_timezone'); ?></label>
<div id="ostimezone"><?= $config['timezone']; ?></div>
</div>
</div>
<div class="col-sm-8" id="issuetemplate" style="text-align: left;"><br>
<?= lang('Config.ospos_info') . ':' ?>
<?= esc(config('App')->application_version) ?> - <?= esc(substr(config(OSPOS::class)->commit_sha1, 0, 6)) ?><br>
Language Code: <?= current_language_code() ?><br><br>
<div id="TimeError"></div>
Extensions & Modules:<br>
<?php
echo "&#187; GD: ", extension_loaded('gd') ? '<span style="color: green;">Enabled &#x2713</span>' : '<span style="color: red;">Disabled &#x2717</span>', '<br>';
echo "&#187; BC Math: ", extension_loaded('bcmath') ? '<span style="color: green;">Enabled &#x2713</span>' : '<span style="color: red;">Disabled &#x2717</span>', '<br>';
echo "&#187; INTL: ", extension_loaded('intl') ? '<span style="color: green;">Enabled &#x2713</span>' : '<span style="color: red;">Disabled &#x2717</span>', '<br>';
echo "&#187; OpenSSL: ", extension_loaded('openssl') ? '<span style="color: green;">Enabled &#x2713</span>' : '<span style="color: red;">Disabled &#x2717</span>', '<br>';
echo "&#187; MBString: ", extension_loaded('mbstring') ? '<span style="color: green;">Enabled &#x2713</span>' : '<span style="color: red;">Disabled &#x2717</span>', '<br>';
echo "&#187; Curl: ", extension_loaded('curl') ? '<span style="color: green;">Enabled &#x2713</span>' : '<span style="color: red;">Disabled &#x2717</span>', '<br>';
echo "&#187; Json: ", extension_loaded('json') ? '<span style="color: green;">Enabled &#x2713</span>' : '<span style="color: red;">Disabled &#x2717</span>', '<br><br>';
echo "&#187; Xml: ", extension_loaded('xml') ? '<span style="color: green;">Enabled &#x2713</span>' : '<span style="color: red;">Disabled &#x2717</span>', '<br><br>';
?>
User Configuration:<br>
.Browser:
<?php
<span>Extensions & Modules:</span><br>
<ul class="list-unstyled">
<li><?= $bullet . 'GD: ', extension_loaded('gd') ? $enabled : $disabled; ?></li>
<li><?= $bullet . 'BC Math: ', extension_loaded('bcmath') ? $enabled : $disabled; ?></li>
<li><?= $bullet . 'INTL: ', extension_loaded('intl') ? $enabled : $disabled; ?></li>
<li><?= $bullet . 'OpenSSL: ', extension_loaded('openssl') ? $enabled : $disabled; ?></li>
<li><?= $bullet . 'MBString: ', extension_loaded('mbstring') ? $enabled : $disabled; ?></li>
<li><?= $bullet . 'Curl: ', extension_loaded('curl') ? $enabled : $disabled; ?></li>
<li><?= $bullet . 'Xml: ', extension_loaded('xml') ? $enabled : $disabled; ?></li>
</ul>
</div>
</div>
<div class="row mb-3">
<label for="user-setup" class="col-12 col-lg-2 form-label fw-bold">User Setup</label>
<div class="col-12 col-lg-10" id="user-setup">
<ul class="list-unstyled">
<?php
/**
* @param string $userAgent
* @return string
@@ -55,162 +104,169 @@ use Config\OSPOS;
function getBrowserNameAndVersion(string $userAgent): string
{
$browser = match (true) {
strpos($userAgent, 'Opera') !== false || strpos($userAgent, 'OPR/') !== false => 'Opera',
strpos($userAgent, 'Edge') !== false => 'Edge',
strpos($userAgent, 'Chrome') !== false => 'Chrome',
strpos($userAgent, 'Safari') !== false => 'Safari',
strpos($userAgent, 'Opera') !== false || strpos($userAgent, 'OPR/') !== false => 'Opera',
strpos($userAgent, 'Edge') !== false => 'Edge',
strpos($userAgent, 'Chrome') !== false => 'Chrome',
strpos($userAgent, 'Safari') !== false => 'Safari',
strpos($userAgent, 'Firefox') !== false => 'Firefox',
strpos($userAgent, 'MSIE') !== false || strpos($userAgent, 'Trident/7') !== false => 'Internet Explorer',
default => 'Other',
strpos($userAgent, 'MSIE') !== false || strpos($userAgent, 'Trident/7') !== false => 'Internet Explorer',
default => 'Other',
};
$version = match ($browser) {
'Opera' => preg_match('/(Opera|OPR)\/([0-9.]+)/', $userAgent, $matches) ? $matches[2] : '',
'Edge' => preg_match('/Edge\/([0-9.]+)/', $userAgent, $matches) ? $matches[1] : '',
'Chrome' => preg_match('/Chrome\/([0-9.]+)/', $userAgent, $matches) ? $matches[1] : '',
'Safari' => preg_match('/Version\/([0-9.]+)/', $userAgent, $matches) ? $matches[1] : '',
'Firefox' => preg_match('/Firefox\/([0-9.]+)/', $userAgent, $matches) ? $matches[1] : '',
'Opera' => preg_match('/(Opera|OPR)\/([0-9.]+)/', $userAgent, $matches) ? $matches[2] : '',
'Edge' => preg_match('/Edge\/([0-9.]+)/', $userAgent, $matches) ? $matches[1] : '',
'Chrome' => preg_match('/Chrome\/([0-9.]+)/', $userAgent, $matches) ? $matches[1] : '',
'Safari' => preg_match('/Version\/([0-9.]+)/', $userAgent, $matches) ? $matches[1] : '',
'Firefox' => preg_match('/Firefox\/([0-9.]+)/', $userAgent, $matches) ? $matches[1] : '',
'Internet Explorer' => preg_match('/(MSIE|rv:)([0-9.]+)/', $userAgent, $matches) ? $matches[2] : '',
default => '',
default => '',
};
return $browser . ($version ? ' ' . $version : '');
}
echo esc(getBrowserNameAndVersion($_SERVER['HTTP_USER_AGENT']));
?><br>
Server Software: <?= esc($_SERVER['SERVER_SOFTWARE']) ?><br>
PHP Version: <?= PHP_VERSION ?><br>
DB Version: <?= esc($dbVersion) ?><br>
Server Port: <?= esc($_SERVER['SERVER_PORT']) ?><br>
OS: <?= php_uname('s') . ' ' . php_uname('r') ?><br><br>
<br><br>
File Permissions:<br>
&#187; [writable/logs:]
<?php $logs = WRITEPATH . 'logs/';
$uploads = FCPATH. 'uploads/';
$images = FCPATH. 'uploads/item_pics/';
$importCustomers = WRITEPATH . '/uploads/importCustomers.csv'; // TODO: This variable does not follow naming conventions for the project.
if (is_writable($logs)) {
echo ' - ' . substr(sprintf("%o", fileperms($logs)), -4) . ' | ' . '<span style="color: green;"> Writable &#x2713 </span>';
} else {
echo ' - ' . substr(sprintf("%o", fileperms($logs)), -4) . ' | ' . '<span style="color: red;"> Not Writable &#x2717 </span>';
}
clearstatcache();
if (is_writable($logs) && substr(decoct(fileperms($logs)), -4) != 750) {
echo ' | <span style="color: red;">Vulnerable or Incorrect Permissions &#x2717</span>';
} else {
echo ' | <span style="color: green;">Security Check Passed &#x2713</span>';
}
clearstatcache();
?>
<br>
&#187; [public/uploads:]
<?php
if (is_writable($uploads)) {
echo ' - ' . substr(sprintf("%o", fileperms($uploads)), -4) . ' | ' . '<span style="color: green;"> Writable &#x2713 </span>';
} else {
echo ' - ' . substr(sprintf("%o", fileperms($uploads)), -4) . ' | ' . '<span style="color: red;"> Not Writable &#x2717 </span>';
}
clearstatcache();
if (is_writable($uploads) && substr(decoct(fileperms($uploads)), -4) != 750) {
echo ' | <span style="color: red;">Vulnerable or Incorrect Permissions &#x2717</span>';
} else {
echo ' | <span style="color: green;">Security Check Passed &#x2713 </span>';
}
clearstatcache();
?>
<br>
&#187; [public/uploads/item_pics:]
<?php
if (is_writable($images)) {
echo ' - ' . substr(sprintf("%o", fileperms($images)), -4) . ' | ' . '<span style="color: green;"> Writable &#x2713 </span>';
} else {
echo ' - ' . substr(sprintf("%o", fileperms($images)), -4) . ' | ' . '<span style="color: red;"> Not Writable &#x2717 </span>';
}
clearstatcache();
if (substr(decoct(fileperms($images)), -4) != 750) {
echo ' | <span style="color: red;">Vulnerable or Incorrect Permissions &#x2717</span>';
} else {
echo ' | <span style="color: green;">Security Check Passed &#x2713 </span>';
}
clearstatcache();
?>
<br>
&#187; [importCustomers.csv:]
<?php
if (is_readable($importCustomers)) {
echo ' - ' . substr(sprintf("%o", fileperms($importCustomers)), -4) . ' | ' . '<span style="color: green;"> Readable &#x2713 </span>';
} else {
echo ' - ' . substr(sprintf("%o", fileperms($importCustomers)), -4) . ' | ' . '<span style="color: red;"> Not Readable &#x2717 </span>';
}
clearstatcache();
if (!((substr(decoct(fileperms($importCustomers)), -4) == 640) || (substr(decoct(fileperms($importCustomers)), -4) == 660))) {
echo ' | <span style="color: red;">Vulnerable or Incorrect Permissions &#x2717</span>';
} else {
echo ' | <span style="color: green;">Security Check Passed &#x2713 </span>';
}
clearstatcache();
?>
<br>
<?php
if (!((substr(decoct(fileperms($logs)), -4) == 750)
&& (substr(decoct(fileperms($uploads)), -4) == 750)
&& (substr(decoct(fileperms($images)), -4) == 750)
&& ((substr(decoct(fileperms($importCustomers)), -4) == 640)
|| (substr(decoct(fileperms($importCustomers)), -4) == 660)))) {
echo '<br><span style="color: red;"><strong>' . lang('Config.security_issue') . '</strong> <br>' . lang('Config.perm_risk') . '</span><br>';
} else {
echo '<br><span style="color: green;">' . lang('Config.no_risk') . '</strong> <br> </span>';
}
if (substr(decoct(fileperms($logs)), -4) != 750) {
echo '<br><span style="color: red;"> &#187; [writable/logs:] ' . lang('Config.is_writable') . '</span>';
}
if (substr(decoct(fileperms($uploads)), -4) != 750) {
echo '<br><span style="color: red;"> &#187; [writable/uploads:] ' . lang('Config.is_writable') . '</span>';
}
if (substr(decoct(fileperms($images)), -4) != 750) {
echo '<br><span style="color: red;"> &#187; [writable/uploads/item_pics:] ' . lang('Config.is_writable') . '</span>';
}
if (!((substr(decoct(fileperms($importCustomers)), -4) == 640)
|| (substr(decoct(fileperms($importCustomers)), -4) == 660))) {
echo '<br><span style="color: red;"> &#187; [importCustomers.csv:] ' . lang('Config.is_readable') . '</span>';
}
?>
</div>
?>
<li><?= $bullet . 'Browser: ' . esc(getBrowserNameAndVersion($_SERVER['HTTP_USER_AGENT'])); ?></li>
<li><?= $bullet . 'Server Software: ' . esc($_SERVER['SERVER_SOFTWARE']); ?></li>
<li><?= $bullet . 'PHP Version: ' . PHP_VERSION; ?></li>
<li><?= $bullet . 'DB Version: ' . esc($dbVersion); ?></li>
<li><?= $bullet . 'Server Port: ' . esc($_SERVER['SERVER_PORT']); ?></li>
<li><?= $bullet . 'OS: ' . php_uname('s') . ' ' . php_uname('r'); ?></li>
</ul>
</div>
</div>
<div class="row mb-3">
<label for="permissions" class="col-12 col-lg-2 form-label fw-bold">Permissions</label>
<div class="col-12 col-lg-10" id="permissions">
<ul class="list-unstyled">
<li>
<?= $bullet; ?><code>writable/logs</code>
<?php
if (is_writable($logs)) {
echo substr(sprintf("%o", fileperms($logs)), -4) . $divider . $writable;
} else {
echo substr(sprintf("%o", fileperms($logs)), -4) . $divider . $notwritable;
}
clearstatcache();
echo $divider;
if (is_writable($logs) && substr(decoct(fileperms($logs)), -4) != 750) {
echo $permissions_fail;
} else {
echo $permissions_check;
}
clearstatcache();
?>
</li>
<li>
<?= $bullet; ?><code>public/uploads</code>
<?php
if(is_writable($uploads)) {
echo substr(sprintf("%o",fileperms($uploads)),-4) . $divider . $writable;
} else {
echo substr(sprintf("%o",fileperms($uploads)),-4) . $divider . $notwritable;
}
clearstatcache();
echo $divider;
if(is_writable($uploads) && substr(decoct(fileperms($uploads)), -4) != 750 ) {
echo $permissions_fail;
} else {
echo $permissions_check;
}
clearstatcache();
?>
</li>
<li>
<?= $bullet; ?><code>public/uploads/item_pics</code>
<?php
if (is_writable($images)) {
echo substr(sprintf("%o", fileperms($images)), -4) . $divider . $writable;
} else {
echo substr(sprintf("%o", fileperms($images)), -4) . $divider . $notwritable;
}
clearstatcache();
echo $divider;
if (substr(decoct(fileperms($images)), -4) != 750) {
echo $permissions_fail;
} else {
echo $permissions_check;
}
clearstatcache();
?>
</li>
<li>
<?= $bullet; ?><code>importCustomers.csv</code>
<?php
if (is_readable($importCustomers)) {
echo substr(sprintf("%o", fileperms($importCustomers)), -4) . $divider . $readable;
} else {
echo substr(sprintf("%o", fileperms($importCustomers)), -4) . $divider . $notreadable;
}
clearstatcache();
echo $divider;
if (!((substr(decoct(fileperms($importCustomers)), -4) == 640) || (substr(decoct(fileperms($importCustomers)), -4) == 660))) {
echo $permissions_fail;
} else {
echo $permissions_check;
}
clearstatcache();
?>
</li>
</ul>
<?php
if (((substr(decoct(fileperms($logs)), -4) == 750) && (substr(decoct(fileperms($uploads)), -4) == 750) && (substr(decoct(fileperms($images)), -4) == 750) && ((substr(decoct(fileperms($importCustomers)), -4) == 640) || (substr(decoct(fileperms($importCustomers)), -4) == 660)))) {
echo '<span class="text-success">' . lang('Config.no_risk') . '</span>';
}
?>
</div>
</div>
</form>
<div class="d-flex justify-content-center gap-3">
<button type="button" class="copy btn btn-secondary" data-clipboard-target="#copy-issue"><i class="bi bi-clipboard-plus"></i> Copy Info</button> <!-- TODO-BS5 add to translations -->
<a class="btn btn-secondary" href="https://github.com/opensourcepos/opensourcepos/issues/new" target="_blank" rel="noopener"><i class="bi bi-flag"></i> <?= lang('Config.report_an_issue') ?></a>
</div>
<div style="text-align: center;">
<a class="copy" data-clipboard-action="copy" data-clipboard-target="#issuetemplate">Copy Info</a> | <a href="https://github.com/opensourcepos/opensourcepos/issues/new" target="_blank"> <?= lang('Config.report_an_issue') ?></a>
<script type="text/javascript">
var clipboard = new ClipboardJS('.copy');
<script type="text/javascript">
var clipboard = new ClipboardJS('.copy');
clipboard.on('success', function(e) {
document.getSelection().removeAllRanges();
clipboard.on('success', function(e) {
document.getSelection().removeAllRanges();
$.notify({
icon: 'bi bi-clipboard-check-fill',
message: 'System info successfully copied.'
}, {
type: 'success'
});
});
$(function() {
$('#timezone').clone().appendTo('#timezoneE');
clipboard.on('error', function(e) {
$.notify({
icon: 'bi bi-clipboard-x-fill',
message: 'Something went wrong while copying.'
}, {
type: 'danger'
});
});
if ($('#timezone').html() !== $('#ostimezone').html()) {
document.getElementById("timezone").innerText = Intl.DateTimeFormat().resolvedOptions().timeZone;
document.getElementById("TimeError").innerHTML = '<span style="color: red;"><?= lang('Config.timezone_error') ?></span><br><br><?= lang('Config.user_timezone') ?><div id="timezoneE" style="font-weight:600;"></div><br><?= lang('Config.os_timezone') ?><div id="ostimezoneE" style="font-weight:600;"><?= esc($config['timezone']) ?></div><br>';
}
</script>
</div>
document.getElementById("timezone").innerText = Intl.DateTimeFormat().resolvedOptions().timeZone;
$(function() {
$('#timezone').clone().appendTo('#timezoneE');
});
if ($('#timezone').html() !== $('#ostimezone').html()) {
$('#time-error').removeClass('d-none');
};
</script>

View File

@@ -5,38 +5,28 @@
*/
?>
<?= form_open('config/saveTables/', ['id' => 'table_config_form', 'class' => 'form-horizontal']) ?>
<div id="config_wrapper">
<fieldset id="config_info">
<?= form_open('config/saveTables/', ['id' => 'table_config_form']) ?>
<div id="required_fields_message"><?= lang('Common.fields_required_message') ?></div>
<ul id="table_error_message_box" class="error_message_box"></ul>
<?php
$title_info['config_title'] = lang('Config.table_configuration');
echo view('configs/config_header', $title_info);
?>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.dinner_table_enable'), 'dinner_table_enable', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-1">
<?= form_checkbox([
'name' => 'dinner_table_enable',
'value' => 'dinner_table_enable',
'id' => 'dinner_table_enable',
'checked' => $config['dinner_table_enable'] == 1
]) ?>
</div>
</div>
<ul id="error_message_box" class="table_error_message_box alert alert-warning d-none"></ul>
<div id="dinner_tables">
<?= view('partial/dinner_tables', ['dinner_tables' => $dinner_tables]) ?>
</div>
<?= form_submit([
'name' => 'submit_table',
'id' => 'submit_table',
'value' => lang('Common.submit'),
'class' => 'btn btn-primary btn-sm pull-right'
]) ?>
</fieldset>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="dinner_table_enable" name="dinner_table_enable" value="dinner_table_enable" <?= $config['dinner_table_enable'] == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="dinner_table_enable"><?= lang('Config.dinner_table_enable'); ?></label>
</div>
<div class="row" id="dinner_tables">
<?= view('partial/dinner_tables', ['dinner_tables' => $dinner_tables]) ?>
</div>
<div class="d-flex justify-content-end">
<button type="submit" class="btn btn-primary" name="submit_table"><?= lang('Common.submit'); ?></button>
</div>
<?= form_close() ?>
<script type="text/javascript">
@@ -72,8 +62,8 @@
var block = $(this).parent().clone(true);
var new_block = block.insertAfter($(this).parent());
var new_block_id = 'dinner_table_' + ++id;
$(new_block).find('label').html("<?= lang('Config.dinner_table') ?> " + ++table_count).attr('for', new_block_id).attr('class', 'control-label col-xs-2');
$(new_block).find('input').attr('id', new_block_id).removeAttr('disabled').attr('name', new_block_id).attr('class', 'form-control input-sm').val('');
$(new_block).find('label').html("<?= lang('Config.dinner_table') ?> " + ++table_count).attr('for', new_block_id).attr('class', 'control-label col-xs-2'); // TODO-BS5 change classes from bs3 to bs5
$(new_block).find('input').attr('id', new_block_id).removeAttr('disabled').attr('name', new_block_id).attr('class', 'form-control input-sm').val(''); // TODO-BS5 change classes from bs3 to bs5
hide_show_remove();
};
@@ -114,6 +104,7 @@
},
success: function(response) {
$.notify({
icon: 'bi bi-bell-fill',
message: response.message
}, {
type: response.success ? 'success' : 'danger'

View File

@@ -8,136 +8,99 @@
*/
?>
<?= form_open('config/saveTax/', ['id' => 'tax_config_form', 'class' => 'form-horizontal']) ?>
<div id="config_wrapper">
<fieldset id="config_info">
<?= form_open('config/saveTax/', ['id' => 'tax_config_form']) ?>
<div id="required_fields_message"><?= lang('Common.fields_required_message') ?></div>
<ul id="tax_error_message_box" class="error_message_box"></ul>
<?php
$title_info['config_title'] = lang('Config.tax_configuration');
echo view('configs/config_header', $title_info);
?>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.tax_id'), 'tax_id', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_input([
'name' => 'tax_id',
'id' => 'tax_id',
'class' => 'form-control input-sm',
'value' => $config['tax_id']
]) ?>
</div>
<ul id="error_message_box" class="tax_error_message_box alert alert-warning d-none"></ul>
<div class="row">
<div class="col-12 col-lg-6">
<label for="tax_id" class="form-label"><?= lang('Config.tax_id'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-bank"></i></span>
<input type="text" name="tax_id" class="form-control" id="tax_id" value="<?= $config['tax_id']; ?>">
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.tax_included'), 'tax_included', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_checkbox([
'name' => 'tax_included',
'id' => 'tax_included',
'value' => 'tax_included',
'checked' => $config['tax_included'] == 1
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.default_tax_rate_1'), 'default_tax_1_rate', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_input([
'name' => 'default_tax_1_name',
'id' => 'default_tax_1_name',
'class' => 'form-control input-sm',
'value' => $config['default_tax_1_name'] !== false ? $config['default_tax_1_name'] : lang('Items.sales_tax_1')
]) ?>
</div>
<div class="col-xs-1 input-group">
<?= form_input([
'name' => 'default_tax_1_rate',
'id' => 'default_tax_1_rate',
'class' => 'form-control input-sm',
'value' => to_tax_decimals($config['default_tax_1_rate'])
]) ?>
<span class="input-group-addon input-sm">%</span>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.default_tax_rate_2'), 'default_tax_2_rate', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_input([
'name' => 'default_tax_2_name',
'id' => 'default_tax_2_name',
'class' => 'form-control input-sm',
'value' => $config['default_tax_2_name'] !== false ? $config['default_tax_2_name'] : lang('Items.sales_tax_2')
]) ?>
</div>
<div class="col-xs-1 input-group">
<?= form_input([
'name' => 'default_tax_2_rate',
'id' => 'default_tax_2_rate',
'class' => 'form-control input-sm',
'value' => to_tax_decimals($config['default_tax_2_rate'])
]) ?>
<span class="input-group-addon input-sm">%</span>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.use_destination_based_tax'), 'use_destination_based_tax', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_checkbox([
'name' => 'use_destination_based_tax',
'id' => 'use_destination_based_tax',
'value' => 'use_destination_based_tax',
'checked' => $config['use_destination_based_tax'] == 1
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.default_tax_code'), 'default_tax_code', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_dropdown(
'default_tax_code',
$tax_code_options,
$config['default_tax_code'],
'class="form-control input-sm"'
) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.default_tax_category'), 'default_tax_category', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_dropdown(
'default_tax_category',
$tax_category_options,
$config['default_tax_category'],
'class="form-control input-sm"'
) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Config.default_tax_jurisdiction'), 'default_tax_jurisdiction', ['class' => 'control-label col-xs-2']) ?>
<div class="col-xs-2">
<?= form_dropdown(
'default_tax_jurisdiction',
$tax_jurisdiction_options,
$config['default_tax_jurisdiction'],
'class="form-control input-sm"'
) ?>
</div>
</div>
<?= form_submit([
'name' => 'submit_tax',
'id' => 'submit_tax',
'value' => lang('Common.submit'),
'class' => 'btn btn-primary btn-sm pull-right'
]) ?>
</fieldset>
</div>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="tax_included" name="tax_included" <?= $config['tax_included'] == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="tax_included"><?= lang('Config.tax_included'); ?></label>
</div>
<div class="row">
<div class="col-12 col-lg-6">
<label for="default_tax_1_rate" class="form-label"><?= lang('Config.default_tax_rate_1') ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-1-square"></i></span>
<input type="text" class="form-control w-25" id="default_tax_1_name" name="default_tax_1_name" value="<?= $config['default_tax_1_name'] !== false ? $config['default_tax_1_name'] : lang('Items.sales_tax_1') ?>">
<input type="number" step="any" min="0" max="100" class="form-control" id="default_tax_1_rate" name="default_tax_1_rate" value="<?= to_tax_decimals($config['default_tax_1_rate']) ?>">
<span class="input-group-text"><i class="bi bi-percent"></i></span>
</div>
</div>
<div class="col-12 col-lg-6">
<label for="default_tax_2_rate" class="form-label"><?= lang('Config.default_tax_rate_2') ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-2-square"></i></span>
<input type="text" class="form-control w-25" id="default_tax_2_name" name="default_tax_2_name" value="<?= $config['default_tax_2_name'] !== false ? $config['default_tax_2_name'] : lang('Items.sales_tax_2') ?>">
<input type="number" step="any" min="0" max="100" class="form-control" id="default_tax_2_rate" name="default_tax_2_rate" value="<?= to_tax_decimals($config['default_tax_2_rate']) ?>">
<span class="input-group-text"><i class="bi bi-percent"></i></span>
</div>
</div>
</div>
<div class="form-check form-switch mb-3">
<input class="form-check-input" type="checkbox" role="switch" id="use_destination_based_tax" name="use_destination_based_tax" value="use_destination_based_tax" <?= $config['use_destination_based_tax'] == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="use_destination_based_tax"><?= lang('Config.use_destination_based_tax'); ?></label>
</div>
<div class="row">
<div class="col-12 col-lg-6">
<label for="default_tax_code" class="form-label"><?= lang('Config.default_tax_code'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-code"></i></span>
<select class="form-select" name="default_tax_code" id="default_tax_code">
<?php foreach ($tax_code_options as $key => $value): ?>
<option value="<?= $key ?>" <?= $config['default_tax_code'] == $key ? 'selected' : '' ?>><?= $value ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="col-12 col-lg-6">
<label for="default_tax_category" class="form-label"><?= lang('Config.default_tax_category'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-bookmark"></i></span>
<select class="form-select" name="default_tax_category" id="default_tax_category">
<?php foreach ($tax_category_options as $key => $value): ?>
<option value="<?= $key ?>" <?= $config['default_tax_category'] == $key ? 'selected' : '' ?>><?= $value ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="col-12 col-lg-6">
<label for="default_tax_jurisdiction" class="form-label"><?= lang('Config.default_tax_jurisdiction'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-globe"></i></span>
<select class="form-select" name="default_tax_jurisdiction" id="default_tax_jurisdiction">
<?php foreach ($tax_jurisdiction_options as $key => $value): ?>
<option value="<?= $key ?>" <?= $config['default_tax_jurisdiction'] == $key ? 'selected' : '' ?>><?= $value ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
</div>
<div class="d-flex justify-content-end">
<button type="submit" class="btn btn-primary" name="submit_tax"><?= lang('Common.submit'); ?></button>
</div>
<?= form_close() ?>
<script type="text/javascript">
@@ -168,6 +131,7 @@
},
success: function(response) {
$.notify({
icon: 'bi bi-bell-fill',
message: response.message
}, {
type: response.success ? 'success' : 'danger'

View File

@@ -11,433 +11,239 @@
*/
?>
<div id="required_fields_message"><?= lang('Common.fields_required_message') ?></div>
<ul id="error_message_box" class="error_message_box"></ul>
<?= form_open("$controller_name/save/$person_info->person_id", ['id' => 'customer_form']) ?>
<?= form_open("$controller_name/save/$person_info->person_id", ['id' => 'customer_form', 'class' => 'form-horizontal']) ?>
<?php if (!empty($stats) || (!empty($mailchimp_info) && !empty($mailchimp_activity))) { ?>
<ul class="nav nav-pills nav-justified mb-3" role="tablist">
<li class="nav-item" role="presentation">
<button type="button" class="nav-link active" data-bs-toggle="pill" data-bs-target="#customer_basic_info" role="tab"><?= lang('Customers.basic_information') ?></button>
</li>
<?php if (!empty($stats)) { ?>
<li class="nav-item" role="presentation">
<button type="button" class="nav-link" data-bs-toggle="pill" data-bs-target="#customer_stats_info" role="tab"><?= lang('Customers.stats_info') ?></button>
</li>
<?php } ?>
<?php if (!empty($mailchimp_info) && !empty($mailchimp_activity)) { ?>
<li class="nav-item" role="presentation">
<button type="button" class="nav-link" data-bs-toggle="pill" data-bs-target="#customer_mailchimp_info" role="tab"><?= lang('Customers.mailchimp_info') ?></button>
</li>
<?php } ?>
</ul>
<?php } ?>
<ul class="nav nav-tabs nav-justified" data-tabs="tabs">
<li class="active" role="presentation">
<a data-toggle="tab" href="#customer_basic_info"><?= lang('Customers.basic_information') ?></a>
</li>
<?php if (!empty($stats)) { ?>
<li role="presentation">
<a data-toggle="tab" href="#customer_stats_info"><?= lang('Customers.stats_info') ?></a>
</li>
<?php } ?>
<?php if (!empty($mailchimp_info) && !empty($mailchimp_activity)) { ?>
<li role="presentation">
<a data-toggle="tab" href="#customer_mailchimp_info"><?= lang('Customers.mailchimp_info') ?></a>
</li>
<?php } ?>
</ul>
<ul id="error_message_box" class="alert alert-warning d-none"></ul>
<div class="tab-content">
<div class="tab-pane fade in active" id="customer_basic_info">
<fieldset>
<div class="form-group form-group-sm">
<?= form_label(lang('Customers.consent'), 'consent', ['class' => 'required control-label col-xs-3']) ?>
<div class="col-xs-1">
<?= form_checkbox('consent', 1, $person_info->consent == '' ? !$config['enforce_privacy'] : (bool)$person_info->consent) ?>
</div>
<div class="tab-pane show active" id="customer_basic_info" role="tabpanel" tabindex="0">
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" name="consent" id="consent" value="1" required <?php $checked = ($person_info->consent == '' ? !$config['enforce_privacy'] : (bool)$person_info->consent); if ($checked) { echo 'checked';} ?>>
<label class="form-check-label" for="consent"><?= lang('Customers.consent') ?><sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup></label>
</div>
<?= view('people/form_basic_info') ?>
<label for="discount_type" class="form-label"><?= lang('Customers.discount_type') ?></label>
<div class="mb-3">
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="discount_type" id="discount_type_percent" value="0" <?php if ($person_info->discount_type == PERCENT) echo 'checked'; ?>>
<label class="form-check-label" for="discount_type_percent"><?= lang('Customers.discount_percent') ?></label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="discount_type" id="discount_type_fixed" value="1" <?php if ($person_info->discount_type == FIXED) echo 'checked'; ?>>
<label class="form-check-label" for="discount_type_fixed"><?= lang('Customers.discount_fixed') ?></label>
</div>
</div>
<label for="discount" class="form-label"><?= lang('Customers.discount'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="discount-icon"><i class="bi bi-patch-minus"></i></span>
<input type="number" step="any" class="form-control" name="discount" id="discount" aria-describedby="discount-icon" value="<?= $person_info->discount_type === FIXED ? to_currency_no_money($person_info->discount) : to_decimals($person_info->discount)?>">
</div>
<label for="company_name" class="form-label"><?= lang('Customers.company_name'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="company_name-icon"><i class="bi bi-building"></i></span>
<input type="text" class="form-control" name="company_name" id="company_name" aria-describedby="company_name-icon" value="<?= $person_info->company_name ?>">
</div>
<label for="account_number" class="form-label"><?= lang('Customers.account_number'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="account_number-icon"><i class="bi bi-hash"></i></span>
<input type="text" class="form-control" name="account_number" id="account_number" aria-describedby="account_number-icon" value="<?= $person_info->account_number ?>">
</div>
<label for="tax_id" class="form-label"><?= lang('Customers.tax_id'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="tax_id-icon"><i class="bi bi-bank"></i></span>
<input type="text" class="form-control" name="tax_id" id="tax_id" aria-describedby="tax_id-icon" value="<?= $person_info->tax_id ?>">
</div>
<?php if ($config['customer_reward_enable']): ?>
<label for="rewards" class="form-label"><?= lang('Customers.rewards_package'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-trophy"></i></span>
<select class="form-select" name="package_id">
<?php foreach ($packages as $id => $label): ?>
<option value="<?= $id ?>" <?= $id == $selected_package ? 'selected' : '' ?>><?= $label ?></option>
<?php endforeach; ?>
</select>
</div>
<?= view('people/form_basic_info') ?>
<div class="form-group form-group-sm">
<?= form_label(lang('Customers.discount_type'), 'discount_type', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<label class="radio-inline">
<?= form_radio([
'name' => 'discount_type',
'type' => 'radio',
'id' => 'discount_type',
'value' => 0,
'checked' => $person_info->discount_type == PERCENT
]) ?> <?= lang('Customers.discount_percent') ?>
</label>
<label class="radio-inline">
<?= form_radio([
'name' => 'discount_type',
'type' => 'radio',
'id' => 'discount_type',
'value' => 1,
'checked' => $person_info->discount_type == FIXED
]) ?> <?= lang('Customers.discount_fixed') ?>
</label>
</div>
<label for="available_points" class="form-label"><?= lang('Customers.available_points'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="available_points-icon"><i class="bi bi-hand-thumbs-up"></i></span>
<input type="text" class="form-control" name="available_points" id="available_points" aria-describedby="available_points-icon" value="<?= $person_info->points ?>" disabled readonly>
</div>
<?php endif; ?>
<div class="form-group form-group-sm">
<?= form_label(lang('Customers.discount'), 'discount', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-3">
<div class="input-group input-group-sm">
<?= form_input([
'name' => 'discount',
'id' => 'discount',
'class' => 'form-control input-sm',
'onClick' => 'this.select();',
'value' => $person_info->discount_type === FIXED ? to_currency_no_money($person_info->discount) : to_decimals($person_info->discount)
]) ?>
</div>
</div>
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" name="taxable" id="taxable" value="1" <?php if ($person_info->taxable == 1) echo 'checked'; ?>>
<label class="form-check-label" for="taxable"><?= lang('Customers.taxable') ?></label>
</div>
<?php if ($use_destination_based_tax): ?>
<label for="sales_tax_code_name" class="form-label"><?= lang('Customers.tax_code'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="sales_tax_code_name-icon"><i class="bi bi-bank"></i></span>
<input type="hidden" name="sales_tax_code_id" value="<?= $person_info->sales_tax_code_id ?>">
<input type="text" class="form-control" name="sales_tax_code_name" id="sales_tax_code_name" aria-describedby="sales_tax_code_name-icon" size="50" value="<?= $sales_tax_code_label ?>">
</div>
<?php endif; ?>
<div class="form-group form-group-sm">
<?= form_label(lang('Customers.company_name'), 'customer_company_name', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_input([
'name' => 'company_name',
'id' => 'customer_company_name',
'class' => 'form-control input-sm',
'value' => $person_info->company_name
]) ?>
</div>
</div>
<label for="datetime" class="form-label"><?= lang('Customers.date'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="datetime-icon"><i class="bi bi-calendar2"></i></span>
<input type="hidden" name="date" id="datetime" aria-describedby="datetime-icon" value="<?= to_datetime(strtotime($person_info->date)) ?>">
<input type="text" class="form-control" value="<?= to_datetime(strtotime($person_info->date)) ?>" disabled readonly>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Customers.account_number'), 'account_number', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-4">
<?= form_input([
'name' => 'account_number',
'id' => 'account_number',
'class' => 'form-control input-sm',
'value' => $person_info->account_number
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Customers.tax_id'), 'tax_id', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-4">
<?= form_input([
'name' => 'tax_id',
'id' => 'tax_id',
'class' => 'form-control input-sm',
'value' => $person_info->tax_id
]) ?>
</div>
</div>
<?php if ($config['customer_reward_enable']): ?>
<div class="form-group form-group-sm">
<?= form_label(lang('Customers.rewards_package'), 'rewards', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_dropdown(
'package_id',
$packages,
$selected_package,
'class="form-control input-sm"'
) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Customers.available_points'), 'available_points', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-4">
<?= form_input([
'name' => 'available_points',
'id' => 'available_points',
'class' => 'form-control input-sm',
'value' => $person_info->points,
'disabled' => ''
]) ?>
</div>
</div>
<?php endif; ?>
<div class="form-group form-group-sm">
<?= form_label(lang('Customers.taxable'), 'taxable', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-1">
<?= form_checkbox('taxable', 1, $person_info->taxable == 1) ?>
</div>
</div>
<?php if ($use_destination_based_tax) { ?>
<div class="form-group form-group-sm">
<?= form_label(lang('Customers.tax_code'), 'sales_tax_code_name', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<div class="input-group input-group-sm">
<?= form_input([
'name' => 'sales_tax_code_name',
'id' => 'sales_tax_code_name',
'class' => 'form-control input-sm',
'size' => '50',
'value' => $sales_tax_code_label
]) ?>
<?= form_hidden('sales_tax_code_id', $person_info->sales_tax_code_id) ?>
</div>
</div>
</div>
<?php } ?>
<div class="form-group form-group-sm">
<?= form_label(lang('Customers.date'), 'date', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<div class="input-group">
<span class="input-group-addon input-sm"><span class="glyphicon glyphicon-calendar"></span></span>
<?= form_input([
'name' => 'date',
'id' => 'datetime',
'class' => 'form-control input-sm',
'value' => to_datetime(strtotime($person_info->date)),
'readonly' => 'true'
]) ?>
</div>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Customers.employee'), 'employee', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_input([
'name' => 'employee',
'id' => 'employee',
'class' => 'form-control input-sm',
'value' => $employee,
'readonly' => 'true'
]) ?>
</div>
</div>
<?= form_hidden('employee_id', $person_info->employee_id) ?>
</fieldset>
<label for="employee" class="form-label"><?= lang('Customers.employee'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="employee-icon"><i class="bi bi-person"></i></span>
<input type="hidden" name="employee_id" value="<?= $person_info->employee_id ?>">
<input type="text" class="form-control" name="employee" id="employee" aria-describedby="employee-icon" value="<?= $employee ?>" disabled readonly>
</div>
</div>
<?php if (!empty($stats)) { ?>
<br>
<div class="tab-pane" id="customer_stats_info">
<fieldset>
<div class="form-group form-group-sm">
<?= form_label(lang('Customers.total'), 'total', ['class' => 'control-label col-xs-5']) ?>
<div class="col-xs-4">
<div class="input-group input-group-sm">
<?php if (!is_right_side_currency_symbol()): ?>
<span class="input-group-addon input-sm"><b><?= esc($config['currency_symbol']) ?></b></span>
<?php endif; ?>
<?= form_input([
'name' => 'total',
'id' => 'total',
'class' => 'form-control input-sm',
'value' => to_currency_no_money($stats->total),
'disabled' => ''
]) ?>
<?php if (is_right_side_currency_symbol()): ?>
<span class="input-group-addon input-sm"><b><?= esc($config['currency_symbol']) ?></b></span>
<?php endif; ?>
</div>
</div>
</div>
<div class="tab-pane" id="customer_stats_info" role="tabpanel" tabindex="0">
<label for="total" class="form-label"><?= lang('Customers.total'); ?></label>
<div class="input-group mb-3">
<?php if (!is_right_side_currency_symbol()): ?>
<span class="input-group-text" id="total-icon"><?= esc($config['currency_symbol']) ?></span>
<?php endif; ?>
<input type="text" class="form-control" name="total" id="total" aria-describedby="total-icon" value="<?= to_currency_no_money($stats->total) ?>" disabled readonly>
<?php if (is_right_side_currency_symbol()): ?>
<span class="input-group-text" id="total-icon"><?= esc($config['currency_symbol']) ?></span>
<?php endif; ?>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Customers.max'), 'max', ['class' => 'control-label col-xs-5']) ?>
<div class="col-xs-4">
<div class="input-group input-group-sm">
<?php if (!is_right_side_currency_symbol()): ?>
<span class="input-group-addon input-sm"><b><?= esc($config['currency_symbol']) ?></b></span>
<?php endif; ?>
<?= form_input([
'name' => 'max',
'id' => 'max',
'class' => 'form-control input-sm',
'value' => to_currency_no_money($stats->max),
'disabled' => ''
]) ?>
<?php if (is_right_side_currency_symbol()): ?>
<span class="input-group-addon input-sm"><b><?= esc($config['currency_symbol']) ?></b></span>
<?php endif; ?>
</div>
</div>
</div>
<label for="max" class="form-label"><?= lang('Customers.max'); ?></label>
<div class="input-group mb-3">
<?php if (!is_right_side_currency_symbol()): ?>
<span class="input-group-text" id="max-icon"><?= esc($config['currency_symbol']) ?></span>
<?php endif; ?>
<input type="text" class="form-control" name="max" id="max" aria-describedby="max-icon" value="<?= to_currency_no_money($stats->max) ?>" disabled readonly>
<?php if (is_right_side_currency_symbol()): ?>
<span class="input-group-text" id="max-icon"><?= esc($config['currency_symbol']) ?></span>
<?php endif; ?>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Customers.min'), 'min', ['class' => 'control-label col-xs-5']) ?>
<div class="col-xs-4">
<div class="input-group input-group-sm">
<?php if (!is_right_side_currency_symbol()): ?>
<span class="input-group-addon input-sm"><b><?= esc($config['currency_symbol']) ?></b></span>
<?php endif; ?>
<?= form_input([
'name' => 'min',
'id' => 'min',
'class' => 'form-control input-sm',
'value' => to_currency_no_money($stats->min),
'disabled' => ''
]) ?>
<?php if (is_right_side_currency_symbol()): ?>
<span class="input-group-addon input-sm"><b><?= esc($config['currency_symbol']) ?></b></span>
<?php endif; ?>
</div>
</div>
</div>
<label for="min" class="form-label"><?= lang('Customers.min'); ?></label>
<div class="input-group mb-3">
<?php if (!is_right_side_currency_symbol()): ?>
<span class="input-group-text" id="min-icon"><?= esc($config['currency_symbol']) ?></span>
<?php endif; ?>
<input type="text" class="form-control" name="min" id="min" aria-describedby="min-icon" value="<?= to_currency_no_money($stats->min) ?>" disabled readonly>
<?php if (is_right_side_currency_symbol()): ?>
<span class="input-group-text" id="min-icon"><?= esc($config['currency_symbol']) ?></span>
<?php endif; ?>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Customers.average'), 'average', ['class' => 'control-label col-xs-5']) ?>
<div class="col-xs-4">
<div class="input-group input-group-sm">
<?php if (!is_right_side_currency_symbol()): ?>
<span class="input-group-addon input-sm"><b><?= esc($config['currency_symbol']) ?></b></span>
<?php endif; ?>
<?= form_input([
'name' => 'average',
'id' => 'average',
'class' => 'form-control input-sm',
'value' => to_currency_no_money($stats->average),
'disabled' => ''
]) ?>
<?php if (is_right_side_currency_symbol()): ?>
<span class="input-group-addon input-sm"><b><?= esc($config['currency_symbol']) ?></b></span>
<?php endif; ?>
</div>
</div>
</div>
<label for="average" class="form-label"><?= lang('Customers.average'); ?></label>
<div class="input-group mb-3">
<?php if (!is_right_side_currency_symbol()): ?>
<span class="input-group-text" id="average-icon"><?= esc($config['currency_symbol']) ?></span>
<?php endif; ?>
<input type="text" class="form-control" name="average" id="average" aria-describedby="average-icon" value="<?= to_currency_no_money($stats->average) ?>" disabled readonly>
<?php if (is_right_side_currency_symbol()): ?>
<span class="input-group-text" id="average-icon"><?= esc($config['currency_symbol']) ?></span>
<?php endif; ?>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Customers.quantity'), 'quantity', ['class' => 'control-label col-xs-5']) ?>
<div class="col-xs-4">
<div class="input-group input-group-sm">
<span class="input-group-addon input-sm"><b><?= '>' ?></b></span>
<?= form_input([
'name' => 'quantity',
'id' => 'quantity',
'class' => 'form-control input-sm',
'value' => to_quantity_decimals($stats->quantity),
'disabled' => ''
]) ?>
</div>
</div>
</div>
<label for="quantity" class="form-label"><?= lang('Customers.quantity'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="quantity-icon"><i class="bi bi-123"></i></span>
<input type="text" class="form-control" name="quantity" id="quantity" aria-describedby="quantity-icon" value="<?= to_quantity_decimals($stats->quantity) ?>" disabled readonly>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Customers.avg_discount'), 'avg_discount', ['class' => 'control-label col-xs-5']) ?>
<div class="col-xs-4">
<div class="input-group input-group-sm">
<?= form_input([
'name' => 'avg_discount',
'id' => 'avg_discount',
'class' => 'form-control input-sm',
'value' => to_decimals($stats->avg_discount),
'disabled' => ''
]) ?>
<span class="input-group-addon input-sm"><b>%</b></span>
</div>
</div>
</div>
</fieldset>
<label for="avg_discount" class="form-label"><?= lang('Customers.avg_discount'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="avg_discount-icon"><i class="bi bi-percent"></i></span>
<input type="text" class="form-control" name="avg_discount" id="avg_discount" aria-describedby="avg_discount-icon" value="<?= to_decimals($stats->avg_discount) ?>" disabled readonly>
</div>
</div>
<?php } ?>
<?php if (!empty($mailchimp_info) && !empty($mailchimp_activity)) { ?>
<div class="tab-pane" id="customer_mailchimp_info">
<fieldset>
<div class="form-group form-group-sm">
<?= form_label(lang('Customers.mailchimp_status'), 'mailchimp_status', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-4">
<?= form_dropdown(
'mailchimp_status',
[
'subscribed' => 'subscribed',
'unsubscribed' => 'unsubscribed',
'cleaned' => 'cleaned',
'pending' => 'pending'
],
$mailchimp_info['status'],
['id' => 'mailchimp_status', 'class' => 'form-control input-sm']
) ?>
</div>
</div>
<div class="tab-pane" id="customer_mailchimp_info" role="tabpanel" tabindex="0">
<label for="mailchimp_status" class="form-label"><?= lang('Customers.mailchimp_status'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-envelope-check"></i></span>
<select class="form-select" name="mailchimp_status" id="mailchimp_status">
<option value="subscribed" <?= $mailchimp_info['status'] === 'subscribed' ? 'selected' : '' ?>>Subscribed</option>
<option value="unsubscribed" <?= $mailchimp_info['status'] === 'unsubscribed' ? 'selected' : '' ?>>Unsubscribed</option>
<option value="cleaned" <?= $mailchimp_info['status'] === 'cleaned' ? 'selected' : '' ?>>Cleaned</option>
<option value="pending" <?= $mailchimp_info['status'] === 'pending' ? 'selected' : '' ?>>Pending</option>
</select>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Customers.mailchimp_vip'), 'mailchimp_vip', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-1">
<?= form_checkbox('mailchimp_vip', 1, $mailchimp_info['vip'] == 1) ?>
</div>
</div>
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" name="mailchimp_vip" id="mailchimp_vip" value="1" <?= $mailchimp_info['vip'] == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="mailchimp_vip"><?= lang('Customers.mailchimp_vip') ?></label>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Customers.mailchimp_member_rating'), 'mailchimp_member_rating', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-4">
<?= form_input([
'name' => 'mailchimp_member_rating',
'class' => 'form-control input-sm',
'value' => $mailchimp_info['member_rating'],
'disabled' => ''
]) ?>
</div>
</div>
<label for="mailchimp_member_rating" class="form-label"><?= lang('Customers.mailchimp_member_rating'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="mailchimp_member_rating-icon"><i class="bi bi-hand-thumbs-up"></i></span>
<input type="text" class="form-control" name="mailchimp_member_rating" id="mailchimp_member_rating" aria-describedby="mailchimp_member_rating-icon" value="<?= $mailchimp_info['member_rating'] ?>" disabled readonly>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Customers.mailchimp_activity_total'), 'mailchimp_activity_total', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-4">
<?= form_input([
'name' => 'mailchimp_activity_total',
'class' => 'form-control input-sm',
'value' => $mailchimp_activity['total'],
'disabled' => ''
]) ?>
</div>
</div>
<label for="mailchimp_activity_total" class="form-label"><?= lang('Customers.mailchimp_activity_total'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="mailchimp_activity_total-icon"><i class="bi bi-envelope-arrow-up"></i></span>
<input type="text" class="form-control" name="mailchimp_activity_total" id="mailchimp_activity_total" aria-describedby="mailchimp_activity_total-icon" value="<?= $mailchimp_activity['total'] ?>" disabled readonly>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Customers.mailchimp_activity_lastopen'), 'mailchimp_activity_lastopen', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-4">
<?= form_input([
'name' => 'mailchimp_activity_lastopen',
'class' => 'form-control input-sm',
'value' => $mailchimp_activity['lastopen'],
'disabled' => ''
]) ?>
</div>
</div>
<label for="mailchimp_activity_lastopen" class="form-label"><?= lang('Customers.mailchimp_activity_lastopen'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="mailchimp_activity_lastopen-icon"><i class="bi bi-calendar2-check"></i></span>
<input type="text" class="form-control" name="mailchimp_activity_lastopen" id="mailchimp_activity_lastopen" aria-describedby="mailchimp_activity_lastopen-icon" value="<?= $mailchimp_activity['lastopen'] ?>" disabled readonly>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Customers.mailchimp_activity_open'), 'mailchimp_activity_open', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-4">
<?= form_input([
'name' => 'mailchimp_activity_open',
'class' => 'form-control input-sm',
'value' => $mailchimp_activity['open'],
'disabled' => ''
]) ?>
</div>
</div>
<label for="mailchimp_activity_open" class="form-label"><?= lang('Customers.mailchimp_activity_open'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="mailchimp_activity_open-icon"><i class="bi bi-envelope-open"></i></span>
<input type="text" class="form-control" name="mailchimp_activity_open" id="mailchimp_activity_open" aria-describedby="mailchimp_activity_open-icon" value="<?= $mailchimp_activity['open'] ?>" disabled readonly>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Customers.mailchimp_activity_click'), 'mailchimp_activity_click', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-4">
<?= form_input([
'name' => 'mailchimp_activity_click',
'class' => 'form-control input-sm',
'value' => $mailchimp_activity['click'],
'disabled' => ''
]) ?>
</div>
</div>
<label for="mailchimp_activity_click" class="form-label"><?= lang('Customers.mailchimp_activity_click'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="mailchimp_activity_click-icon"><i class="bi bi-hand-index"></i></span>
<input type="text" class="form-control" name="mailchimp_activity_click" id="mailchimp_activity_click" aria-describedby="mailchimp_activity_click-icon" value="<?= $mailchimp_activity['click'] ?>" disabled readonly>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Customers.mailchimp_activity_unopen'), 'mailchimp_activity_unopen', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-4">
<?= form_input([
'name' => 'mailchimp_activity_unopen',
'class' => 'form-control input-sm',
'value' => $mailchimp_activity['unopen'],
'disabled' => ''
]) ?>
</div>
</div>
<label for="mailchimp_activity_unopen" class="form-label"><?= lang('Customers.mailchimp_activity_unopen'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="mailchimp_activity_unopen-icon"><i class="bi bi-envelope-slash"></i></span>
<input type="text" class="form-control" name="mailchimp_activity_unopen" id="mailchimp_activity_unopen" aria-describedby="mailchimp_activity_unopen-icon" value="<?= $mailchimp_activity['unopen'] ?>" disabled readonly>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Customers.mailchimp_email_client'), 'mailchimp_email_client', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-4">
<?= form_input([
'name' => 'mailchimp_email_client',
'class' => 'form-control input-sm',
'value' => $mailchimp_info['email_client'],
'disabled' => ''
]) ?>
</div>
</div>
</fieldset>
<label for="mailchimp_email_client" class="form-label"><?= lang('Customers.mailchimp_email_client'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="mailchimp_email_client-icon"><i class="bi bi-inbox"></i></span>
<input type="text" class="form-control" name="mailchimp_email_client" id="mailchimp_email_client" aria-describedby="mailchimp_email_client-icon" value="<?= $mailchimp_info['email_client'] ?>" disabled readonly>
</div>
</div>
<?php } ?>
</div>

View File

@@ -1,27 +1,22 @@
<ul id="error_message_box" class="error_message_box"></ul>
<?= form_open_multipart('customers/importCsvFile/', ['id' => 'csv_form']) ?>
<?= form_open_multipart('customers/importCsvFile/', ['id' => 'csv_form', 'class' => 'form-horizontal']) ?>
<fieldset id="item_basic_info">
<ul id="error_message_box" class="alert alert-warning d-none"></ul>
<div class="form-group form-group-sm">
<div class="col-xs-12">
<a href="<?= esc('customers/csv') ?>"><?= lang('Common.download_import_template') ?></a>
</div>
<a type="button" class="btn btn-secondary mb-3" href="<?= esc('customers/csv') ?>"><?= lang('Common.download_import_template') ?></a>
<div class="fileinput fileinput-new input-group mb-3" data-provides="fileinput">
<span class="input-group-text"><i class="bi bi-filetype-csv"></i></span>
<div class="form-control" data-trigger="fileinput">
<span class="fileinput-filename"></span>
</div>
<span class="input-group-text fileinput-exists" data-dismiss="fileinput" style="cursor: pointer;"><?= lang('Common.import_remove_file') ?></span>
<span class="input-group-text btn-file">
<span class="fileinput-new"><?= lang('Common.import_select_file') ?></span>
<span class="fileinput-exists"><?= lang('Common.import_change_file') ?></span>
<input type="file" id="file_path" name="file_path" accept=".csv">
</span>
</div>
<div class="form-group form-group-sm">
<div class="col-xs-12">
<div class="fileinput fileinput-new input-group" data-provides="fileinput">
<div class="form-control" data-trigger="fileinput"><i class="glyphicon glyphicon-file fileinput-exists"></i><span class="fileinput-filename"></span></div>
<span class="input-group-addon input-sm btn btn-default btn-file">
<span class="fileinput-new"><?= lang('Common.import_select_file') ?></span><span class="fileinput-exists"><?= lang('Common.import_change_file') ?></span><input type="file" id="file_path" name="file_path" accept=".csv">
</span>
<a href="#" class="input-group-addon input-sm btn btn-default fileinput-exists" data-dismiss="fileinput"><?= lang('Common.import_remove_file') ?></a>
</div>
</div>
</div>
</fieldset>
<?= form_close() ?>
<script type="text/javascript">

View File

@@ -8,152 +8,125 @@
*/
?>
<div id="required_fields_message"><?= lang('Common.fields_required_message') ?></div>
<ul id="error_message_box" class="error_message_box"></ul>
<?= form_open("$controller_name/save/$person_info->person_id", ['id' => 'employee_form']) ?>
<?= form_open("$controller_name/save/$person_info->person_id", ['id' => 'employee_form', 'class' => 'form-horizontal']) ?>
<ul class="nav nav-tabs nav-justified" data-tabs="tabs">
<li class="active" role="presentation">
<a data-toggle="tab" href="#employee_basic_info"><?= lang('Employees.basic_information') ?></a>
<ul class="nav nav-pills nav-justified mb-3" role="tablist">
<li class="nav-item" role="presentation">
<button type="button" class="nav-link active" data-bs-toggle="pill" data-bs-target="#employee_basic_info" role="tab"><?= lang('Employees.basic_information') ?></button>
</li>
<li role="presentation">
<a data-toggle="tab" href="#employee_login_info"><?= lang('Employees.login_info') ?></a>
<li class="nav-item" role="presentation">
<button type="button" class="nav-link" data-bs-toggle="pill" data-bs-target="#employee_login_info" role="tab"><?= lang('Employees.login_info') ?></button>
</li>
<li role="presentation">
<a data-toggle="tab" href="#employee_permission_info"><?= lang('Employees.permission_info') ?></a>
<li class="nav-item" role="presentation">
<button type="button" class="nav-link" data-bs-toggle="pill" data-bs-target="#employee_permission_info" role="tab"><?= lang('Employees.permission_info') ?></button>
</li>
</ul>
<ul id="error_message_box" class="alert alert-warning d-none"></ul>
<div class="tab-content">
<div class="tab-pane fade in active" id="employee_basic_info">
<fieldset>
<?= view('people/form_basic_info') ?>
</fieldset>
<div class="tab-pane show active" id="employee_basic_info" role="tabpanel" tabindex="0">
<?= view('people/form_basic_info') ?>
</div>
<div class="tab-pane" id="employee_login_info">
<fieldset>
<div class="form-group form-group-sm">
<?= form_label(lang('Employees.username'), 'username', ['class' => 'required control-label col-xs-3']) ?>
<div class="col-xs-8">
<div class="input-group">
<span class="input-group-addon input-sm"><span class="glyphicon glyphicon-user"></span></span>
<?= form_input([
'name' => 'username',
'id' => 'username',
'class' => 'form-control input-sm',
'value' => $person_info->username
]) ?>
</div>
</div>
</div>
<div class="tab-pane" id="employee_login_info" role="tabpanel" tabindex="0">
<label for="username" class="form-label"><?= lang('Employees.username'); ?><sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup></label>
<div class="input-group mb-3">
<span class="input-group-text" id="username-icon"><i class="bi bi-person"></i></span>
<input type="text" class="form-control" name="username" id="username" aria-describedby="username-icon" value="<?= $person_info->username; ?>" required>
</div>
<?php $password_label_attributes = $person_info->person_id == "" ? ['class' => 'required'] : []; ?>
<?php $password_label_attributes = $person_info->person_id == "" ? ['class' => 'required'] : []; ?>
<label for="password" class="form-label"><?= lang('Employees.password'); ?><sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup></label>
<div class="input-group mb-3">
<span class="input-group-text" id="password-icon"><i class="bi bi-lock"></i></span>
<input type="password" class="form-control" name="password" id="password" aria-describedby="password-icon" required>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Employees.password'), 'password', array_merge($password_label_attributes, ['class' => 'control-label col-xs-3'])) ?>
<div class="col-xs-8">
<div class="input-group">
<span class="input-group-addon input-sm"><span class="glyphicon glyphicon-lock"></span></span>
<?= form_password([
'name' => 'password',
'id' => 'password',
'class' => 'form-control input-sm'
]) ?>
</div>
</div>
</div>
<label for="repeat_password" class="form-label"><?= lang('Employees.repeat_password'); ?><sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup></label>
<div class="input-group mb-3">
<span class="input-group-text" id="repeat_password-icon"><i class="bi bi-lock"></i></span>
<input type="password" class="form-control" name="repeat_password" id="repeat_password" aria-describedby="repeat_password-icon" required>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Employees.repeat_password'), 'repeat_password', array_merge($password_label_attributes, ['class' => 'control-label col-xs-3'])) ?>
<div class="col-xs-8">
<div class="input-group">
<span class="input-group-addon input-sm"><span class="glyphicon glyphicon-lock"></span></span>
<?= form_password([
'name' => 'repeat_password',
'id' => 'repeat_password',
'class' => 'form-control input-sm'
]) ?>
</div>
</div>
</div>
<label for="language" class="form-label"><?= lang('Employees.language'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="language-icon"><i class="bi bi-globe"></i></span>
<?php
$languages = get_languages();
$languages[':'] = lang('Employees.system_language');
$language_code = current_language_code();
$language = current_language();
<div class="form-group form-group-sm">
<?= form_label(lang('Employees.language'), 'language', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<div class="input-group">
<?php
$languages = get_languages();
$languages[':'] = lang('Employees.system_language');
$language_code = current_language_code();
$language = current_language();
// If No language is set then it will display "System Language"
if ($language_code === current_language_code(true)) {
$language_code = '';
$language = '';
}
// If No language is set then it will display "System Language"
if ($language_code === current_language_code(true)) {
$language_code = '';
$language = '';
}
echo form_dropdown(
'language',
$languages,
"$language_code:$language",
['class' => 'form-control input-sm']
);
?>
</div>
</div>
</div>
</fieldset>
echo form_dropdown(
'language',
$languages,
"$language_code:$language",
['class' => 'form-select']
);
?>
</div>
</div>
<div class="tab-pane" id="employee_permission_info">
<fieldset>
<p><?= lang('Employees.permission_desc') ?></p>
<div class="tab-pane" id="employee_permission_info" role="tabpanel" tabindex="0">
<div class="mb-3"><?= lang('Employees.permission_desc') ?></div>
<ul class="list-unstyled" id="permission_list">
<?php foreach ($all_modules as $module): ?>
<li class="form-check">
<input class="form-check-input module" type="checkbox" value="<?= $module->module_id ?>" name="grant_<?= $module->module_id ?>" id="grant_<?= $module->module_id ?>" <?= $module->grant == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="grant_<?= $module->module_id ?>">
<select class="form-select form-select-sm d-inline-block w-auto me-1 module" name="menu_group_<?= $module->module_id ?>">
<option value="home" <?= $module->menu_group == 'home' ? 'selected' : '' ?>>
<?= lang('Module.home') ?>
</option>
<option value="office" <?= $module->menu_group == 'office' ? 'selected' : '' ?>>
<?= lang('Module.office') ?>
</option>
<option value="both" <?= $module->menu_group == 'both' ? 'selected' : '' ?>>
<?= lang('Module.both') ?>
</option>
</select>
<span><?= lang("Module.$module->module_id") ?>:</span>
<span class="fw-light fst-italic"><?= lang("Module.$module->module_id" . '_desc') ?></span>
</label>
<ul id="permission_list">
<?php foreach ($all_modules as $module) { ?>
<li>
<?= form_checkbox("grant_$module->module_id", $module->module_id, $module->grant == 1, 'class="module"') ?>
<?= form_dropdown(
"menu_group_$module->module_id",
[
'home' => lang('Module.home'),
'office' => lang('Module.office'),
'both' => lang('Module.both')
],
$module->menu_group,
'class="module"'
) ?>
<span class="medium"><?= lang("Module.$module->module_id") ?>:</span>
<span class="small"><?= lang("Module.$module->module_id" . '_desc') ?></span>
<?php foreach ($all_subpermissions as $permission): ?>
<?php
foreach ($all_subpermissions as $permission) {
$exploded_permission = explode('_', $permission->permission_id, 2);
if ($permission->module_id == $module->module_id) {
$lang_key = $module->module_id . '.' . $exploded_permission[1];
$lang_line = lang(ucfirst($lang_key));
$lang_line = (lang(ucfirst($lang_key)) == $lang_line) ? ucwords(str_replace("_", " ", $exploded_permission[1])) : $lang_line;
if (!empty($lang_line)) {
?>
<ul>
<li>
<?= form_checkbox("grant_$permission->permission_id", $permission->permission_id, $permission->grant == 1) ?>
<?= form_hidden("menu_group_$permission->permission_id", "--") ?>
<span class="medium"><?= esc($lang_line) ?></span>
</li>
</ul>
<?php
}
if ($permission->module_id != $module->module_id) {
continue;
}
$lang_key = $module->module_id . '.' . $exploded_permission[1];
$lang_line = lang(ucfirst($lang_key));
// Fallback if language line doesn't exist
if ($lang_line === lang(ucfirst($lang_key))) {
$lang_line = ucwords(str_replace("_", " ", $exploded_permission[1]));
}
if (empty($lang_line)) {
continue;
}
}
?>
</li>
<?php } ?>
</ul>
</fieldset>
<ul class="list-unstyled">
<li class="form-check">
<input class="form-check-input module" type="checkbox" value="<?= $permission->permission_id ?>" name="grant_<?= $permission->permission_id ?>" id="grant_<?= $permission->permission_id ?>" <?= $permission->grant == 1 ? 'checked' : '' ?>>
<input type="hidden" name="menu_group_<?= $permission->permission_id ?>" value="--">
<label class="form-check-label" for="grant_<?= $permission->permission_id ?>"><?= esc($lang_line) ?></label>
</li>
</ul>
<?php endforeach; ?>
</li>
<?php endforeach; ?>
</ul>
</div>
</div>

View File

@@ -101,9 +101,11 @@ p.lead {
}
.tabs {
list-style: none inside none;
list-style: none;
list-style-position: inside;
margin: 0;
padding: 0;
margin: 0 0 -1px;
margin-bottom: -1px;
}
.tabs li {
display: inline;

View File

@@ -24,7 +24,7 @@
<?= form_label(lang('Expenses.date'), 'date', ['class' => 'required control-label col-xs-3']) ?>
<div class="col-xs-6">
<div class="input-group">
<span class="input-group-addon input-sm"><span class="glyphicon glyphicon-calendar"></span></span>
<span class="input-group-addon input-sm"><i class="bi bi-calendar2"></i></span>
<?= form_input([
'name' => 'date',
'class' => 'form-control input-sm datetime',
@@ -52,7 +52,7 @@
</div>
<div class="col-xs-2">
<a id="remove_supplier_button" class="btn btn-danger btn-sm" title="Remove Supplier">
<span class="glyphicon glyphicon-remove"></span>
<i class="bi bi-x-circle"></i>
</a>
</div>
</div>

View File

@@ -12,6 +12,11 @@
<?= view('partial/header') ?>
<?php
$title_info['config_title'] = 'Expenses';
echo view('configs/config_header', $title_info);
?>
<script type="text/javascript">
$(document).ready(function() {
// Load the preset datarange picker
@@ -54,29 +59,36 @@
<?= view('partial/print_receipt', ['print_after_sale' => false, 'selected_printer' => 'takings_printer']) ?>
<div id="title_bar" class="print_hide btn-toolbar">
<button onclick="printdoc()" class="btn btn-info btn-sm pull-right">
<span class="glyphicon glyphicon-print">&nbsp;</span><?= lang('Common.print') ?>
<div id="title_bar" class="d-flex gap-2 justify-content-end d-print-none">
<button type="button" class="btn btn-primary modal-launch" data-btn-submit="<?= lang('Common.submit') ?>" data-href="<?= "$controller_name/view" ?>" title="<?= lang(ucfirst($controller_name) . ".new") ?>">
<i class="bi bi-journal-check me-2"></i><?= lang(esc(ucfirst($controller_name)) . '.new') // TODO: String Interpolation ?>
</button>
<button class="btn btn-info btn-sm pull-right modal-dlg" data-btn-submit="<?= lang('Common.submit') ?>" data-href="<?= "$controller_name/view" ?>" title="<?= lang(ucfirst($controller_name) . '.new') ?>">
<span class="glyphicon glyphicon-tags">&nbsp;</span><?= lang(ucfirst($controller_name) . '.new') ?>
<button type="button" class="btn btn-primary" onclick="window.print()" title="<?= lang('Common.print') ?>">
<i class="bi bi-printer me-2"></i><?= lang('Common.print') ?>
</button>
</div>
<div id="toolbar">
<div class="pull-left form-inline" role="toolbar">
<button id="delete" class="btn btn-default btn-sm print_hide">
<span class="glyphicon glyphicon-trash">&nbsp;</span><?= lang('Common.delete') ?>
<div class="d-flex gap-2">
<button type="button" id="delete" class="btn btn-secondary d-print-none">
<i class="bi bi-trash"></i><span class="d-none d-sm-inline ms-2"><?= lang('Common.delete') ?></span>
</button>
<?= form_input(['name' => 'daterangepicker', 'class' => 'form-control input-sm', 'id' => 'daterangepicker']) ?>
<?= form_multiselect('filters[]', esc($filters), $selected_filters ?? [], [
'id' => 'filters',
'data-none-selected-text' => lang('Common.none_selected_text'),
'class' => 'selectpicker show-menu-arrow',
'data-selected-text-format' => 'count > 1',
'data-style' => 'btn-default btn-sm',
'data-width' => 'fit'
]) ?>
<div class="input-group w-auto">
<span class="input-group-text" id="daterangepicker-icon"><i class="bi bi-calendar2-range"></i></span>
<input type="text" class="form-select" name="daterangepicker" id="daterangepicker" aria-describedby="daterangepicker-icon">
</div>
<div class="input-group w-auto">
<span class="input-group-text" id="filters-icon"><i class="bi bi-funnel"></i></span>
<select class="form-select" name="filters[]" id="filters" aria-describedby="filters-icon" multiple>
<?php foreach (esc($filters) as $value => $label) { ?>
<option value="<?= $value ?>" <?= in_array($value, $selected_filters ?? []) ? 'selected' : '' ?>>
<?= $label ?>
</option>
<?php } ?>
</select>
</div>
</div>
</div>
@@ -87,3 +99,15 @@
<div id="payment_summary"></div>
<?= view('partial/footer') ?>
<script type="text/javascript">
new TomSelect('#filters', {
plugins: ['checkbox_options', 'remove_button'],
placeholder: '<?= lang('Common.none_selected_text') ?>',
hidePlaceholder: true,
closeAfterSelect: false,
onChange: function() {
$('#table').bootstrapTable('refresh');
}
});
</script>

View File

@@ -5,37 +5,22 @@
*/
?>
<div id="required_fields_message"><?= lang('Common.fields_required_message') ?></div>
<ul id="error_message_box" class="error_message_box"></ul>
<?= form_open("expenses_categories/save/$category_info->expense_category_id", ['id' => 'expense_category_edit_form']) ?>
<?= form_open("expenses_categories/save/$category_info->expense_category_id", ['id' => 'expense_category_edit_form', 'class' => 'form-horizontal']) ?>
<fieldset id="expenses_categories">
<ul id="error_message_box" class="alert alert-warning d-none"></ul>
<div class="form-group form-group-sm">
<?= form_label(lang('Expenses_categories.name'), 'category_name', ['class' => 'required control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_input([
'name' => 'category_name',
'id' => 'category_name',
'class' => 'form-control input-sm',
'value' => $category_info->category_name
]) ?>
</div>
</div>
<label for="category_name" class="form-label"><?= lang('Expenses_categories.name'); ?><sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup></label>
<div class="input-group mb-3">
<span class="input-group-text" id="category_name-icon"><i class="bi bi-bookmark"></i></span>
<input type="text" class="form-control" name="category_name" id="category_name" aria-describedby="category_name-icon" value="<?= $category_info->category_name; ?>" required>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Expenses_categories.description'), 'category_description', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_textarea([
'name' => 'category_description',
'id' => 'category_description',
'class' => 'form-control input-sm',
'value' => $category_info->category_description
]) ?>
</div>
</div>
<label for="category_description" class="form-label"><?= lang('Expenses_categories.description'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="category_description-icon"><i class="bi bi-card-text"></i></span>
<textarea class="form-control" name="category_description" id="category_description" rows="10" aria-describedby="category_description-icon"><?= $category_info->category_description ?></textarea>
</div>
</fieldset>
<?= form_close() ?>
<script type="text/javascript">

View File

@@ -8,6 +8,11 @@
<?= view('partial/header') ?>
<?php
$title_info['config_title'] = 'Expenses Categories';
echo view('configs/config_header', $title_info);
?>
<script type="text/javascript">
$(document).ready(function() {
<?= view('partial/bootstrap_tables_locale') ?>
@@ -27,16 +32,16 @@
});
</script>
<div id="title_bar" class="btn-toolbar">
<button class="btn btn-info btn-sm pull-right modal-dlg" data-btn-submit="<?= lang('Common.submit') ?>" data-href="<?= esc("$controller_name/view") ?>" title="<?= lang(ucfirst($controller_name) . '.new') ?>">
<span class="glyphicon glyphicon-list">&nbsp;</span><?= lang(ucfirst($controller_name) . '.new') ?>
<div class="d-flex gap-2 justify-content-end">
<button type="button" class="btn btn-primary modal-launch" data-btn-submit="<?= lang('Common.submit') ?>" data-href="<?= esc("$controller_name/view") ?>" title="<?= lang(ucfirst($controller_name) . '.new') ?>">
<i class="bi bi-bookmark-plus me-2"></i><?= lang(ucfirst($controller_name) . '.new') ?>
</button>
</div>
<div id="toolbar">
<div class="pull-left form-inline" role="toolbar">
<button id="delete" class="btn btn-default btn-sm print_hide">
<span class="glyphicon glyphicon-trash">&nbsp;</span><?= lang('Common.delete') ?>
<div class="d-flex gap-2">
<button type="button" class="btn btn-secondary" id="delete">
<i class="bi bi-trash"></i><span class="d-none d-sm-inline ms-2"><?= lang('Common.delete') ?></span>
</button>
</div>
</div>

View File

@@ -10,65 +10,42 @@
*/
?>
<div id="required_fields_message"><?= lang('Common.fields_required_message') ?></div>
<ul id="error_message_box" class="error_message_box"></ul>
<?= form_open("giftcards/save/$giftcard_id", ['id' => 'giftcard_form']) ?>
<?= form_open("giftcards/save/$giftcard_id", ['id' => 'giftcard_form', 'class' => 'form-horizontal']) ?>
<fieldset id="giftcard_basic_info">
<ul id="error_message_box" class="alert alert-warning d-none"></ul>
<div class="form-group form-group-sm">
<?= form_label(lang('Giftcards.person_id'), 'person_name', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_input([
'name' => 'person_name',
'id' => 'person_name',
'class' => 'form-control input-sm',
'value' => $selected_person_name
]) ?>
<?= form_hidden('person_id', (string)$selected_person_id) ?>
</div>
</div>
<label for="person_name" class="form-label"><?= lang('Giftcards.person_id'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="person_name-icon"><i class="bi bi-person"></i></span>
<input type="hidden" name="person_id" value="<?= (string)$selected_person_id ?>">
<input type="text" class="form-control" name="person_name" id="person_name" aria-describedby="person_name-icon" value="<?= $selected_person_name ?>">
</div>
<?php
$class = '';
if ($config['giftcard_number'] == 'series') {
$class = ' required';
}
?>
<div class="form-group form-group-sm">
<?= form_label(lang('Giftcards.giftcard_number'), 'giftcard_number', ['class' => "control-label col-xs-3$class"]) ?>
<div class="col-xs-4">
<?= form_input([
'name' => 'giftcard_number',
'id' => 'giftcard_number',
'class' => 'form-control input-sm',
'value' => $giftcard_number
]) ?>
</div>
</div>
<?php
$class = '';
$label = '';
if ($config['giftcard_number'] == 'series') {
$class = 'required';
$label = '<sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup>';
}
?>
<label for="giftcard_number" class="form-label"><?= lang('Giftcards.giftcard_number'); ?><?= $label ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="giftcard_number-icon"><i class="bi bi-gift"></i></span>
<input type="text" class="form-control" name="giftcard_number" id="giftcard_number" aria-describedby="giftcard_number-icon" value="<?= $giftcard_number ?>" <?= $class ?>>
</div>
<label for="giftcard_amount" class="form-label"><?= lang('Giftcards.card_value') ?><sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup></label>
<div class="input-group mb-3">
<?php if (!is_right_side_currency_symbol()): ?>
<span class="input-group-text" id="giftcard_amount-icon"><?= esc($config['currency_symbol']) ?></span>
<?php endif; ?>
<input type="number" class="form-control" name="giftcard_amount" id="giftcard_amount" aria-describedby="giftcard_amount-icon" value="<?= number_format((float)$giftcard_value, 2, '.', '') ?>" required>
<?php if (is_right_side_currency_symbol()): ?>
<span class="input-group-text" id="giftcard_amount-icon"><?= esc($config['currency_symbol']) ?></span>
<?php endif; ?>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Giftcards.card_value'), 'giftcard_amount', ['class' => 'required control-label col-xs-3']) ?>
<div class="col-xs-4">
<div class="input-group input-group-sm">
<?php if (!is_right_side_currency_symbol()): ?>
<span class="input-group-addon input-sm"><?= esc($config['currency_symbol']) ?></span>
<?php endif; ?>
<?= form_input([
'name' => 'giftcard_amount',
'id' => 'giftcard_amount',
'class' => 'form-control input-sm',
'value' => to_currency_no_money($giftcard_value)
]) ?>
<?php if (is_right_side_currency_symbol()): ?>
<span class="input-group-addon input-sm"><b><?= esc($config['currency_symbol']) ?></span>
<?php endif; ?>
</div>
</div>
</div>
</fieldset>
<?= form_close() ?>
<script type="text/javascript">

View File

@@ -8,6 +8,11 @@
<?= view('partial/header') ?>
<?php
$title_info['config_title'] = 'Gift Cards';
echo view('configs/config_header', $title_info);
?>
<script type="text/javascript">
$(document).ready(function() {
<?= view('partial/bootstrap_tables_locale') ?>
@@ -20,16 +25,16 @@
});
</script>
<div id="title_bar" class="btn-toolbar">
<button class="btn btn-info btn-sm pull-right modal-dlg" data-btn-submit="<?= lang('Common.submit') ?>" data-href="<?= esc("$controller_name/view") ?>" title="<?= lang(ucfirst($controller_name) . '.new') ?>">
<span class="glyphicon glyphicon-heart">&nbsp;</span><?= lang(ucfirst($controller_name) . '.new') ?>
<div class="d-flex gap-2 justify-content-end">
<button type="button" class="btn btn-primary modal-launch" data-btn-submit="<?= lang('Common.submit') ?>" data-href="<?= esc("$controller_name/view") ?>" title="<?= lang(ucfirst($controller_name) . '.new') ?>">
<i class="bi bi-gift me-2"></i><?= lang(ucfirst($controller_name) .'.new') ?>
</button>
</div>
<div id="toolbar">
<div class="pull-left btn-toolbar">
<button id="delete" class="btn btn-default btn-sm">
<span class="glyphicon glyphicon-trash">&nbsp;</span><?= lang('Common.delete') ?>
<div class="d-flex gap-2">
<button type="button" class="btn btn-secondary">
<i class="bi bi-trash"></i><span class="d-none d-sm-inline ms-2"><?= lang('Common.delete') ?></span>
</button>
</div>
</div>

View File

@@ -1,130 +0,0 @@
<?php
/**
* @var object $person_info
*/
?>
<div id="required_fields_message"><?= lang('Common.fields_required_message') ?></div>
<ul id="error_message_box" class="error_message_box"></ul>
<?= form_open("home/save/$person_info->person_id", ['id' => 'employee_form', 'class' => 'form-horizontal']) ?>
<div class="tab-content">
<div class="tab-pane fade in active" id="employee_login_info">
<fieldset>
<div class="form-group form-group-sm">
<?= form_label(lang('Employees.username'), 'username', ['class' => 'required control-label col-xs-3']) ?>
<div class="col-xs-8">
<div class="input-group">
<span class="input-group-addon input-sm"><span class="glyphicon glyphicon-user"></span></span>
<?= form_input([
'name' => 'username',
'id' => 'username',
'class' => 'form-control input-sm',
'value' => $person_info->username,
'readonly' => 'true'
]) ?>
</div>
</div>
</div>
<?php $password_label_attributes = $person_info->person_id == "" ? ['class' => 'required'] : []; ?>
<div class="form-group form-group-sm">
<?= form_label(lang('Employees.current_password'), 'current_password', array_merge($password_label_attributes, ['class' => 'control-label col-xs-3'])) ?>
<div class="col-xs-8">
<div class="input-group">
<span class="input-group-addon input-sm"><span class="glyphicon glyphicon-lock"></span></span>
<?= form_password([
'name' => 'current_password',
'id' => 'current_password',
'class' => 'form-control input-sm'
]) ?>
</div>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Employees.password'), 'password', array_merge($password_label_attributes, ['class' => 'control-label col-xs-3'])) ?>
<div class="col-xs-8">
<div class="input-group">
<span class="input-group-addon input-sm"><span class="glyphicon glyphicon-lock"></span></span>
<?= form_password([
'name' => 'password',
'id' => 'password',
'class' => 'form-control input-sm'
]) ?>
</div>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Employees.repeat_password'), 'repeat_password', array_merge($password_label_attributes, ['class' => 'control-label col-xs-3'])) ?>
<div class="col-xs-8">
<div class="input-group">
<span class="input-group-addon input-sm"><span class="glyphicon glyphicon-lock"></span></span>
<?= form_password([
'name' => 'repeat_password',
'id' => 'repeat_password',
'class' => 'form-control input-sm'
]) ?>
</div>
</div>
</div>
</fieldset>
</div>
</div>
<?= form_close() ?>
<script type="text/javascript">
// Validation and submit handling
$(document).ready(function() {
$.validator.setDefaults({
ignore: []
});
$.validator.addMethod("notEqualTo", function(value, element, param) {
return this.optional(element) || value != $(param).val();
}, '<?= lang('Employees.password_not_must_match') ?>');
$('#employee_form').validate($.extend({
submitHandler: function(form) {
$(form).ajaxSubmit({
success: function(response) {
dialog_support.hide();
$.notify(response.message, {
type: response.success ? 'success' : 'danger'
});
},
dataType: 'json'
});
},
rules: {
current_password: {
required: true,
minlength: 8
},
password: {
required: true,
minlength: 8,
notEqualTo: "#current_password"
},
repeat_password: {
equalTo: "#password"
}
},
messages: {
password: {
required: "<?= lang('Employees.password_required') ?>",
minlength: "<?= lang('Employees.password_minlength') ?>"
},
repeat_password: {
equalTo: "<?= lang('Employees.password_must_match') ?>"
}
}
}, form_support.error));
});
</script>

View File

@@ -6,19 +6,6 @@
<?= view('partial/header') ?>
<script type="text/javascript">
dialog_support.init("a.modal-dlg");
</script>
<h3 class="text-center"><?= lang('Common.welcome_message') ?></h3>
<div id="home_module_list">
<?php foreach($allowed_modules as $module) { ?>
<div class="module_item" title="<?= lang("Module.$module->module_id" . '_desc') ?>">
<a href="<?= base_url($module->module_id) ?>"><img src="<?= base_url("images/menubar/$module->module_id.svg") ?>" style="border-width: 0; height: 64px; max-width: 64px;" alt="Menubar Image"></a>
<a href="<?= base_url($module->module_id) ?>"><?= lang("Module.$module->module_id") ?></a>
</div>
<?php } ?>
</div>
<?= view('home/modules') ?>
<?= view('partial/footer') ?>

View File

@@ -0,0 +1,16 @@
<h3 class="text-center pb-3 d-none d-lg-block"><?= lang('Common.welcome_message') ?></h3>
<section class="container-fluid d-flex flex-wrap justify-content-center gap-3 p-0 py-1 py-lg-0">
<?php foreach ($allowed_modules as $module) { ?>
<div class="border border-primary rounded shadow-sm bg-primary-subtle text-center d-block" title="<?= lang("Module.$module->module_id" . '_desc') ?>">
<a href="<?= base_url($module->module_id) ?>">
<img class="d-block mx-auto p-2" src="<?= base_url("images/menubar/$module->module_id.svg") ?>" alt="Menubar Image"> <!-- TODO-BS5 alt text translatable -->
</a>
<a href="<?= base_url($module->module_id) ?>">
<div class="tile-text rounded-bottom d-block bg-primary text-light fw-bold p-2">
<span><?= lang("Module.$module->module_id") ?></span>
</div>
</a>
</div>
<?php } ?>
</section>

View File

@@ -6,19 +6,6 @@
<?= view('partial/header') ?>
<script type="text/javascript">
dialog_support.init("a.modal-dlg");
</script>
<h3 class="text-center"><?= lang('Common.welcome_message') ?></h3>
<div id="office_module_list">
<?php foreach ($allowed_modules as $module) { ?>
<div class="module_item" title="<?= lang("Module.$module->module_id" . '_desc') ?>">
<a href="<?= base_url($module->module_id) ?>"><img src="<?= base_url("images/menubar/$module->module_id.svg") ?>" style="border-width: 0; height: 64px; max-width: 64px;" alt="Menubar Image"></a>
<a href="<?= base_url($module->module_id) ?>"><?= lang("Module.$module->module_id") ?></a>
</div>
<?php } ?>
</div>
<?= view('home/modules') ?>
<?= view('partial/footer') ?>

137
app/Views/home/profile.php Normal file
View File

@@ -0,0 +1,137 @@
<?php
$email = $user_info->email;
$size = 96;
$default = 'https://ui-avatars.com/api/?name=' . $user_info->first_name . '+' . $user_info->last_name . '&format=svg&size=' . $size;
$grav_url = 'https://www.gravatar.com/avatar/' . md5(strtolower(trim($email))) . '?d=' . urlencode($default) . '&s=' . $size;
?>
<div class="modal fade" id="profile-modal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<ul class="nav nav-pills nav-justified w-100 me-1 gap-1">
<li class="nav-item">
<button type="button" id="modal-button-profile" onclick="modalSwitchProfile()" class="nav-link active">Profile</button>
</li>
<li class="nav-item" title="<?= lang('Employees.change_password'); ?>">
<button type="button" id="modal-button-password" onclick="modalSwitchPassword()" class="nav-link"><?= lang('Employees.change_password'); ?></button>
</li>
</ul>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body text-start">
<div id="modal-profile">
<div class="container">
<table>
<tbody>
<tr>
<td class="pe-2"><img class="img-thumbnail rounded-circle" src="<?= $default; ?>" style="height: 48px;"></td>
<td class="align-middle"><h5><?= $user_info->first_name . '&nbsp;' . $user_info->last_name; ?></h5></td>
</tr>
</tbody>
</table>
<br>
<table>
<tbody>
<tr>
<td class="pe-3">Username</td>
<td><?= $user_info->username; ?></td>
</tr>
<tr>
<td class="pe-3"><?= lang('Common.id'); ?></td>
<td><?= $user_info->person_id; ?></td>
</tr>
<tr>
<td class="pe-3"><?= lang('Common.email'); ?></td>
<td><?= $user_info->email; ?></td>
</tr>
<tr>
<td class="pe-3"><?= lang('Common.phone_number'); ?></td>
<td><?= $user_info->phone_number; ?></td>
</tr>
<tr>
<td class="pe-3"><?= lang('Common.gender'); ?></td>
<td><?= $user_info->gender; ?></td>
</tr>
<tr>
<td class="pe-3"><?= lang('Common.address_1'); ?></td>
<td><?= $user_info->address_1; ?></td>
</tr>
<tr>
<td class="pe-3"><?= lang('Common.address_2'); ?></td>
<td><?= $user_info->address_2; ?></td>
</tr>
<tr>
<td class="pe-3"><?= lang('Common.city'); ?></td>
<td><?= $user_info->city; ?></td>
</tr>
<tr>
<td class="pe-3"><?= lang('Common.state'); ?></td>
<td><?= $user_info->state; ?></td>
</tr>
<tr>
<td class="pe-3"><?= lang('Common.zip'); ?></td>
<td><?= $user_info->zip; ?></td>
</tr>
<tr>
<td class="pe-3"><?= lang('Common.country'); ?></td>
<td><?= $user_info->country; ?></td>
</tr>
<tr>
<td class="pe-3"><?= lang('Common.comments'); ?></td>
<td><?= $user_info->comments; ?></td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="modal-password" class="d-none was-validated" novalidate>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-person"></i></span>
<div class="form-floating">
<input name="username" id="input-username" type="text" class="form-control" placeholder="<?= lang('Login.username'); ?>" value="<?= $user_info->username; ?>" disabled>
<label for="input-username"><?= lang('Login.username'); ?></label>
</div>
</div>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-lock"></i></span>
<div class="form-floating is-invalid">
<input name="password-current" id="input-password-current" type="password" class="form-control" placeholder="Current Password" required>
<label for="input-password-current">Current Password</label>
</div>
<div class="invalid-feedback">Please fill in your current password.</div>
</div>
<div class="form-text">Must be 8-20 characters long</div>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-lock"></i></span>
<div class="form-floating is-invalid">
<input name="password-new" id="input-password-new" type="password" class="form-control" placeholder="New Password" required>
<label for="input-password-new">New Password</label>
</div>
<div class="invalid-feedback">Please fill in a new password.</div>
</div>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-lock"></i></span>
<div class="form-floating is-invalid">
<input name="password-repeat" id="input-password-repeat" type="password" class="form-control" placeholder="Repeat Password" required>
<label for="input-password-repeat">Repeat Password</label>
</div>
<div class="invalid-feedback">Please repeat the new password.</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<a type="button" id="modal-button-logout" class="btn btn-danger" href="home/logout">
<i class="bi bi-power me-2"></i><?= lang('Login.logout'); ?>
</a>
<button type="button" id="modal-button-save" class="btn btn-primary d-none">
<i class="bi bi-floppy me-2"></i>Save
</button>
</div>
</div>
</div>
</div>

View File

@@ -8,200 +8,114 @@
*/
?>
<div id="required_fields_message"><?= lang('Common.fields_required_message') ?></div>
<ul id="error_message_box" class="error_message_box"></ul>
<?= form_open("item_kits/save/$item_kit_info->item_kit_id", ['id' => 'item_kit_form']) ?>
<?= form_open("item_kits/save/$item_kit_info->item_kit_id", ['id' => 'item_kit_form', 'class' => 'form-horizontal']) ?>
<fieldset id="item_kit_basic_info">
<ul id="error_message_box" class="alert alert-warning d-none"></ul>
<div class="form-group form-group-sm">
<?= form_label(lang('Item_kits.item_kit_number'), 'item_kit_number', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<div class="input-group">
<span class="input-group-addon input-sm"><span class="glyphicon glyphicon-barcode"></span></span>
<?= form_input([
'name' => 'item_kit_number',
'id' => 'item_kit_number',
'class' => 'form-control input-sm',
'value' => $item_kit_info->item_kit_number
]) ?>
</div>
</div>
<label for="item_kit_number" class="form-label"><?= lang('Item_kits.item_kit_number'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="item_kit_number-icon"><i class="bi bi-upc-scan"></i></span>
<input type="text" class="form-control" name="item_kit_number" id="item_kit_number" aria-describedby="item_kit_number-icon" value="<?= $item_kit_info->item_kit_number ?>">
</div>
<label for="name" class="form-label"><?= lang('Item_kits.name'); ?><sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup></label>
<div class="input-group mb-3">
<span class="input-group-text" id="name-icon"><i class="bi bi-tags"></i></span>
<input type="text" class="form-control" name="name" id="name" aria-describedby="name-icon" value="<?= $item_kit_info->name ?>" required>
</div>
<label for="item_name" class="form-label"><?= lang('Item_kits.find_kit_item'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="item_name-icon"><i class="bi bi-tag"></i></span>
<input type="hidden" name="kit_item_id" value="<?= (string)$selected_kit_item_id ?>">
<input type="text" class="form-control" name="item_name" id="item_name" aria-describedby="item_name-icon" value="<?= $selected_kit_item ?>">
</div>
<label for="kit_discount_type" class="form-label"><?= lang('Item_kits.discount_type') ?></label>
<div class="mb-3">
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="kit_discount_type" id="kit_discount_type_percent" value="0" <?= $item_kit_info->kit_discount_type == PERCENT ? 'checked' : '' ?>>
<label class="form-check-label" for="kit_discount_type_percent"><?= lang('Item_kits.discount_percent') ?></label>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Item_kits.name'), 'name', ['class' => 'required control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_input([
'name' => 'name',
'id' => 'name',
'class' => 'form-control input-sm',
'value' => $item_kit_info->name
]) ?>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="kit_discount_type" id="kit_discount_type_fixed" value="1" <?= $item_kit_info->kit_discount_type == FIXED ? 'checked' : '' ?>>
<label class="form-check-label" for="kit_discount_type_fixed"><?= lang('Item_kits.discount_fixed') ?></label>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Item_kits.find_kit_item'), 'item_name', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<div class="input-group input-group-sm">
<?= form_input([
'name' => 'item_name',
'id' => 'item_name',
'class' => 'form-control input-sm',
'size' => '50',
'value' => $selected_kit_item
]) ?>
<?= form_hidden('kit_item_id', (string)$selected_kit_item_id) ?>
<label for="kit_discount" class="form-label"><?= lang('Item_kits.discount'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="kit_discount-icon"><i class="bi bi-patch-minus"></i></span>
<input type="number" step="any" class="form-control" name="kit_discount" id="kit_discount" aria-describedby="kit_discount-icon" value="<?= $item_kit_info->kit_discount_type === FIXED ? to_currency_no_money($item_kit_info->kit_discount) : to_decimals($item_kit_info->kit_discount) ?>">
</div>
</div>
</div>
<label for="price_option" class="form-label"><?= lang('Item_kits.price_option') ?> <?= !empty($basic_version) ? '<sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup>' : '' ?></label>
<div class="mb-3">
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="price_option" id="price_option_kit_and_components" value="0" <?= $item_kit_info->price_option == PRICE_ALL ? 'checked' : '' ?> <?= !empty($basic_version) ? 'required' : '' ?>>
<label class="form-check-label" for="price_option_kit_and_components"><?= lang('Item_kits.kit_and_components') ?></label>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Item_kits.discount_type'), 'kit_discount_type', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<label class="radio-inline">
<?= form_radio([
'name' => 'kit_discount_type',
'type' => 'radio',
'value' => 0,
'checked' => $item_kit_info->kit_discount_type == PERCENT
]) ?> <?= lang('Item_kits.discount_percent') ?>
</label>
<label class="radio-inline">
<?= form_radio([
'name' => 'kit_discount_type',
'type' => 'radio',
'value' => 1,
'checked' => $item_kit_info->kit_discount_type == FIXED
]) ?> <?= lang('Item_kits.discount_fixed') ?>
</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="price_option" id="price_option_kit_only" value="1" <?= $item_kit_info->price_option == PRICE_KIT ? 'checked' : '' ?> <?= !empty($basic_version) ? 'required' : '' ?>>
<label class="form-check-label" for="price_option_kit_only"><?= lang('Item_kits.kit_only') ?></label>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Item_kits.discount'), 'kit_discount', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-3">
<div class="input-group input-group-sm">
<?= form_input([
'name' => 'kit_discount',
'size' => '5',
'maxlength' => '5',
'id' => 'kit_discount',
'class' => 'form-control input-sm',
'value' => $item_kit_info->kit_discount_type === FIXED ? to_currency_no_money($item_kit_info->kit_discount) : to_decimals($item_kit_info->kit_discount)
]) ?>
</div>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="price_option" id="price_option_kit_and_stock" value="2" <?= $item_kit_info->price_option == PRICE_KIT_ITEMS ? 'checked' : '' ?> <?= !empty($basic_version) ? 'required' : '' ?>>
<label class="form-check-label" for="price_option_kit_and_stock"><?= lang('Item_kits.kit_and_stock') ?></label>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Item_kits.price_option'), 'price_option', !empty($basic_version) ? ['class' => 'required control-label col-xs-3'] : ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<label class="radio-inline">
<?= form_radio([
'name' => 'price_option',
'type' => 'radio',
'value' => 0,
'checked' => $item_kit_info->price_option == PRICE_ALL
]) ?> <?= lang('Item_kits.kit_and_components') ?>
</label>
<label class="radio-inline">
<?= form_radio([
'name' => 'price_option',
'type' => 'radio',
'value' => 1,
'checked' => $item_kit_info->price_option == PRICE_KIT
]) ?> <?= lang('Item_kits.kit_only') ?>
</label>
<label class="radio-inline">
<?= form_radio([
'name' => 'price_option',
'type' => 'radio',
'value' => 2,
'checked' => $item_kit_info->price_option == PRICE_KIT_ITEMS // TODO: === for all of these?
]) ?> <?= lang('Item_kits.kit_and_stock') ?>
</label>
</div>
<label for="print_option" class="form-label"><?= lang('Item_kits.print_option') ?> <?= !empty($basic_version) ? '<sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup>' : '' ?></label>
<div class="mb-3">
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="print_option" id="print_option_all" value="0" <?= $item_kit_info->print_option == PRINT_ALL ? 'checked' : '' ?> <?= !empty($basic_version) ? 'required' : '' ?>>
<label class="form-check-label" for="print_option_all"><?= lang('Item_kits.all') ?></label>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Item_kits.print_option'), 'print_option', !empty($basic_version) ? ['class' => 'required control-label col-xs-3'] : ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<label class="radio-inline">
<?= form_radio([
'name' => 'print_option',
'type' => 'radio',
'value' => 0,
'checked' => $item_kit_info->print_option == PRINT_ALL
]) ?> <?= lang('Item_kits.all') ?>
</label>
<label class="radio-inline">
<?= form_radio([
'name' => 'print_option',
'type' => 'radio',
'value' => 1,
'checked' => $item_kit_info->print_option == PRINT_PRICED
]) ?> <?= lang('Item_kits.priced_only') ?>
</label>
<label class="radio-inline">
<?= form_radio([
'name' => 'print_option',
'type' => 'radio',
'value' => 2,
'checked' => $item_kit_info->print_option == PRINT_KIT
]) ?> <?= lang('Item_kits.kit_only') ?>
</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="print_option" id="print_option_priced_only" value="1" <?= $item_kit_info->print_option == PRINT_PRICED ? 'checked' : '' ?> <?= !empty($basic_version) ? 'required' : '' ?>>
<label class="form-check-label" for="print_option_priced_only"><?= lang('Item_kits.priced_only') ?></label>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Item_kits.description'), 'description', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_textarea([
'name' => 'description',
'id' => 'description',
'class' => 'form-control input-sm',
'value' => $item_kit_info->description
]) ?>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="print_option" id="print_option_kit_only" value="2" <?= $item_kit_info->print_option == PRINT_KIT ? 'checked' : '' ?> <?= !empty($basic_version) ? 'required' : '' ?>>
<label class="form-check-label" for="print_option_kit_only"><?= lang('Item_kits.kit_only') ?></label>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Item_kits.add_item'), 'item', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_input([
'name' => 'item',
'id' => 'item',
'class' => 'form-control input-sm'
]) ?>
</div>
</div>
<label for="description" class="form-label"><?= lang('Item_kits.description'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-chat"></i></span>
<textarea class="form-control" name="description" id="description" rows="6"><?= $item_kit_info->description ?></textarea>
</div>
<table id="item_kit_items" class="table table-striped table-hover">
<thead>
<label for="item" class="form-label"><?= lang('Item_kits.add_item'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="item-icon"><i class="bi bi-tag"></i></span>
<input type="text" class="form-control" name="item" id="item" aria-describedby="item-icon">
</div>
<div class="table-responsive">
<table class="table table-sm table-hover align-middle text-nowrap" id="item_kit_items">
<thead class="table-secondary">
<tr>
<th style="width: 10%;"><?= lang('Common.delete') ?></th>
<th style="width: 10%;"><?= lang('Item_kits.sequence') ?></th>
<th style="width: 60%;"><?= lang('Item_kits.item') ?></th>
<th style="width: 20%;"><?= lang('Item_kits.quantity') ?></th>
<th scope="col"><?= lang('Common.delete') ?></th>
<th scope="col"><?= lang('Item_kits.sequence') ?></th>
<th scope="col"><?= lang('Item_kits.item') ?></th>
<th scope="col"><?= lang('Item_kits.quantity') ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($item_kit_items as $item_kit_item) { ?>
<?php foreach ($item_kit_items as $item_kit_item): ?>
<tr>
<td><a href="#" onclick="return delete_item_kit_row(this);"><span class="glyphicon glyphicon-trash"></span></a></td>
<td><input class="quantity form-control input-sm" id="item_seq_<?= $item_kit_item['item_id'] ?>" name="item_kit_seq[<?= $item_kit_item['item_id'] ?>]" value="<?= parse_decimals($item_kit_item['kit_sequence'], 0) ?>"></td>
<td class="text-center"><a class="text-danger" href="#" onclick="return delete_item_kit_row(this);"><i class="bi bi-trash"></i></a></td>
<td class="text-center"><input class="quantity form-control" id="item_seq_<?= $item_kit_item['item_id'] ?>" name="item_kit_seq[<?= $item_kit_item['item_id'] ?>]" value="<?= parse_decimals($item_kit_item['kit_sequence'], 0) ?>"></td>
<td><?= esc($item_kit_item['name']) ?></td>
<td><input class="quantity form-control input-sm" id="item_qty_<?= $item_kit_item['item_id'] ?>" name="item_kit_qty[<?= $item_kit_item['item_id'] ?>]" value="<?= to_quantity_decimals($item_kit_item['quantity']) ?>"></td>
<td class="text-center"><input class="quantity form-control" id="item_qty_<?= $item_kit_item['item_id'] ?>" name="item_kit_qty[<?= $item_kit_item['item_id'] ?>]" value="<?= to_quantity_decimals($item_kit_item['quantity']) ?>"></td>
</tr>
<?php } ?>
<?php endforeach; ?>
</tbody>
</table>
</div>
</fieldset>
<?= form_close() ?>
<script type="text/javascript">
@@ -218,10 +132,10 @@
$('#item_kit_item_' + ui.item.value).val(parseFloat($('#item_kit_item_' + ui.item.value).val()) + 1);
} else {
$('#item_kit_items').append('<tr>' +
'<td><a href="#" onclick="return delete_item_kit_row(this);"><span class="glyphicon glyphicon-trash"></span></a></td>' +
'<td><input class="quantity form-control input-sm" id="item_seq_' + ui.item.value + '" name="item_kit_seq[' + ui.item.value + ']" value="0"></td>' +
'<td class="text-center"><a class="text-danger" href="#" onclick="return delete_item_kit_row(this);"><i class="bi bi-trash"></i></a></td>' +
'<td class="text-center"><input class="quantity form-control" id="item_seq_' + ui.item.value + '" name="item_kit_seq[' + ui.item.value + ']" value="0"></td>' +
'<td>' + DOMPurify.sanitize(ui.item.label) + '</td>' +
'<td><input class="quantity form-control input-sm" id="item_qty_' + ui.item.value + '" name="item_kit_qty[' + ui.item.value + ']" value="1"></td>' +
'<td class="text-center"><input class="quantity form-control" id="item_qty_' + ui.item.value + '" name="item_kit_qty[' + ui.item.value + ']" value="1"></td>' +
'</tr>');
}
$('#item').val('');

View File

@@ -8,6 +8,11 @@
<?= view('partial/header') ?>
<?php
$title_info['config_title'] = 'Item Kits';
echo view('configs/config_header', $title_info);
?>
<script type="text/javascript">
$(document).ready(function() {
<?= view('partial/bootstrap_tables_locale') ?>
@@ -28,20 +33,19 @@
});
</script>
<div id="title_bar" class="btn-toolbar">
<button class="btn btn-info btn-sm pull-right modal-dlg" data-btn-submit="<?= lang('Common.submit') ?>" data-href="<?= esc("$controller_name/view") ?>" title="<?= lang(ucfirst($controller_name) . '.new') ?>">
<span class="glyphicon glyphicon-tags">&nbsp;</span><?= lang(ucfirst($controller_name) . '.new') ?>
<div class="d-flex gap-2 justify-content-end">
<button type="button" class="btn btn-primary modal-launch" data-btn-submit="<?= lang('Common.submit') ?>" data-href="<?= esc("$controller_name/view") ?>" title="<?= lang(ucfirst($controller_name) . '.new') ?>">
<i class="bi bi-tags me-2"></i><?= lang(ucfirst($controller_name) . '.new') ?>
</button>
</div>
<div id="toolbar">
<div class="pull-left btn-toolbar">
<button id="delete" class="btn btn-default btn-sm">
<span class="glyphicon glyphicon-trash">&nbsp;</span><?= lang('Common.delete') ?>
<div class="d-flex gap-2">
<button type="button" class="btn btn-secondary" id="delete">
<i class="bi bi-trash"></i><span class="d-none d-sm-inline ms-2"><?= lang('Common.delete') ?></span>
</button>
<button id="generate_barcodes" class="btn btn-default btn-sm" data-href="<?= esc("$controller_name/generateBarcodes") ?>">
<span class="glyphicon glyphicon-barcode">&nbsp;</span><?= lang('Items.generate_barcodes') ?>
<button type="button" class="btn btn-secondary" id="generate_barcodes" data-href="<?= esc("$controller_name/generateBarcodes") ?>" title="<?= lang('Items.generate_barcodes') ?>">
<i class="bi bi-upc-scan"></i><span class="d-none d-sm-inline ms-2"><?= lang('Items.generate_barcodes') ?></span>
</button>
</div>
</div>

View File

@@ -25,430 +25,226 @@
*/
?>
<div id="required_fields_message"><?= lang('Common.fields_required_message') ?></div>
<ul id="error_message_box" class="error_message_box"></ul>
<?= form_open("items/save/$item_info->item_id", ['id' => 'item_form', 'enctype' => 'multipart/form-data']) ?>
<?= form_open("items/save/$item_info->item_id", ['id' => 'item_form', 'enctype' => 'multipart/form-data', 'class' => 'form-horizontal']) ?>
<fieldset id="item_basic_info">
<ul id="error_message_box" class="alert alert-warning d-none"></ul>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.item_number'), 'item_number', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<div class="input-group">
<span class="input-group-addon input-sm"><span class="glyphicon glyphicon-barcode"></span></span>
<?= form_input([
'name' => 'item_number',
'id' => 'item_number',
'class' => 'form-control input-sm',
'value' => $item_info->item_number
]) ?>
</div>
</div>
</div>
<label for="item_number" class="form-label"><?= lang('Items.item_number'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="item_number-icon"><i class="bi bi-upc-scan"></i></span>
<input type="text" class="form-control" name="item_number" id="item_number" aria-describedby="item_number-icon" value="<?= $item_info->item_number ?>">
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.name'), 'name', ['class' => 'required control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_input([
'name' => 'name',
'id' => 'name',
'class' => 'form-control input-sm',
'value' => $item_info->name
]) ?>
</div>
</div>
<label for="name" class="form-label"><?= lang('Items.name'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="name-icon"><i class="bi bi-tag"></i></span>
<input type="text" class="form-control" name="name" id="name" aria-describedby="name-icon" value="<?= $item_info->name ?>">
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.category'), 'category', ['class' => 'required control-label col-xs-3']) ?>
<div class="col-xs-8">
<div class="input-group">
<span class="input-group-addon input-sm"><span class="glyphicon glyphicon-tag"></span></span>
<?php
if ($config['category_dropdown']) {
echo form_dropdown('category', $categories, $selected_category, ['class' => 'form-control']);
} else {
echo form_input([
'name' => 'category',
'id' => 'category',
'class' => 'form-control input-sm',
'value' => $item_info->category
]);
}
?>
</div>
</div>
</div>
<div id="attributes">
<script type="text/javascript">
$('#attributes').load('<?= "items/attributes/$item_info->item_id" ?>');
</script>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.stock_type'), 'stock_type', !empty($basic_version) ? ['class' => 'required control-label col-xs-3'] : ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<label class="radio-inline">
<?= form_radio([
'name' => 'stock_type',
'type' => 'radio',
'id' => 'stock_type',
'value' => 0,
'checked' => $item_info->stock_type == HAS_STOCK
]) ?> <?= lang('Items.stock') ?>
</label>
<label class="radio-inline">
<?= form_radio([
'name' => 'stock_type',
'type' => 'radio',
'id' => 'stock_type',
'value' => 1,
'checked' => $item_info->stock_type == HAS_NO_STOCK
]) ?><?= lang('Items.nonstock') ?>
</label>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.type'), 'item_type', !empty($basic_version) ? ['class' => 'required control-label col-xs-3'] : ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<label class="radio-inline">
<?php
$radio_button = [
'name' => 'item_type',
'type' => 'radio',
'id' => 'item_type',
'value' => 0,
'checked' => $item_info->item_type == ITEM
];
if ($standard_item_locked) {
$radio_button['disabled'] = true;
}
echo form_radio($radio_button) ?> <?= lang('Items.standard') ?>
</label>
<label class="radio-inline">
<?php
$radio_button = [
'name' => 'item_type',
'type' => 'radio',
'id' => 'item_type',
'value' => 1,
'checked' => $item_info->item_type == ITEM_KIT
];
if ($item_kit_disabled) {
$radio_button['disabled'] = true;
}
echo form_radio($radio_button) ?> <?= lang('Items.kit') ?>
</label>
<?php if ($config['derive_sale_quantity'] == '1') { ?>
<label class="radio-inline">
<?= form_radio([
'name' => 'item_type',
'type' => 'radio',
'id' => 'item_type',
'value' => 2,
'checked' => $item_info->item_type == ITEM_AMOUNT_ENTRY
]) ?><?= lang('Items.amount_entry') ?>
</label>
<label for="category" class="form-label"><?= lang('Items.category'); ?><sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup></label>
<div class="input-group mb-3">
<span class="input-group-text" id="category-icon"><i class="bi bi-bookmark"></i></span>
<?php if ($config['category_dropdown']) { ?>
<select class="form-select" name="category" id="category" required>
<?php foreach ($categories as $key => $value) { ?>
<option value="<?= $key ?>" <?= $selected_category == $key ? 'selected' : '' ?>><?= $value ?></option>
<?php } ?>
<?php if ($allow_temp_item == 1) { ?>
<label class="radio-inline">
<?= form_radio([
'name' => 'item_type',
'type' => 'radio',
'id' => 'item_type',
'value' => 3,
'checked' => $item_info->item_type == ITEM_TEMP
]) ?> <?= lang('Items.temp') ?>
</label>
<?php } ?>
</div>
</select>
<?php } else { ?>
<input type="text" class="form-control" name="category" id="category" aria-describedby="category-icon" value="<?= $item_info->category ?>" required>
<?php } ?>
</div>
<div id="attributes">
<script type="text/javascript">
$('#attributes').load('<?= "items/attributes/$item_info->item_id" ?>');
</script>
</div>
<label for="stock_type" class="form-label"><?= lang('Items.stock_type') ?><?= !empty($basic_version) ? '<sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup>' : '' ?></label>
<div class="mb-3">
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="stock_type" id="stock_type_stock" value="0" <?= $item_info->stock_type == HAS_STOCK ? 'checked' : '' ?> <?= !empty($basic_version) ? 'required' : '' ?>>
<label class="form-check-label" for="stock_type_stock"><?= lang('Items.stock') ?></label>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.supplier'), 'supplier', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_dropdown('supplier_id', $suppliers, $selected_supplier, ['class' => 'form-control']) ?>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="stock_type" id="stock_type_nonstock" value="1" <?= $item_info->stock_type == HAS_NO_STOCK ? 'checked' : '' ?> <?= !empty($basic_version) ? 'required' : '' ?>>
<label class="form-check-label" for="stock_type_nonstock"><?= lang('Items.nonstock') ?></label>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.cost_price'), 'cost_price', ['class' => 'required control-label col-xs-3']) ?>
<div class="col-xs-4">
<div class="input-group input-group-sm">
<?php if (!is_right_side_currency_symbol()): ?>
<span class="input-group-addon input-sm"><b><?= esc($config['currency_symbol']) ?></b></span>
<?php endif; ?>
<?= form_input([
'name' => 'cost_price',
'id' => 'cost_price',
'class' => 'form-control input-sm',
'onClick' => 'this.select();',
'value' => to_currency_no_money($item_info->cost_price)
]) ?>
<?php if (is_right_side_currency_symbol()): ?>
<span class="input-group-addon input-sm"><b><?= esc($config['currency_symbol']) ?></b></span>
<?php endif; ?>
</div>
</div>
<label for="item_type" class="form-label"><?= lang('Items.type') ?><?= !empty($basic_version) ? '<sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup>' : '' ?></label>
<div class="mb-3">
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="item_type" id="item_type_standard" value="0" <?= $item_info->item_type == ITEM ? 'checked' : '' ?> <?= $standard_item_locked ? 'disabled readonly' : '' ?> <?= !empty($basic_version) ? 'required' : '' ?>>
<label class="form-check-label" for="item_type_standard"><?= lang('Items.standard') ?></label>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.unit_price'), 'unit_price', ['class' => 'required control-label col-xs-3']) ?>
<div class="col-xs-4">
<div class="input-group input-group-sm">
<?php if (!is_right_side_currency_symbol()): ?>
<span class="input-group-addon input-sm"><b><?= esc($config['currency_symbol']) ?></b></span>
<?php endif; ?>
<?= form_input([
'name' => 'unit_price',
'id' => 'unit_price',
'class' => 'form-control input-sm',
'onClick' => 'this.select();',
'value' => to_currency_no_money($item_info->unit_price)
]) ?>
<?php if (is_right_side_currency_symbol()): ?>
<span class="input-group-addon input-sm"><b><?= esc($config['currency_symbol']) ?></b></span>
<?php endif; ?>
</div>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="item_type" id="item_type_kit" value="1" <?= $item_info->item_type == ITEM_KIT ? 'checked' : '' ?> <?= $item_kit_disabled ? 'disabled readonly' : '' ?> <?= !empty($basic_version) ? 'required' : '' ?>>
<label class="form-check-label" for="item_type_kit"><?= lang('Items.kit') ?></label>
</div>
<?php if (!$use_destination_based_tax) { ?>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.tax_1'), 'tax_percent_1', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-4">
<?= form_input([
'name' => 'tax_names[]',
'id' => 'tax_name_1',
'class' => 'form-control input-sm',
'value' => $item_tax_info[0]['name'] ?? $config['default_tax_1_name']
]) ?>
</div>
<div class="col-xs-4">
<div class="input-group input-group-sm">
<?= form_input([
'name' => 'tax_percents[]',
'id' => 'tax_percent_name_1',
'class' => 'form-control input-sm',
'value' => isset($item_tax_info[0]['percent']) ? to_tax_decimals($item_tax_info[0]['percent']) : to_tax_decimals($default_tax_1_rate)
]) ?>
<span class="input-group-addon input-sm"><b>%</b></span>
</div>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.tax_2'), 'tax_percent_2', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-4">
<?= form_input([
'name' => 'tax_names[]',
'id' => 'tax_name_2',
'class' => 'form-control input-sm',
'value' => $item_tax_info[1]['name'] ?? $config['default_tax_2_name']
]) ?>
</div>
<div class="col-xs-4">
<div class="input-group input-group-sm">
<?= form_input([
'name' => 'tax_percents[]',
'class' => 'form-control input-sm',
'id' => 'tax_percent_name_2',
'value' => isset($item_tax_info[1]['percent']) ? to_tax_decimals($item_tax_info[1]['percent']) : to_tax_decimals($default_tax_2_rate)
]) ?>
<span class="input-group-addon input-sm"><b>%</b></span>
</div>
</div>
<?php if ($config['derive_sale_quantity'] == '1') { ?>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="item_type" id="item_type_amount_entry" value="2" <?= $item_info->item_type == ITEM_AMOUNT_ENTRY ? 'checked' : '' ?> <?= !empty($basic_version) ? 'required' : '' ?>>
<label class="form-check-label" for="item_type_amount_entry"><?= lang('Items.amount_entry') ?></label>
</div>
<?php } ?>
<?php if ($use_destination_based_tax): ?>
<div class="form-group form-group-sm">
<?= form_label(lang('Taxes.tax_category'), 'tax_category', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<div class="input-group input-group-sm">
<?= form_input([
'name' => 'tax_category',
'id' => 'tax_category',
'class' => 'form-control input-sm',
'size' => '50',
'value' => $tax_category
]) ?>
<?= form_hidden('tax_category_id', $tax_category_id) ?>
</div>
</div>
<?php if ($allow_temp_item == 1) { ?>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="item_type" id="item_type_temp" value="3" <?= $item_info->item_type == ITEM_TEMP ? 'checked' : '' ?> <?= !empty($basic_version) ? 'required' : '' ?>>
<label class="form-check-label" for="item_type_temp"><?= lang('Items.temp') ?></label>
</div>
<?php } ?>
</div>
<label for="supplier_id" class="form-label"><?= lang('Items.supplier'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-truck"></i></span>
<select class="form-select" name="supplier_id" id="supplier_id">
<?php foreach ($suppliers as $key => $value) { ?>
<option value="<?= $key ?>" <?= $selected_supplier == $key ? 'selected' : '' ?>><?= $value ?></option>
<?php } ?>
</select>
</div>
<label for="cost_price" class="form-label"><?= lang('Items.cost_price') ?><sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup></label>
<div class="input-group mb-3">
<?php if (!is_right_side_currency_symbol()): ?>
<span class="input-group-text" id="cost_price-icon"><?= esc($config['currency_symbol']) ?></span>
<?php endif; ?>
<?php if ($include_hsn): ?>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.hsn_code'), 'category', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<div class="input-group">
<?= form_input([
'name' => 'hsn_code',
'id' => 'hsn_code',
'class' => 'form-control input-sm',
'value' => $hsn_code
]) ?>
</div>
</div>
</div>
<input type="number" step="any" class="form-control" name="cost_price" id="cost_price" aria-describedby="cost_price-icon" value="<?= to_currency_no_money($item_info->cost_price) ?>" required>
<?php if (is_right_side_currency_symbol()): ?>
<span class="input-group-text" id="cost_price-icon"><?= esc($config['currency_symbol']) ?></span>
<?php endif; ?>
</div>
<?php foreach ($stock_locations as $key => $location_detail) { ?>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.quantity') . ' ' . $location_detail['location_name'], "quantity_$key", ['class' => 'required control-label col-xs-3']) ?>
<div class="col-xs-4">
<?= form_input([
'name' => "quantity_$key",
'id' => "quantity_$key",
'class' => 'required quantity form-control',
'onClick' => 'this.select();',
'value' => isset($item_info->item_id) ? to_quantity_decimals($location_detail['quantity']) : to_quantity_decimals(0)
]) ?>
</div>
</div>
<?php } ?>
<label for="unit_price" class="form-label"><?= lang('Items.unit_price') ?><sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup></label>
<div class="input-group mb-3">
<?php if (!is_right_side_currency_symbol()): ?>
<span class="input-group-text" id="unit_price-icon"><?= esc($config['currency_symbol']) ?></span>
<?php endif; ?>
<input type="number" step="any" class="form-control" name="unit_price" id="unit_price" aria-describedby="unit_price-icon" value="<?= to_currency_no_money($item_info->unit_price) ?>" required>
<?php if (is_right_side_currency_symbol()): ?>
<span class="input-group-text" id="unit_price-icon"><?= esc($config['currency_symbol']) ?></span>
<?php endif; ?>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.receiving_quantity'), 'receiving_quantity', ['class' => 'required control-label col-xs-3']) ?>
<div class="col-xs-4">
<?= form_input([
'name' => 'receiving_quantity',
'id' => 'receiving_quantity',
'class' => 'required form-control input-sm',
'onClick' => 'this.select();',
'value' => isset($item_info->item_id) ? to_quantity_decimals($item_info->receiving_quantity) : to_quantity_decimals(0)
]) ?>
</div>
<?php if (!$use_destination_based_tax): ?>
<label for="tax_name_1" class="form-label"><?= lang('Items.tax_1') ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="tax_name_1-icon"><i class="bi bi-piggy-bank"></i></span>
<input type="text" class="form-control w-25" name="tax_names[]" id="tax_name_1" aria-describedby="tax_name_1-icon" value="<?= $item_tax_info[0]['name'] ?? $config['default_tax_1_name'] ?>">
<input type="number" step="any" min="0" max="100" class="form-control" name="tax_percents[]" id="tax_percent_name_1" aria-describedby="tax_percent_name_1-icon" value="<?= isset($item_tax_info[0]['percent']) ? to_tax_decimals($item_tax_info[0]['percent']) : to_tax_decimals($default_tax_1_rate) ?>">
<span class="input-group-text" id="tax_percent_name_1-icon"><i class="bi bi-percent"></i></span>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.reorder_level'), 'reorder_level', ['class' => 'required control-label col-xs-3']) ?>
<div class="col-xs-4">
<?= form_input([
'name' => 'reorder_level',
'id' => 'reorder_level',
'class' => 'form-control input-sm',
'onClick' => 'this.select();',
'value' => isset($item_info->item_id) ? to_quantity_decimals($item_info->reorder_level) : to_quantity_decimals(0)
]) ?>
<label for="tax_name_2" class="form-label"><?= lang('Items.tax_2') ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="tax_name_2-icon"><i class="bi bi-piggy-bank"></i></span>
<input type="text" class="form-control w-25" name="tax_names[]" id="tax_name_2" aria-describedby="tax_name_2-icon" value="<?= $item_tax_info[1]['name'] ?? $config['default_tax_2_name'] ?>">
<input type="number" step="any" min="0" max="100" class="form-control" name="tax_percents[]" id="tax_percent_name_2" aria-describedby="tax_percent_name_2-icon" value="<?= isset($item_tax_info[1]['percent']) ? to_tax_decimals($item_tax_info[1]['percent']) : to_tax_decimals($default_tax_2_rate) ?>">
<span class="input-group-text" id="tax_percent_name_2-icon"><i class="bi bi-percent"></i></span>
</div>
<?php endif; ?>
<?php if ($use_destination_based_tax): ?>
<label for="tax_category" class="form-label"><?= lang('Taxes.tax_category') ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="tax_category-icon"><i class="bi bi-piggy-bank"></i></span>
<input type="hidden" name="tax_category_id" id="tax_category_id" value="<?= $tax_category_id ?>">
<input type="text" class="form-control" name="tax_category" id="tax_category" aria-describedby="tax_category-icon" value="<?= $tax_category ?>">
</div>
<?php endif; ?>
<?php if ($include_hsn): ?>
<label for="hsn_code" class="form-label"><?= lang('Items.hsn_code'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="hsn_code-icon"><i class="bi bi-123"></i></span>
<input type="text" class="form-control" name="hsn_code" id="hsn_code" aria-describedby="hsn_code-icon" value="<?= $hsn_code ?>">
</div>
<?php endif; ?>
<?php foreach ($stock_locations as $key => $location_detail): ?>
<label for="quantity_<?= $key ?>" class="form-label"><?= lang('Items.quantity') . ' ' . $location_detail['location_name'] ?><sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup></label>
<div class="input-group mb-3">
<span class="input-group-text" id="quantity_<?= $key ?>-icon"><i class="bi bi-boxes"></i></span>
<input type="text" class="form-control" name="quantity_<?= $key ?>" id="quantity_<?= $key ?>" aria-describedby="quantity_<?= $key ?>-icon" value="<?= isset($item_info->item_id) ? to_quantity_decimals($location_detail['quantity']) : to_quantity_decimals(0) ?>" required>
</div>
<?php endforeach; ?>
<label for="receiving_quantity" class="form-label"><?= lang('Items.receiving_quantity') ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="receiving_quantity-icon"><i class="bi bi-truck"></i></span>
<input type="text" class="form-control" name="receiving_quantity" id="receiving_quantity" aria-describedby="receiving_quantity-icon" value="<?= isset($item_info->item_id) ? to_quantity_decimals($item_info->receiving_quantity) : to_quantity_decimals(0) ?>">
</div>
<label for="reorder_level" class="form-label"><?= lang('Items.reorder_level') ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="reorder_level-icon"><i class="bi bi-list-ol"></i></span>
<input type="text" class="form-control" name="reorder_level" id="reorder_level" aria-describedby="reorder_level-icon" value="<?= isset($item_info->item_id) ? to_quantity_decimals($item_info->reorder_level) : to_quantity_decimals(0) ?>">
</div>
<label for="description" class="form-label"><?= lang('Items.description'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-chat"></i></span>
<textarea class="form-control" name="description" id="description" rows="6"><?= $item_info->description ?></textarea>
</div>
<label for="items_image" class="form-label"><?= lang('Items.image'); ?></label>
<div id="items_image" class="w-100 fileinput <?= $logo_exists ? 'fileinput-exists' : 'fileinput-new'; ?>" data-provides="fileinput">
<div class="input-group mb-3" aria-describedby="company-logo-desc">
<span class="input-group-text"><i class="bi bi-image"></i></span>
<div class="fileinput-new form-control rounded-end mb-0" style="height: 200px; cursor: default;"></div>
<div class="fileinput-exists fileinput-preview img-thumbnail form-control rounded-end mb-0 bg-light mh-100" style="height: 200px; cursor: default; background-size: 40px 40px; background-position: 0 0, 20px 20px; background-image: linear-gradient(45deg, white 25%, transparent 25%, transparent 75%, white 75%, white), linear-gradient(45deg, white 25%, transparent 25%, transparent 75%, white 75%, white);">
<img class="mh-100 mw-100" data-src="holder.js/100%x100%" alt="<?= esc(lang('Config.company_logo')) ?>" src="<?= $image_path ?>">
</div>
</div>
<div type="button" class="btn btn-secondary btn-file me-2">
<span class="fileinput-new"><i class="bi bi-hand-index me-2"></i><?= lang('Items.select_image') ?></span>
<span class="fileinput-exists"><i class="bi bi-images me-2"></i><?= lang('Items.change_image') ?></span>
<input type="file" name="items_image" accept="image/*">
</div>
<a type="button" class="btn btn-outline-secondary fileinput-exists" data-dismiss="fileinput">
<i class="bi bi-eraser me-2"></i><?= lang('Items.remove_image') ?>
</a>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.description'), 'description', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_textarea([
'name' => 'description',
'id' => 'description',
'class' => 'form-control input-sm',
'value' => $item_info->description
]) ?>
</div>
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" name="allow_alt_description" id="allow_alt_description" value="1" <?= $item_info->allow_alt_description == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="allow_alt_description"><?= lang('Items.allow_alt_description') ?></label>
</div>
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" name="is_serialized" id="is_serialized" value="1" <?= $item_info->is_serialized == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="is_serialized"><?= lang('Items.is_serialized') ?></label>
</div>
<?php if ($config['multi_pack_enabled'] == '1'): ?>
<label for="qty_per_pack" class="form-label"><?= lang('Items.qty_per_pack') ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="qty_per_pack-icon"><i class="bi bi-123"></i></span>
<input type="text" class="form-control" name="qty_per_pack" id="qty_per_pack" aria-describedby="qty_per_pack-icon" value="<?= isset($item_info->item_id) ? to_quantity_decimals($item_info->qty_per_pack) : to_quantity_decimals(0) ?>">
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.image'), 'items_image', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<div class="fileinput <?= $logo_exists ? 'fileinput-exists' : 'fileinput-new' ?>" data-provides="fileinput">
<div class="fileinput-new thumbnail" style="width: 100px; height: 100px;"></div>
<div class="fileinput-preview fileinput-exists thumbnail" style="max-width: 100px; max-height: 100px;">
<img data-src="holder.js/100%x100%" alt="<?= lang('Items.image') ?>"
src="<?= $image_path ?>"
style="max-height: 100%; max-width: 100%;">
</div>
<div>
<span class="btn btn-default btn-sm btn-file">
<span class="fileinput-new"><?= lang('Items.select_image') ?></span>
<span class="fileinput-exists"><?= lang('Items.change_image') ?></span>
<input type="file" name="items_image" accept="image/*">
</span>
<a href="#" class="btn btn-default btn-sm fileinput-exists" data-dismiss="fileinput"><?= lang('Items.remove_image') ?></a>
</div>
</div>
</div>
<label for="pack_name" class="form-label"><?= lang('Items.pack_name') ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="pack_name-icon"><i class="bi bi-box2-heart"></i></span>
<input type="text" class="form-control" name="pack_name" id="pack_name" aria-describedby="pack_name-icon" value="<?= $item_info->pack_name ?>">
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.allow_alt_description'), 'allow_alt_description', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-1">
<?= form_checkbox([
'name' => 'allow_alt_description',
'id' => 'allow_alt_description',
'value' => 1,
'checked' => $item_info->allow_alt_description == 1
]) ?>
</div>
<label for="low_sell_item_name" class="form-label"><?= lang('Items.low_sell_item') ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="pack_name-icon"><i class="bi bi-thermometer-low"></i></span>
<input type="hidden" name="low_sell_item_id" value="<?= $selected_low_sell_item_id ?>">
<input type="text" class="form-control" name="low_sell_item_name" id="low_sell_item_name" aria-describedby="low_sell_item_name-icon" value="<?= $selected_low_sell_item ?>">
</div>
<?php endif; ?>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.is_serialized'), 'is_serialized', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-1">
<?= form_checkbox([
'name' => 'is_serialized',
'id' => 'is_serialized',
'value' => 1,
'checked' => $item_info->is_serialized == 1
]) ?>
</div>
</div>
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" name="is_deleted" id="is_deleted" value="1" <?= $item_info->deleted == 1 ? 'checked' : '' ?>>
<label class="form-check-label" for="is_deleted"><?= lang('Items.is_deleted') ?></label>
</div>
<?php if ($config['multi_pack_enabled'] == '1') { ?>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.qty_per_pack'), 'qty_per_pack', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-4">
<?= form_input([
'name' => 'qty_per_pack',
'id' => 'qty_per_pack',
'class' => 'form-control input-sm',
'value' => isset($item_info->item_id) ? to_quantity_decimals($item_info->qty_per_pack) : to_quantity_decimals(0)
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.pack_name'), 'name', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_input([
'name' => 'pack_name',
'id' => 'pack_name',
'class' => 'form-control input-sm',
'value' => $item_info->pack_name
]) ?>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.low_sell_item'), 'low_sell_item_name', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<div class="input-group input-group-sm">
<?= form_input([
'name' => 'low_sell_item_name',
'id' => 'low_sell_item_name',
'class' => 'form-control input-sm',
'value' => $selected_low_sell_item
]) ?>
<?= form_hidden('low_sell_item_id', $selected_low_sell_item_id) ?>
</div>
</div>
</div>
<?php } ?>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.is_deleted'), 'is_deleted', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-1">
<?= form_checkbox([
'name' => 'is_deleted',
'id' => 'is_deleted',
'value' => 1,
'checked' => $item_info->deleted == 1
]) ?>
</div>
</div>
</fieldset>
<?= form_close() ?>
<script type="text/javascript">

View File

@@ -8,165 +8,104 @@
*/
?>
<div id="required_fields_message"><?= lang('Items.edit_fields_you_want_to_update') ?></div>
<ul id="error_message_box" class="error_message_box"></ul>
<?= form_open('items/bulkUpdate/', ['id' => 'item_form']) ?>
<?= form_open('items/bulkUpdate/', ['id' => 'item_form', 'class' => 'form-horizontal']) ?>
<fieldset id="bulk_item_basic_info">
<div class="mb-3"><?= lang('Items.edit_fields_you_want_to_update') ?></div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.name'), 'name', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_input([
'name' => 'name',
'id' => 'name',
'class' => 'form-control input-sm'
]) ?>
</div>
</div>
<ul id="error_message_box" class="alert alert-warning d-none"></ul>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.category'), 'category', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<div class="input-group">
<span class="input-group-addon input-sm"><span class="glyphicon glyphicon-tag"></span></span>
<?= form_input([
'name' => 'category',
'id' => 'category',
'class' => 'form-control input-sm'
]) ?>
</div>
</div>
</div>
<label for="name" class="form-label"><?= lang('Items.name') ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="name-icon"><i class="bi bi-tag"></i></span>
<input type="text" class="form-control" name="name" id="name" aria-describedby="name-icon">
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.supplier'), 'supplier', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_dropdown('supplier_id', $suppliers, '', ['class' => 'form-control']) ?>
</div>
</div>
<label for="category" class="form-label"><?= lang('Items.category') ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="category-icon"><i class="bi bi-bookmark"></i></span>
<input type="text" class="form-control" name="category" id="category" aria-describedby="category-icon">
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.cost_price'), 'cost_price', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-4">
<div class="input-group input-group-sm">
<?php if (!is_right_side_currency_symbol()): ?>
<span class="input-group-addon input-sm"><b><?= esc($config['currency_symbol']) ?></b></span>
<?php endif; ?>
<?= form_input([
'name' => 'cost_price',
'id' => 'cost_price',
'class' => 'form-control input-sm'
]) ?>
<?php if (is_right_side_currency_symbol()): ?>
<span class="input-group-addon input-sm"><b><?= esc($config['currency_symbol']) ?></b></span>
<?php endif; ?>
</div>
</div>
</div>
<label for="supplier" class="form-label"><?= lang('Items.supplier'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-truck"></i></span>
<select class="form-select" name="supplier_id" id="supplier">
<?php foreach ($suppliers as $value => $label): ?>
<option value="<?= $value ?>"><?= $label ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="form-group form-group">
<?= form_label(lang('Items.unit_price'), 'unit_price', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-4">
<div class="input-group input-group-sm">
<?php if (!is_right_side_currency_symbol()): ?>
<span class="input-group-addon input-sm"><b><?= esc($config['currency_symbol']) ?></b></span>
<?php endif; ?>
<?= form_input([
'name' => 'unit_price',
'id' => 'unit_price',
'class' => 'form-control input-sm'
]) ?>
<?php if (is_right_side_currency_symbol()): ?>
<span class="input-group-addon input-sm"><b><?= esc($config['currency_symbol']) ?></b></span>
<?php endif; ?>
</div>
</div>
</div>
<label for="cost_price" class="form-label"><?= lang('Items.cost_price') ?></label>
<div class="input-group mb-3">
<?php if (!is_right_side_currency_symbol()): ?>
<span class="input-group-text" id="cost_price-icon"><?= esc($config['currency_symbol']) ?></span>
<?php endif; ?>
<input type="number" step="any" class="form-control" name="cost_price" id="cost_price" aria-describedby="cost_price-icon">
<?php if (is_right_side_currency_symbol()): ?>
<span class="input-group-text" id="cost_price-icon"><?= esc($config['currency_symbol']) ?></span>
<?php endif; ?>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.tax_1'), 'tax_percent_1', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-4">
<?= form_input([
'name' => 'tax_names[]',
'id' => 'tax_name_1',
'class' => 'form-control input-sm',
'value' => $config['default_tax_1_name']
]) ?>
</div>
<div class="col-xs-4">
<div class="input-group input-group-sm">
<?= form_input([
'name' => 'tax_percents[]',
'id' => 'tax_percent_name_1',
'class' => 'form-control input-sm',
'value' => to_tax_decimals($config['default_tax_1_rate'])
]) ?>
<span class="input-group input-group-addon"><b>%</b></span>
</div>
</div>
</div>
<label for="unit_price" class="form-label"><?= lang('Items.unit_price') ?></label>
<div class="input-group mb-3">
<?php if (!is_right_side_currency_symbol()): ?>
<span class="input-group-text" id="unit_price-icon"><?= esc($config['currency_symbol']) ?></span>
<?php endif; ?>
<input type="number" step="any" class="form-control" name="unit_price" id="unit_price" aria-describedby="unit_price-icon">
<?php if (is_right_side_currency_symbol()): ?>
<span class="input-group-text" id="unit_price-icon"><?= esc($config['currency_symbol']) ?></span>
<?php endif; ?>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.tax_2'), 'tax_percent_2', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-4">
<?= form_input([
'name' => 'tax_names[]',
'id' => 'tax_name_2',
'class' => 'form-control input-sm',
'value' => $config['default_tax_2_name']
]) ?>
</div>
<div class="col-xs-4">
<div class="input-group input-group-sm">
<?= form_input([
'name' => 'tax_percents[]',
'id' => 'tax_percent_name_2',
'class' => 'form-control input-sm',
'value' => to_tax_decimals($config['default_tax_2_rate'])
]) ?>
<span class="input-group input-group-addon"><b>%</b></span>
</div>
</div>
</div>
<label for="tax_name_1" class="form-label"><?= lang('Items.tax_1') ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="tax_name_1-icon"><i class="bi bi-piggy-bank"></i></span>
<input type="text" class="form-control w-25" name="tax_names[]" id="tax_name_1" aria-describedby="tax_name_1-icon" value="<?= $config['default_tax_1_name'] ?>">
<input type="number" step="any" min="0" max="100" class="form-control" name="tax_percents[]" id="tax_percent_name_1" aria-describedby="tax_percent_name_1-icon" value="<?= to_tax_decimals($config['default_tax_1_rate']) ?>">
<span class="input-group-text" id="tax_percent_name_1-icon"><i class="bi bi-percent"></i></span>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.reorder_level'), 'reorder_level', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-4">
<?= form_input([
'name' => 'reorder_level',
'id' => 'reorder_level',
'class' => 'form-control input-sm'
]) ?>
</div>
</div>
<label for="tax_name_2" class="form-label"><?= lang('Items.tax_2') ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="tax_name_2-icon"><i class="bi bi-piggy-bank"></i></span>
<input type="text" class="form-control w-25" name="tax_names[]" id="tax_name_2" aria-describedby="tax_name_2-icon" value="<?= $config['default_tax_2_name'] ?>">
<input type="number" step="any" min="0" max="100" class="form-control" name="tax_percents[]" id="tax_percent_name_2" aria-describedby="tax_percent_name_2-icon" value="<?= to_tax_decimals($config['default_tax_2_rate']) ?>">
<span class="input-group-text" id="tax_percent_name_2-icon"><i class="bi bi-percent"></i></span>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.description'), 'description', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_textarea([
'name' => 'description',
'id' => 'description',
'class' => 'form-control input-sm'
]) ?>
</div>
</div>
<label for="reorder_level" class="form-label"><?= lang('Items.reorder_level') ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="reorder_level-icon"><i class="bi bi-list-ol"></i></span>
<input type="text" class="form-control" name="reorder_level" id="reorder_level" aria-describedby="reorder_level-icon">
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.allow_alt_description'), 'allow_alt_description', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_dropdown('allow_alt_description', $allow_alt_description_choices, '', ['class' => 'form-control']) ?>
</div>
</div>
<label for="description" class="form-label"><?= lang('Items.description'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-chat"></i></span>
<textarea class="form-control" name="description" id="description" rows="6"></textarea>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.is_serialized'), 'is_serialized', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_dropdown('is_serialized', $serialization_choices, '', ['class' => 'form-control']) ?>
</div>
</div>
<label for="allow_alt_description" class="form-label"><?= lang('Items.allow_alt_description'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-input-cursor-text"></i></span>
<select class="form-select" name="allow_alt_description" id="allow_alt_description">
<?php foreach ($allow_alt_description_choices as $value => $label): ?>
<option value="<?= $value ?>"><?= $label ?></option>
<?php endforeach; ?>
</select>
</div>
<label for="is_serialized" class="form-label"><?= lang('Items.is_serialized'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-123"></i></span>
<select class="form-select" name="is_serialized" id="is_serialized">
<?php foreach ($serialization_choices as $value => $label): ?>
<option value="<?= $value ?>"><?= $label ?></option>
<?php endforeach; ?>
</select>
</div>
</fieldset>
<?= form_close() ?>
<script type="text/javascript">

View File

@@ -9,105 +9,74 @@ use App\Models\Employee;
use App\Models\Inventory;
?>
<?= form_open('items', ['id' => 'item_form', 'class' => 'form-horizontal']) ?>
<fieldset id="count_item_basic_info">
<?= form_open('items', ['id' => 'item_form']) ?>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.item_number'), 'name', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<div class="input-group">
<span class="input-group-addon input-sm"><span class="glyphicon glyphicon-barcode"></span></span>
<?= form_input([
'name' => 'item_number',
'id' => 'item_number',
'class' => 'form-control input-sm',
'disabled' => '',
'value' => $item_info->item_number
]) ?>
</div>
</div>
</div>
<label for="item_number" class="form-label"><?= lang('Items.item_number'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="item_number-icon"><i class="bi bi-upc-scan"></i></span>
<input type="text" class="form-control" name="item_number" id="item_number" aria-describedby="item_number-icon" value="<?= $item_info->item_number ?>" disabled readonly>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.name'), 'name', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_input([
'name' => 'name',
'id' => 'name',
'class' => 'form-control input-sm',
'disabled' => '',
'value' => $item_info->name
]) ?>
</div>
</div>
<label for="name" class="form-label"><?= lang('Items.name'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="name-icon"><i class="bi bi-tag"></i></span>
<input type="text" class="form-control" name="name" id="name" aria-describedby="name-icon" value="<?= $item_info->name ?>" disabled readonly>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.category'), 'category', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<div class="input-group">
<span class="input-group-addon input-sm"><span class="glyphicon glyphicon-tag"></span></span>
<?= form_input([
'name' => 'category',
'id' => 'category',
'class' => 'form-control input-sm',
'disabled' => '',
'value' => $item_info->category
]) ?>
</div>
</div>
</div>
<label for="category" class="form-label"><?= lang('Items.category'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="category-icon"><i class="bi bi-bookmark"></i></span>
<input type="text" class="form-control" name="category" id="category" aria-describedby="category-icon" value="<?= $item_info->category ?>" disabled readonly>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.stock_location'), 'stock_location', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_dropdown('stock_location', $stock_locations, current($stock_locations), ['onchange' => 'display_stock(this.value);', 'class' => 'form-control']) ?>
</div>
</div>
<label for="stock_location" class="form-label"><?= lang('Items.stock_location'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-boxes"></i></span>
<select class="form-select" name="stock_location" id="stock_location" onchange="display_stock(this.value)">
<?php foreach ($stock_locations as $value => $label): ?>
<option value="<?= $value ?>" <?= $value == current($stock_locations) ? 'selected' : '' ?>><?= $label ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.current_quantity'), 'quantity', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-4">
<?= form_input([
'name' => 'quantity',
'id' => 'quantity',
'class' => 'form-control input-sm',
'disabled' => '',
'value' => to_quantity_decimals(current($item_quantities))
]) ?>
</div>
</div>
<label for="quantity" class="form-label"><?= lang('Items.current_quantity'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="quantity-icon"><i class="bi bi-box"></i></span>
<input type="text" class="form-control" name="quantity" id="quantity" aria-describedby="quantity-icon" value="<?= to_quantity_decimals(current($item_quantities)) ?>" disabled readonly>
</div>
</fieldset>
<?= form_close() ?>
<table id="items_count_details" class="table table-striped table-hover">
<thead>
<tr style="background-color: #999 !important;">
<th colspan="4"><?= lang('Items.inventory_data_tracking') ?></th>
</tr>
<tr>
<th style="width: 30%;"><?= lang('Items.inventory_date') ?></th>
<th style="width: 20%;"><?= lang('Items.inventory_employee') ?></th>
<th style="width: 20%;"><?= lang('Items.inventory_in_out_quantity') ?></th>
<th style="width: 30%;"><?= lang('Items.inventory_remarks') ?></th>
</tr>
</thead>
<tbody id="inventory_result">
<?php
// The tbody content of the table will be filled in by the javascript (see bottom of page)
$employee = model(Employee::class);
$inventory = model(Inventory::class);
<div class="table-responsive">
<table class="table table-sm table-hover align-middle text-nowrap" id="items_count_details">
<thead class="table-secondary">
<tr class="table-active">
<th colspan="4"><?= lang('Items.inventory_data_tracking') ?></th>
</tr>
<tr>
<th scope="col"><?= lang('Items.inventory_date') ?></th>
<th scope="col"><?= lang('Items.inventory_employee') ?></th>
<th scope="col" class="text-center" title="<?= lang('Items.inventory_in_out_quantity') ?>">#</th>
<th scope="col"><?= lang('Items.inventory_remarks') ?></th>
</tr>
</thead>
<tbody id="inventory_result">
<?php
// The tbody content of the table will be filled in by the javascript (see bottom of page)
$employee = model(Employee::class);
$inventory = model(Inventory::class);
$inventory_array = $inventory->get_inventory_data_for_item($item_info->item_id)->getResultArray();
$employee_name = [];
$inventory_array = $inventory->get_inventory_data_for_item($item_info->item_id)->getResultArray();
$employee_name = [];
foreach ($inventory_array as $row) {
$employee_data = $employee->get_info($row['trans_user']);
$employee_name[] = $employee_data->first_name . ' ' . $employee_data->last_name;
}
?>
</tbody>
</table>
foreach ($inventory_array as $row) {
$employee_data = $employee->get_info($row['trans_user']);
$employee_name[] = $employee_data->first_name . ' ' . $employee_data->last_name;
}
?>
</tbody>
</table>
</div>
<script type="text/javascript">
$(document).ready(function() {
@@ -145,7 +114,7 @@ use App\Models\Inventory;
td = document.createElement('td');
td.appendChild(document.createTextNode(parseFloat(data['trans_inventory']).toFixed(<?= quantity_decimals() ?>)));
td.setAttribute("style", "text-align: center");
td.setAttribute("class", "text-end");
tr.appendChild(td);
td = document.createElement('td');

View File

@@ -1,27 +1,22 @@
<ul id="error_message_box" class="error_message_box"></ul>
<?= form_open_multipart('items/importCsvFile/', ['id' => 'csv_form']) ?>
<?= form_open_multipart('items/importCsvFile/', ['id' => 'csv_form', 'class' => 'form-horizontal']) ?>
<fieldset id="item_basic_info">
<ul id="error_message_box" class="alert alert-warning d-none"></ul>
<div class="form-group form-group-sm">
<div class="col-xs-12">
<a href="<?= esc('items/generateCsvFile', 'attr') ?>"><?= lang('Common.download_import_template') ?></a>
</div>
<a type="button" class="btn btn-secondary mb-3" href="<?= esc('items/generateCsvFile', 'attr') ?>"><?= lang('Common.download_import_template') ?></a>
<div class="fileinput fileinput-new input-group mb-3" data-provides="fileinput">
<span class="input-group-text"><i class="bi bi-filetype-csv"></i></span>
<div class="form-control" data-trigger="fileinput">
<span class="fileinput-filename"></span>
</div>
<span class="input-group-text fileinput-exists" data-dismiss="fileinput" style="cursor: pointer;"><?= lang('Common.import_remove_file') ?></span>
<span class="input-group-text btn-file">
<span class="fileinput-new"><?= lang('Common.import_select_file') ?></span>
<span class="fileinput-exists"><?= lang('Common.import_change_file') ?></span>
<input type="file" id="file_path" name="file_path" accept=".csv">
</span>
</div>
<div class="form-group form-group-sm">
<div class="col-xs-12">
<div class="fileinput fileinput-new input-group" data-provides="fileinput">
<div class="form-control" data-trigger="fileinput"><i class="glyphicon glyphicon-file fileinput-exists"></i><span class="fileinput-filename"></span></div>
<span class="input-group-addon input-sm btn btn-default btn-file">
<span class="fileinput-new"><?= lang('Common.import_select_file') ?></span><span class="fileinput-exists"><?= lang('Common.import_change_file') ?></span><input type="file" id="file_path" name="file_path" accept=".csv">
</span>
<a href="#" class="input-group-addon input-sm btn btn-default fileinput-exists" data-dismiss="fileinput"><?= lang('Common.import_remove_file') ?></a>
</div>
</div>
</div>
</fieldset>
<?= form_close() ?>
<script type="text/javascript">

View File

@@ -7,100 +7,56 @@
*/
?>
<div id="required_fields_message"><?= lang('Common.fields_required_message') ?></div>
<ul id="error_message_box" class="error_message_box"></ul>
<?= form_open("items/saveInventory/$item_info->item_id", ['id' => 'item_form']) ?>
<?= form_open("items/saveInventory/$item_info->item_id", ['id' => 'item_form', 'class' => 'form-horizontal']) ?>
<fieldset id="inv_item_basic_info">
<ul id="error_message_box" class="alert alert-warning d-none"></ul>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.item_number'), 'name', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<div class="input-group">
<span class="input-group-addon input-sm"><span class="glyphicon glyphicon-barcode"></span></span>
<?= form_input([
'name' => 'item_number',
'id' => 'item_number',
'class' => 'form-control input-sm',
'disabled' => '',
'value' => $item_info->item_number
]) ?>
</div>
</div>
</div>
<label for="item_number" class="form-label"><?= lang('Items.item_number'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="item_number-icon"><i class="bi bi-upc-scan"></i></span>
<input type="text" class="form-control" name="item_number" id="item_number" aria-describedby="item_number-icon" value="<?= $item_info->item_number ?>" disabled readonly>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.name'), 'name', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_input([
'name' => 'name',
'id' => 'name',
'class' => 'form-control input-sm',
'disabled' => '',
'value' => $item_info->name
]) ?>
</div>
</div>
<label for="name" class="form-label"><?= lang('Items.name'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="name-icon"><i class="bi bi-tag"></i></span>
<input type="text" class="form-control" name="name" id="name" aria-describedby="name-icon" value="<?= $item_info->name ?>" disabled readonly>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.category'), 'category', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<div class="input-group">
<span class="input-group-addon input-sm"><span class="glyphicon glyphicon-tag"></span></span>
<?= form_input([
'name' => 'category',
'id' => 'category',
'class' => 'form-control input-sm',
'disabled' => '',
'value' => $item_info->category
]) ?>
</div>
</div>
</div>
<label for="category" class="form-label"><?= lang('Items.category'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="category-icon"><i class="bi bi-bookmark"></i></span>
<input type="text" class="form-control" name="category" id="category" aria-describedby="category-icon" value="<?= $item_info->category ?>" disabled readonly>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.stock_location'), 'stock_location', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_dropdown('stock_location', $stock_locations, current($stock_locations), ['onchange' => 'fill_quantity(this.value)', 'class' => 'form-control']) ?>
</div>
</div>
<label for="stock_location" class="form-label"><?= lang('Items.stock_location'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-boxes"></i></span>
<select class="form-select" name="stock_location" id="stock_location" onchange="fill_quantity(this.value)">
<?php foreach ($stock_locations as $value => $label): ?>
<option value="<?= $value ?>" <?= $value == current($stock_locations) ? 'selected' : '' ?>><?= $label ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.current_quantity'), 'quantity', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-4">
<?= form_input([
'name' => 'quantity',
'id' => 'quantity',
'class' => 'form-control input-sm',
'disabled' => '',
'value' => to_quantity_decimals(current($item_quantities))
]) ?>
</div>
</div>
<label for="quantity" class="form-label"><?= lang('Items.current_quantity'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="quantity-icon"><i class="bi bi-box"></i></span>
<input type="text" class="form-control" name="quantity" id="quantity" aria-describedby="quantity-icon" value="<?= to_quantity_decimals(current($item_quantities)) ?>" disabled readonly>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.add_minus'), 'quantity', ['class' => 'required control-label col-xs-3']) ?>
<div class="col-xs-4">
<?= form_input([
'name' => 'newquantity',
'id' => 'newquantity',
'class' => 'form-control input-sm'
]) ?>
</div>
</div>
<label for="newquantity" class="form-label"><?= lang('Items.add_minus'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="newquantity-icon"><i class="bi bi-plus-slash-minus"></i></span>
<input type="number" step="1" class="form-control" name="newquantity" id="newquantity" aria-describedby="newquantity-icon">
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Items.inventory_comments'), 'description', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_textarea([
'name' => 'trans_comment',
'id' => 'trans_comment',
'class' => 'form-control input-sm'
]) ?>
</div>
</div>
<label for="trans_comment" class="form-label"><?= lang('Items.inventory_comments'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-chat"></i></span>
<textarea class="form-control" name="trans_comment" id="trans_comment" rows="6"></textarea>
</div>
</fieldset>
<?= form_close() ?>
<script type="text/javascript">

View File

@@ -16,6 +16,11 @@ use App\Models\Employee;
<?= view('partial/header') ?>
<?php
$title_info['config_title'] = 'Items';
echo view('configs/config_header', $title_info);
?>
<script type="text/javascript">
$(document).ready(function() {
$('#generate_barcodes').click(function() {
@@ -76,51 +81,57 @@ use App\Models\Employee;
<?= view('partial/table_filter_persistence', ['additional_params' => ['stock_location']]) ?>
<div id="title_bar" class="btn-toolbar print_hide">
<button class="btn btn-info btn-sm pull-right modal-dlg" data-btn-submit="<?= lang('Common.submit') ?>" data-href="<?= "$controller_name/csvImport" ?>" title="<?= lang('Items.import_items_csv') ?>">
<span class="glyphicon glyphicon-import">&nbsp;</span><?= lang('Common.import_csv') ?>
<div class="d-flex gap-2 justify-content-end">
<button type="button" class="btn btn-primary modal-launch" data-btn-new="<?= lang('Common.new') ?>" data-btn-submit="<?= lang('Common.submit') ?>" data-href="<?= "$controller_name/view" ?>" title="<?= lang(ucfirst($controller_name) . '.new') ?>">
<i class="bi bi-tag me-2"></i><?= lang(ucfirst($controller_name) . '.new') ?>
</button>
<button class="btn btn-info btn-sm pull-right modal-dlg" data-btn-new="<?= lang('Common.new') ?>" data-btn-submit="<?= lang('Common.submit') ?>" data-href="<?= "$controller_name/view" ?>" title="<?= lang(ucfirst($controller_name) . '.new') ?>">
<span class="glyphicon glyphicon-tag">&nbsp;</span><?= lang(ucfirst($controller_name) . '.new') ?>
<button type="button" class="btn btn-primary modal-launch" data-btn-submit="<?= lang('Common.submit') ?>" data-href="<?= "$controller_name/csvImport" ?>" title="<?= lang('Items.import_items_csv') ?>">
<i class="bi bi-file-earmark-arrow-down me-2"></i><?= lang('Common.import_csv') ?>
</button>
</div>
<div id="toolbar">
<div class="pull-left form-inline" role="toolbar">
<button id="delete" class="btn btn-default btn-sm print_hide">
<span class="glyphicon glyphicon-trash">&nbsp;</span><?= lang('Common.delete') ?>
<div class="d-flex gap-2">
<button type="button" class="btn btn-secondary d-print-none" id="delete">
<i class="bi bi-trash"></i><span class="d-none d-md-inline ms-2"><?= lang('Common.delete') ?></span>
</button>
<button id="bulk_edit" class="btn btn-default btn-sm modal-dlg print_hide" data-btn-submit="<?= lang('Common.submit') ?>" data-href="<?= "items/bulkEdit" ?>" title="<?= lang('Items.edit_multiple_items') ?>">
<span class="glyphicon glyphicon-edit">&nbsp;</span><?= lang('Items.bulk_edit') ?>
<button type="button" class="btn btn-secondary modal-launch d-print-none" id="bulk_edit" data-btn-submit="<?= lang('Common.submit') ?>" data-href="<?= "items/bulkEdit" ?>" title="<?= lang('Items.edit_multiple_items') ?>">
<i class="bi bi-pencil-square"></i><span class="d-none d-md-inline ms-2"><?= lang('Items.bulk_edit') ?></span>
</button>
<button id="generate_barcodes" class="btn btn-default btn-sm print_hide" data-href="<?= "$controller_name/generateBarcodes" ?>" title="<?= lang('Items.generate_barcodes') ?>">
<span class="glyphicon glyphicon-barcode">&nbsp;</span><?= lang('Items.generate_barcodes') ?>
<button type="button" class="btn btn-secondary d-print-none" id="generate_barcodes" data-href="<?= "$controller_name/generateBarcodes" ?>" title="<?= lang('Items.generate_barcodes') ?>">
<i class="bi bi-upc-scan"></i><span class="d-none d-md-inline ms-2"><?= lang('Items.generate_barcodes') ?></span>
</button>
<?= form_input(['name' => 'daterangepicker', 'class' => 'form-control input-sm', 'id' => 'daterangepicker']) ?>
<?= form_multiselect('filters[]', $filters, $selected_filters ?? [], [
'id' => 'filters',
'class' => 'selectpicker show-menu-arrow',
'data-none-selected-text' => lang('Common.none_selected_text'),
'data-selected-text-format' => 'count > 1',
'data-style' => 'btn-default btn-sm',
'data-width' => 'fit'
]) ?>
<?php
if (count($stock_locations) > 1) {
echo form_dropdown(
'stock_location',
$stock_locations,
$stock_location,
[
'id' => 'stock_location',
'class' => 'selectpicker show-menu-arrow',
'data-style' => 'btn-default btn-sm',
'data-width' => 'fit'
]
);
}
?>
<div class="input-group w-auto">
<span class="input-group-text" id="daterangepicker-icon"><i class="bi bi-calendar2-range"></i></span>
<input type="text" class="form-select" name="daterangepicker" id="daterangepicker" aria-describedby="daterangepicker-icon">
</div>
<div class="input-group w-auto">
<span class="input-group-text" id="filters-icon"><i class="bi bi-funnel"></i></span>
<select class="form-select" name="filters[]" id="filters" aria-describedby="filters-icon" multiple>
<?php foreach ($filters as $key => $label): ?>
<option value="<?= $key ?>" <?= in_array($key, $selected_filters ?? []) ? 'selected' : '' ?>>
<?= esc($label) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<?php if (count($stock_locations) > 1): ?>
<div class="input-group w-auto">
<span class="input-group-text" id="stock_location-icon"><i class="bi bi-boxes"></i></span>
<select class="form-select" name="stock_location" id="stock_location" aria-describedby="stock_location-icon" multiple>
<?php foreach ($stock_locations as $value => $label): ?>
<option value="<?= $value ?>" <?= $value == $stock_location ? 'selected' : '' ?>>
<?= $label ?>
</option>
<?php endforeach; ?>
</select>
</div>
<?php endif; ?>
</div>
</div>
@@ -129,3 +140,25 @@ use App\Models\Employee;
</div>
<?= view('partial/footer') ?>
<script type="text/javascript">
new TomSelect('#filters', {
plugins: ['checkbox_options', 'remove_button'],
placeholder: '<?= lang('Common.none_selected_text') ?>',
hidePlaceholder: true,
closeAfterSelect: false,
onChange: function() {
$('#table').bootstrapTable('refresh');
}
});
new TomSelect('#stock_location', {
plugins: ['checkbox_options', 'remove_button'],
placeholder: '<?= lang('Common.none_selected_text') ?>',
hidePlaceholder: true,
closeAfterSelect: false,
onChange: function() {
$('#table').bootstrapTable('refresh');
}
});
</script>

View File

@@ -5,34 +5,91 @@
* @var bool $is_new_install
* @var string $latest_version
* @var bool $gcaptcha_enabled
* @var CodeIgniter\HTTP\IncomingRequest $request
* @var array $config
* @var $validation
*/
use Config\Services;
$request = Services::request();
// Manually setting some error messages for testing
// $validation->setError('test', 'The test error is testing.');
// $validation->setError('email', 'The email field is required.');
// $has_errors = $validation->hasError('email');
// $has_errors = $validation->hasError('test');
// Manually set database migration message to show
// $is_new_install = true;
// $is_latest = false;
// $latest_version = '1.0.0';
// Manually set language for page, doesn't work for dynamic elements
// \Config\Services::language()->setLocale('de-DE');
// Manually set login form appearence
// $config['login_form'] = 'input_groups';
// Manually set theme
// $config['theme'] = 'flatly';
$theme = (empty($config['theme']) ? 'bootstrap' : $config['theme']);
$themeColors = [
'bootstrap' => '#0d6efd',
'flatly' => '#2c3e50',
'darkly' => '#375a7f',
'cosmo' => '#2780e3',
'cerulean' => '#2fa4e7',
'journal' => '#eb6864',
'litera' => '#4582ec',
'lumen' => '#158cba',
'lux' => '#1a1a1a',
'materia' => '#2196f3',
'minty' => '#78c2ad',
'morph' => '#378dfc',
'pulse' => '#593196',
'quartz' => '#6d45bb',
'sandstone' => '#93c54b',
'simplex' => '#d9230f',
'sketchy' => '#333333',
'slate' => '#3a3f44',
'solar' => '#b58900',
'spacelab' => '#446e9b',
'superhero' => '#df6919',
'united' => '#e95420',
'vapor' => '#6f42c1',
'yeti' => '#008cba',
'zephyr' => '#3459e6',
];
$themeColor = $themeColors[$theme] ?? '#0d6efd';
?>
<!doctype html>
<html lang="<?= current_language_code() ?>">
<html lang="<?= current_language_code() ?>" data-bs-theme="<?= esc($config['color_mode'] ?? 'light') ?>" <?= esc($config['rtl_language'] ?? 0) == 1 ? 'dir="rtl"' : '' ?>>
<head>
<meta charset="utf-8">
<base href="<?= base_url() ?>">
<title><?= esc($config['company']) . '&nbsp;|&nbsp;' . esc(lang('Common.software_short')) . '&nbsp;|&nbsp;' . esc(lang('Login.login')) ?></title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<?= ($config['responsive_design'] ?? 0) == 1 ? '<meta name="viewport" content="width=device-width, initial-scale=1">' : '' ?>
<meta name="robots" content="noindex, nofollow">
<link rel="shortcut icon" type="image/x-icon" href="images/favicon.ico">
<?php
$theme = (empty($config['theme'])
|| 'paper' == $config['theme']
|| 'readable' == $config['theme']
? 'flatly'
: $config['theme']);
?>
<link rel="stylesheet" href="resources/bootswatch5/<?= "$theme" ?>/bootstrap.min.css">
<link rel="stylesheet" href="resources/bootswatch/<?= $theme ?>/bootstrap<?= esc($config['rtl_language'] ?? 0) == 1 ? '.rtl' : '' ?>.min.css">
<link rel="stylesheet" href="resources/bootstrap-icons/bootstrap-icons.min.css">
<link rel="stylesheet" href="css/login.css">
<meta name="theme-color" content="#2c3e50">
<meta name="theme-color" content="<?= $themeColor ?>">
</head>
<body class="bg-secondary-subtle d-flex flex-column">
<!-- BS5 WIP message -->
<div data-notify="container" class="col-11 col-sm-9 col-md-7 col-lg-6 col-xl-5 col-xxl-4 alert alert-warning position-absolute top-0 mt-3 start-50 translate-middle-x" role="alert">
<span data-notify="icon" class="me-2" role="img"><i class="bi bi-exclamation-diamond-fill"></i></span>
<span data-notify="message">WIP conversion to Bootstrap 5</span>
</div>
<main class="d-flex justify-content-around align-items-center flex-grow-1">
<div class="container-login container-fluid d-flex flex-column flex-md-row bg-body shadow rounded m-3 p-4 p-md-0">
<div class="box-logo d-flex flex-column justify-content-center align-items-center border-end border-secondary-subtle px-4 pb-3 p-md-4">
@@ -48,94 +105,87 @@
</div>
<section class="box-login d-flex flex-column justify-content-center align-items-center p-md-4">
<?= form_open('login', ['id' => 'login-form']) ?>
<h3 id="form-heading" class="text-center m-0">
<?php if (!$is_latest || $is_new_install): ?>
<?= lang('Login.migration_required') ?>
<?php else: ?>
<?= lang('Login.welcome', [lang('Common.software_short')]) ?>
<?php endif; ?>
</h3>
<div id="migration-warning" class="alert alert-warning mt-3<?= $is_new_install ? '' : ' d-none' ?>">
<strong><?= lang('Login.migration_auth_message', [$latest_version]) ?></strong>
</div>
<?php if ($has_errors): ?>
<?php foreach ($validation->getErrors() as $error): ?>
<div class="alert alert-danger mt-3">
<?= $error ?>
</div>
<?php endforeach; ?>
<?php endif; ?>
<div id="migration-success" class="alert alert-success d-none mt-3">
<strong><?= lang('Login.migration_complete') ?></strong> <?= lang('Login.migration_complete_login') ?>
</div>
<div id="migration-progress" class="d-none mt-4">
<h3 class="text-center mb-4"><?= lang('Login.migration_initializing') ?></h3>
<div class="progress mb-3" style="height: 30px;">
<div class="progress-bar progress-bar-striped progress-bar-animated bg-primary"
role="progressbar"
style="width: 100%">
</div>
</div>
<p class="text-center text-muted" id="migration-status">
<?= lang('Login.migration_running') ?>
</p>
</div>
<div id="migration-error" class="alert alert-danger d-none mt-3" role="alert">
<strong>Error:</strong> <span id="migration-error-message"></span>
</div>
<div id="login-fields" class="w-100<?= $is_new_install ? ' d-none' : '' ?>">
<?php if (empty($config['login_form']) || 'floating_labels' == ($config['login_form'])): ?>
<div class="form-floating mt-3">
<input class="form-control" id="input-username" name="username" type="text" placeholder="<?= lang('Login.username') ?>" <?php if (ENVIRONMENT == "testing") echo 'value="admin"'; ?>>
<label for="input-username"><?= lang('Login.username') ?></label>
</div>
<div class="form-floating mb-3">
<input class="form-control" id="input-password" name="password" type="password" placeholder="<?= lang('Login.password') ?>" <?php if (ENVIRONMENT == "testing") echo 'value="pointofsale"'; ?>>
<label for="input-password"><?= lang('Login.password') ?></label>
</div>
<?php elseif ('input_groups' == ($config['login_form'])): ?>
<div class="input-group mt-3">
<span class="input-group-text" id="input-username">
<svg class="bi bi-person-fill" fill="currentColor" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<title><?= lang('Common.icon') . '&nbsp;' . lang('Login.username') ?></title>
<path d="M3 14s-1 0-1-1 1-4 6-4 6 3 6 4-1 1-1 1zm5-6a3 3 0 1 0 0-6 3 3 0 0 0 0 6" />
</svg>
</span>
<input class="form-control" name="username" type="text" placeholder="<?= lang('Login.username'); ?>" aria-label="<?= lang('Login.username') ?>" aria-describedby="input-username" <?php if (ENVIRONMENT == "testing") echo 'value="admin"'; ?>>
</div>
<div class="input-group mb-3">
<span class="input-group-text" id="input-password">
<svg class="bi bi-key-fill" fill="currentColor" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<title><?= lang('Common.icon') . '&nbsp;' . lang('Login.password') ?></title>
<path d="M3.5 11.5a3.5 3.5 0 1 1 3.163-5H14L15.5 8 14 9.5l-1-1-1 1-1-1-1 1-1-1-1 1H6.663a3.5 3.5 0 0 1-3.163 2M2.5 9a1 1 0 1 0 0-2 1 1 0 0 0 0 2" />
</svg>
</span>
<input class="form-control" name="password" type="password" placeholder="<?= lang('Login.password') ?>" aria-label="<?= lang('Login.password') ?>" aria-describedby="input-password" <?php if (ENVIRONMENT == "testing") echo 'value="pointofsale"'; ?>>
</div>
<?php endif; ?>
<?php if ($gcaptcha_enabled): ?>
<script src="https://www.google.com/recaptcha/api.js"></script>
<div class="g-recaptcha mb-3" style="text-align: center;" data-sitekey="<?= esc($config['gcaptcha_site_key']) ?>"></div>
<?php endif; ?>
</div>
<div class="d-grid">
<button id="submit-button" class="btn btn-lg btn-primary" name="login-button" type="submit">
<?php if ($is_new_install): ?>
<?= lang('Module.migrate') ?>
<h3 id="form-heading" class="text-center m-0">
<?php if (!$is_latest || $is_new_install): ?>
<?= lang('Login.migration_required') ?>
<?php else: ?>
<?= lang('Login.go') ?>
<?= lang('Login.welcome', [lang('Common.software_short')]) ?>
<?php endif; ?>
</button>
</div>
</h3>
<div id="migration-warning" class="alert alert-info mt-3<?= $is_new_install ? '' : ' d-none' ?>">
<?= lang('Login.migration_auth_message', [$latest_version]) ?>
</div>
<?php if ($has_errors): ?>
<?php foreach ($validation->getErrors() as $error): ?>
<div class="alert alert-danger mt-3">
<?= $error ?>
</div>
<?php endforeach; ?>
<?php endif; ?>
<div id="migration-success" class="alert alert-success d-none mt-3">
<strong><?= lang('Login.migration_complete') ?></strong>
<?= lang('Login.migration_complete_login') ?>
</div>
<div id="migration-progress" class="d-none w-100">
<div class="text-center fw-bold mb-3 mt-3"><?= lang('Login.migration_initializing') ?></div>
<div class="progress" role="progressbar">
<div class="progress-bar progress-bar-striped progress-bar-animated" style="width: 100%"></div>
</div>
<p class="text-center text-muted mt-3" id="migration-status">
<?= lang('Login.migration_running') ?>
</p>
</div>
<div id="migration-error" class="alert alert-danger d-none mt-3" role="alert">
<strong>Error:</strong> <span id="migration-error-message"></span>
</div>
<div id="login-fields" class="w-100<?= $is_new_install ? ' d-none' : '' ?>">
<?php if (empty($config['login_form']) || 'floating_labels' == ($config['login_form'])): ?>
<div class="form-floating mt-3">
<input class="form-control" id="input-username" name="username" type="text" placeholder="<?= lang('Login.username') ?>" <?php if (ENVIRONMENT == "testing") echo 'value="admin"'; ?>>
<label for="input-username"><?= lang('Login.username') ?></label>
</div>
<div class="form-floating mb-3">
<input class="form-control" id="input-password" name="password" type="password" placeholder="<?= lang('Login.password') ?>" <?php if (ENVIRONMENT == "testing") echo 'value="pointofsale"'; ?>>
<label for="input-password"><?= lang('Login.password') ?></label>
</div>
<?php elseif ('input_groups' == ($config['login_form'])): ?>
<div class="input-group mt-3">
<span class="input-group-text" id="input-username">
<i class="bi bi-person" title="<?= lang('Common.icon') . '&nbsp;' . lang('Login.username') ?>"></i>
</span>
<input class="form-control" name="username" type="text" placeholder="<?= lang('Login.username'); ?>" aria-label="<?= lang('Login.username') ?>" aria-describedby="input-username" <?php if (ENVIRONMENT == "testing") echo 'value="admin"'; ?>>
</div>
<div class="input-group mb-3">
<span class="input-group-text" id="input-password">
<i class="bi bi-lock" title="<?= lang('Common.icon') . '&nbsp;' . lang('Login.password') ?>"></i>
</span>
<input class="form-control" name="password" type="password" placeholder="<?= lang('Login.password') ?>" aria-label="<?= lang('Login.password') ?>" aria-describedby="input-password" <?php if (ENVIRONMENT == "testing") echo 'value="pointofsale"'; ?>>
</div>
<?php endif; ?>
<?php if ($gcaptcha_enabled): ?>
<script src="https://www.google.com/recaptcha/api.js"></script>
<div class="g-recaptcha mb-3" style="text-align: center;" data-sitekey="<?= esc($config['gcaptcha_site_key'] ?? '') ?>"></div>
<?php endif; ?>
</div>
<div class="d-grid">
<button type="submit" id="submit-button" class="btn btn-lg btn-primary" name="login-button">
<?php if ($is_new_install): ?>
<?= lang('Module.migrate') ?>
<?php else: ?>
<?= lang('Login.go') ?>
<?php endif; ?>
</button>
</div>
<?= form_close() ?>
</section>
</div>
@@ -154,11 +204,6 @@
</div>
</footer>
<?php
use Config\Services;
$request = Services::request();
?>
<?php if (ENVIRONMENT == 'development' || get_cookie('debug') == 'true' || $request->getGet('debug') == 'true') : ?>
<!-- inject:login:debug:js -->
<!-- endinject -->
@@ -257,9 +302,9 @@
$form.on('submit', function(e) {
if (APP_STATE.isNewInstall) {
e.preventDefault();
showMigrationProgress();
$.ajax({
url: APP_STATE.migrateUrl,
type: 'POST',

View File

@@ -6,44 +6,34 @@
*/
?>
<div id="required_fields_message"><?= lang('Common.fields_required_message') ?></div>
<ul id="error_message_box" class="error_message_box"></ul>
<?= form_open("messages/send_form/$person_info->person_id", ['id' => 'send_sms_form']) ?>
<?= form_open("messages/send_form/$person_info->person_id", ['id' => 'send_sms_form', 'class' => 'form-horizontal']) ?>
<fieldset>
<ul id="error_message_box" class="alert alert-warning d-none"></ul>
<div class="form-group form-group-sm">
<?= form_label(lang('Messages.first_name'), 'first_name_label', ['for' => 'first_name', 'class' => 'control-label col-xs-2']) ?>
<div class="col-xs-10">
<?= form_input(['class' => 'form-control input-sm', 'type' => 'text', 'name' => 'first_name', 'value' => $person_info->first_name, 'readonly' => 'true']) ?>
</div>
</div>
<label for="first_name" class="form-label"><?= lang('Messages.first_name'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="first_name-icon"><i class="bi bi-person-square"></i></span>
<input type="text" class="form-control" name="first_name" id="first_name" aria-describedby="first_name-icon" value="<?= $person_info->first_name; ?>" disabled readonly>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Messages.last_name'), 'last_name_label', ['for' => 'last_name', 'class' => 'control-label col-xs-2']) ?>
<div class="col-xs-10">
<?= form_input(['class' => 'form-control input-sm', 'type' => 'text', 'name' => 'last_name', 'value' => $person_info->last_name, 'readonly' => 'true']) ?>
</div>
</div>
<label for="last_name" class="form-label"><?= lang('Messages.last_name'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="last_name-icon"><i class="bi bi-person-square"></i></span>
<input type="text" class="form-control" name="last_name" id="last_name" aria-describedby="last_name-icon" value="<?= $person_info->last_name; ?>" disabled readonly>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Messages.phone'), 'phone_label', ['for' => 'phone', 'class' => 'control-label col-xs-2 required']) ?>
<div class="col-xs-10">
<div class="input-group">
<span class="input-group-addon input-sm"><span class="glyphicon glyphicon-phone-alt"></span></span>
<?= form_input(['class' => 'form-control input-sm required', 'type' => 'text', 'name' => 'phone', 'value' => $person_info->phone_number]) ?>
</div>
</div>
</div>
<label for="phone" class="form-label"><?= lang('Messages.phone'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="phone-icon"><i class="bi bi-telephone"></i></span>
<input type="text" class="form-control" name="phone" id="phone" aria-describedby="phone-icon" value="<?= $person_info->phone_number; ?>">
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Messages.message'), 'message_label', ['for' => 'message', 'class' => 'control-label col-xs-2 required']) ?>
<div class="col-xs-10">
<?= form_textarea(['class' => 'form-control input-sm required', 'name' => 'message', 'id' => 'message', 'value' => $config['msg_msg']]) ?>
</div>
</div>
<label for="message" class="form-label"><?= lang('Messages.message'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="message-icon"><i class="bi bi-chat-dots"></i></span>
<textarea class="form-control" name="message" id="message" rows="10" aria-describedby="message-icon"><?= $config['msg_msg'] ?></textarea>
</div>
</fieldset>
<?= form_close() ?>
<script type="text/javascript">

View File

@@ -1,39 +1,34 @@
<?= view('partial/header') ?>
<script type="text/javascript">
dialog_support.init("a.modal-dlg");
</script>
<?= form_open("messages/send/", ['id' => 'send_sms_form', 'enctype' => 'multipart/form-data', 'method' => 'post']) ?>
<div class="jumbotron" style="max-width: 60%; margin: auto;">
<?= form_open("messages/send/", ['id' => 'send_sms_form', 'enctype' => 'multipart/form-data', 'method' => 'post', 'class' => 'form-horizontal']) ?>
<fieldset>
<?php
$title_info['config_title'] = lang('Messages.sms_send');
echo view('configs/config_header', $title_info);
?>
<legend style="text-align: center;"><?= lang('Messages.sms_send') ?></legend>
<div class="form-group form-group-sm">
<label for="phone" class="col-xs-3 control-label"><?= lang('Messages.phone') ?></label>
<div class="col-xs-9">
<input class="form-control input-sm" type="text" name="phone" placeholder="<?= lang('Messages.phone_placeholder') ?>">
<span class="help-block" style="text-align: center;"><?= lang('Messages.multiple_phones') ?></span>
</div>
</div>
<div class="col mb-3">
<label for="message-recipients" class="form-label"><?= lang('Messages.phone'); ?></label>
<div class="input-group">
<span class="input-group-text" id="message-icon"><i class="bi bi-phone"></i></span>
<input type="text" name="phone" class="form-control" id="message-recipients" aria-describedby="message-icon" required placeholder="<?= lang('Messages.phone_placeholder'); ?>">
</div>
<span class="form-text"><?= lang('Messages.multiple_phones'); ?></span>
</div>
<div class="form-group form-group-sm">
<label for="message" class="col-xs-3 control-label"><?= lang('Messages.message') ?></label>
<div class="col-xs-9">
<textarea class="form-control input-sm" rows="3" id="message" name="message" placeholder="<?= lang('Messages.message_placeholder') ?>"></textarea>
</div>
</div>
<div class="col mb-3">
<label for="text-message" class="form-label"><?= lang('Messages.message'); ?></label>
<div class="input-group">
<span class="input-group-text"><i class="bi bi-chat-quote"></i></span>
<textarea class="form-control" name="message" id="text-message" rows="10" placeholder="<?= lang('Messages.message_placeholder'); ?>"></textarea>
</div>
</div>
<?= form_submit([
'name' => 'submit_form',
'id' => 'submit_form',
'value' => lang('Common.submit'),
'class' => 'btn btn-primary btn-sm pull-right'
]) ?>
<div class="d-flex justify-content-end">
<button type="submit" class="btn btn-primary" id="submit_form" name="submit_form">Send</button>
</div>
</fieldset>
<?= form_close() ?>
</div>
<?= form_close() ?>
<?= view('partial/footer') ?>
@@ -45,6 +40,7 @@
$(form).ajaxSubmit({
success: function(response) {
$.notify({
icon: 'bi bi-bell-fill',
message: response.message
}, {
type: response.success ? 'success' : 'danger'

View File

@@ -4,6 +4,10 @@
*/
?>
<span class="d-flex justify-content-start add_customer_reward">
<button type="button" class="btn btn-outline-success mb-3"><i class="bi bi-plus-lg"></i>&nbsp;Add reward</button> <!-- TODO-BS5 translate -->
</span>
<?php
$i = 0;
@@ -14,33 +18,14 @@ foreach ($customer_rewards as $reward_key => $reward_category) {
++$i;
?>
<div class="form-group form-group-sm" style="<?= $reward_category['deleted'] ? 'display: none;' : 'display: block;' ?>">
<?= form_label(lang('Config.customer_reward') . " $i", "customer_reward_$i", ['class' => 'required control-label col-xs-2']) ?>
<div class="col-xs-2">
<?php $form_data = [
'name' => 'customer_reward_' . $customer_reward_id,
'id' => 'customer_reward_' . $customer_reward_id,
'class' => 'customer_reward valid_chars form-control input-sm required',
'value' => $customer_reward_name
];
$reward_category['deleted'] && $form_data['disabled'] = 'disabled';
echo form_input($form_data);
?>
<div class="col-12 col-lg-6 <?= $reward_category['deleted'] ? 'd-none' : '' ?>">
<label for="customer_reward_<?= $i ?>" class="form-label"><?= lang('Config.customer_reward') . " $i"; ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><?= $customer_reward_id ?>.</span>
<input type="text" class="form-control customer_reward valid_chars w-25" name="customer_reward_<?= $customer_reward_id ?>" id="customer_reward_<?= $customer_reward_id ?>" value="<?= $customer_reward_name ?>" required <?= $reward_category['deleted'] ? 'disabled' : '' ?>>
<input type="number" min="0" class="form-control customer_reward valid_chars" name="reward_points_<?= $customer_reward_id ?>" id="reward_points_<?= $customer_reward_id ?>" value="<?= $customer_points_percent ?>" required <?= $reward_category['deleted'] ? 'disabled' : '' ?>>
<button type="button" class="btn btn-outline-danger remove_customer_reward"><i class="bi bi-x-lg"></i></button>
</div>
<div class="col-xs-2">
<?php $form_data = [
'name' => 'reward_points_' . $customer_reward_id,
'id' => 'reward_points_' . $customer_reward_id,
'class' => 'customer_reward valid_chars form-control input-sm required',
'value' => $customer_points_percent
];
$reward_category['deleted'] && $form_data['disabled'] = 'disabled';
echo form_input($form_data);
?>
</div>
<span class="add_customer_reward glyphicon glyphicon-plus" style="padding-top: 0.5em;"></span>
<span>&nbsp;&nbsp;</span>
<span class="remove_customer_reward glyphicon glyphicon-minus" style="padding-top: 0.5em;"></span>
</div>
<?php } ?>

View File

@@ -5,206 +5,209 @@
?>
<?php if (empty($config['date_or_time_format'])) { ?>
$('#daterangepicker').css("width", "180");
var start_date = "<?= date('Y-m-d') ?>";
var end_date = "<?= date('Y-m-d') ?>";
$('#daterangepicker').daterangepicker({
"ranges": {
"<?= lang('Datepicker.today') ?>": [
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), date("d"), date("Y"))) ?>",
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), date("d") + 1, date("Y")) - 1) ?>"
],
"<?= lang('Datepicker.today_last_year') ?>": [
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), date("d"), date("Y") - 1)) ?>",
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), date("d") + 1, date("Y") - 1) - 1) ?>"
],
"<?= lang('Datepicker.yesterday') ?>": [
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), date("d") - 1, date("Y"))) ?>",
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), date("d"), date("Y")) - 1) ?>"
],
"<?= lang('Datepicker.last_7') ?>": [
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), date("d") - 6, date("Y"))) ?>",
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), date("d") + 1, date("Y")) - 1) ?>"
],
"<?= lang('Datepicker.last_30') ?>": [
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), date("d") - 29, date("Y"))) ?>",
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), date("d") + 1, date("Y")) - 1) ?>"
],
"<?= lang('Datepicker.this_month') ?>": [
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), 1, date("Y"))) ?>",
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m") + 1, 1, date("Y")) - 1) ?>"
],
"<?= lang('Datepicker.same_month_to_same_day_last_year') ?>": [
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), 1, date("Y") - 1)) ?>",
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), date("d") + 1, date("Y") - 1) - 1) ?>"
],
"<?= lang('Datepicker.same_month_last_year') ?>": [
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), 1, date("Y") - 1)) ?>",
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m") + 1, 1, date("Y") - 1) - 1) ?>"
],
"<?= lang('Datepicker.last_month') ?>": [
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m") - 1, 1, date("Y"))) ?>",
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), 1, date("Y")) - 1) ?>"
],
"<?= lang('Datepicker.this_year') ?>": [
"<?= date($config['dateformat'], mktime(0, 0, 0, 1, 1, date("Y"))) ?>",
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), 1, date("Y") + 1) - 1) ?>"
],
"<?= lang('Datepicker.last_year') ?>": [
"<?= date($config['dateformat'], mktime(0, 0, 0, 1, 1, date("Y") - 1)) ?>",
"<?= date($config['dateformat'], mktime(0, 0, 0, 1, 1, date("Y")) - 1) ?>"
],
"<?= lang('Datepicker.this_financial_year') ?>": [
"<?= date($config['dateformat'], mktime(0, 0, 0, $config['financial_year'], 1, date("Y"))) ?>",
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), 1, date("Y") + 1) - 1) ?>"
],
"<?= lang('Datepicker.last_financial_year') ?>": [
"<?= date($config['dateformat'], mktime(0, 0, 0, $config['financial_year'], 1, date("Y") - 1)) ?>",
"<?= date($config['dateformat'], mktime(0, 0, 0, $config['financial_year'], 1, date("Y")) - 1) ?>"
],
"<?= lang('Datepicker.all_time') ?>": [
"<?= date($config['dateformat'], mktime(0, 0, 0, 1, 1, 2010)) ?>",
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), date("d") + 1, date("Y")) - 1) ?>"
],
"ranges": {
"<?= lang('Datepicker.today') ?>": [
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), date("d"), date("Y"))) ?>",
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), date("d") + 1, date("Y")) - 1) ?>"
],
"<?= lang('Datepicker.today_last_year') ?>": [
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), date("d"), date("Y") - 1)) ?>",
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), date("d") + 1, date("Y") - 1) - 1) ?>"
],
"<?= lang('Datepicker.yesterday') ?>": [
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), date("d") - 1, date("Y"))) ?>",
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), date("d"), date("Y")) - 1) ?>"
],
"<?= lang('Datepicker.last_7') ?>": [
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), date("d") - 6, date("Y"))) ?>",
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), date("d") + 1, date("Y")) - 1) ?>"
],
"<?= lang('Datepicker.last_30') ?>": [
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), date("d") - 29, date("Y"))) ?>",
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), date("d") + 1, date("Y")) - 1) ?>"
],
"<?= lang('Datepicker.this_month') ?>": [
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), 1, date("Y"))) ?>",
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m") + 1, 1, date("Y")) - 1) ?>"
],
"<?= lang('Datepicker.same_month_to_same_day_last_year') ?>": [
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), 1, date("Y") - 1)) ?>",
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), date("d") + 1, date("Y") - 1) - 1) ?>"
],
"<?= lang('Datepicker.same_month_last_year') ?>": [
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), 1, date("Y") - 1)) ?>",
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m") + 1, 1, date("Y") - 1) - 1) ?>"
],
"<?= lang('Datepicker.last_month') ?>": [
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m") - 1, 1, date("Y"))) ?>",
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), 1, date("Y")) - 1) ?>"
],
"<?= lang('Datepicker.this_year') ?>": [
"<?= date($config['dateformat'], mktime(0, 0, 0, 1, 1, date("Y"))) ?>",
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), 1, date("Y") + 1) - 1) ?>"
],
"<?= lang('Datepicker.last_year') ?>": [
"<?= date($config['dateformat'], mktime(0, 0, 0, 1, 1, date("Y") - 1)) ?>",
"<?= date($config['dateformat'], mktime(0, 0, 0, 1, 1, date("Y")) - 1) ?>"
],
"<?= lang('Datepicker.this_financial_year') ?>": [
"<?= date($config['dateformat'], mktime(0, 0, 0, $config['financial_year'], 1, date("Y"))) ?>",
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), 1, date("Y") + 1) - 1) ?>"
],
"<?= lang('Datepicker.last_financial_year') ?>": [
"<?= date($config['dateformat'], mktime(0, 0, 0, $config['financial_year'], 1, date("Y") - 1)) ?>",
"<?= date($config['dateformat'], mktime(0, 0, 0, $config['financial_year'], 1, date("Y")) - 1) ?>"
],
"<?= lang('Datepicker.all_time') ?>": [
"<?= date($config['dateformat'], mktime(0, 0, 0, 1, 1, 2010)) ?>",
"<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), date("d") + 1, date("Y")) - 1) ?>"
],
},
"locale": {
"format": '<?= dateformat_momentjs($config['dateformat']) ?>',
"separator": " - ",
"applyLabel": "<?= lang('Datepicker.apply') ?>",
"cancelLabel": "<?= lang('Datepicker.cancel') ?>",
"fromLabel": "<?= lang('Datepicker.from') ?>",
"toLabel": "<?= lang('Datepicker.to') ?>",
"customRangeLabel": "<?= lang('Datepicker.custom') ?>",
"daysOfWeek": [
"<?= lang('Calendar.su') ?>",
"<?= lang('Calendar.mo') ?>",
"<?= lang('Calendar.tu') ?>",
"<?= lang('Calendar.we') ?>",
"<?= lang('Calendar.th') ?>",
"<?= lang('Calendar.fr') ?>",
"<?= lang('Calendar.sa') ?>"
],
"monthNames": [
"<?= lang('Calendar.january') ?>",
"<?= lang('Calendar.february') ?>",
"<?= lang('Calendar.march') ?>",
"<?= lang('Calendar.april') ?>",
"<?= lang('Calendar.may') ?>",
"<?= lang('Calendar.june') ?>",
"<?= lang('Calendar.july') ?>",
"<?= lang('Calendar.august') ?>",
"<?= lang('Calendar.september') ?>",
"<?= lang('Calendar.october') ?>",
"<?= lang('Calendar.november') ?>",
"<?= lang('Calendar.december') ?>"
],
"firstDay": <?= lang('Datepicker.weekstart') ?>
},
"alwaysShowCalendars": true,
"startDate": "<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), date("d") + 1, date("Y")) - 1) ?>",
"endDate": "<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), date("d") + 1, date("Y")) - 1) ?>",
"minDate": "<?= date($config['dateformat'], mktime(0, 0, 0, 01, 01, 2010)) ?>",
"maxDate": "<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), date("d") + 1, date("Y")) - 1) ?>",
"buttonClasses": "btn",
"applyButtonClasses": "btn-primary",
"cancelClass": "btn-secondary"
},
"locale": {
"format": '<?= dateformat_momentjs($config['dateformat']) ?>',
"separator": " - ",
"applyLabel": "<?= lang('Datepicker.apply') ?>",
"cancelLabel": "<?= lang('Datepicker.cancel') ?>",
"fromLabel": "<?= lang('Datepicker.from') ?>",
"toLabel": "<?= lang('Datepicker.to') ?>",
"customRangeLabel": "<?= lang('Datepicker.custom') ?>",
"daysOfWeek": [
"<?= lang('Calendar.su') ?>",
"<?= lang('Calendar.mo') ?>",
"<?= lang('Calendar.tu') ?>",
"<?= lang('Calendar.we') ?>",
"<?= lang('Calendar.th') ?>",
"<?= lang('Calendar.fr') ?>",
"<?= lang('Calendar.sa') ?>"
],
"monthNames": [
"<?= lang('Calendar.january') ?>",
"<?= lang('Calendar.february') ?>",
"<?= lang('Calendar.march') ?>",
"<?= lang('Calendar.april') ?>",
"<?= lang('Calendar.may') ?>",
"<?= lang('Calendar.june') ?>",
"<?= lang('Calendar.july') ?>",
"<?= lang('Calendar.august') ?>",
"<?= lang('Calendar.september') ?>",
"<?= lang('Calendar.october') ?>",
"<?= lang('Calendar.november') ?>",
"<?= lang('Calendar.december') ?>"
],
"firstDay": <?= lang('Datepicker.weekstart') ?>
},
"alwaysShowCalendars": true,
"startDate": "<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), date("d") + 1, date("Y")) - 1) ?>",
"endDate": "<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), date("d") + 1, date("Y")) - 1) ?>",
"minDate": "<?= date($config['dateformat'], mktime(0, 0, 0, 01, 01, 2010)) ?>",
"maxDate": "<?= date($config['dateformat'], mktime(0, 0, 0, date("m"), date("d") + 1, date("Y")) - 1) ?>"
}, function(start, end, label) {
start_date = start.format('YYYY-MM-DD');
end_date = end.format('YYYY-MM-DD');
function(start, end, label) {
start_date = start.format('YYYY-MM-DD');
end_date = end.format('YYYY-MM-DD');
});
<?php } else { ?>
$('#daterangepicker').css("width", "305");
var start_date = "<?= date('Y-m-d H:i:s', mktime(0, 0, 0, date("m"), date("d"), date("Y"))) ?>";
var end_date = "<?= date('Y-m-d H:i:s', mktime(23, 59, 59, date("m"), date("d"), date("Y"))) ?>";
$('#daterangepicker').daterangepicker({
"ranges": {
"<?= lang('Datepicker.today') ?>": [
"<?= date($config['dateformat'] . ' ' . $config['dateformat'], mktime(0, 0, 0, date("m"), date("d"), date("Y"))) ?>",
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(23, 59, 59, date("m"), date("d"), date("Y"))) ?>"
],
"<?= lang('Datepicker.today_last_year') ?>": [
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(0, 0, 0, date("m"), date("d"), date("Y") - 1)) ?>",
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(23, 59, 59, date("m"), date("d"), date("Y") - 1)) ?>"
],
"<?= lang('Datepicker.yesterday') ?>": [
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(0, 0, 0, date("m"), date("d") - 1, date("Y"))) ?>",
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(23, 59, 59, date("m"), date("d") - 1, date("Y"))) ?>"
],
"<?= lang('Datepicker.last_7') ?>": [
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(0, 0, 0, date("m"), date("d") - 6, date("Y"))) ?>",
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(23, 59, 59, date("m"), date("d"), date("Y"))) ?>"
],
"<?= lang('Datepicker.last_30') ?>": [
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(0, 0, 0, date("m"), date("d") - 29, date("Y"))) ?>",
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(23, 59, 59, date("m"), date("d"), date("Y"))) ?>"
],
"<?= lang('Datepicker.this_month') ?>": [
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(0, 0, 0, date("m"), 1, date("Y"))) ?>",
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(23, 59, 59, date("m"), date("d"), date("Y"))) ?>"
],
"<?= lang('Datepicker.same_month_to_same_day_last_year') ?>": [
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(0, 0, 0, date("m"), 1, date("Y") - 1)) ?>",
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(23, 59, 59, date("m"), date("d"), date("Y") - 1)) ?>"
],
"<?= lang('Datepicker.same_month_last_year') ?>": [
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(0, 0, 0, date("m"), 1, date("Y") - 1)) ?>",
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(23, 59, 59, date("m") + 1, 0, date("Y") - 1)) ?>"
],
"<?= lang('Datepicker.last_month') ?>": [
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(0, 0, 0, date("m") - 1, 1, date("Y"))) ?>",
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(23, 59, 59, date("m"), 0, date("Y"))) ?>"
],
"<?= lang('Datepicker.this_year') ?>": [
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(0, 0, 0, 1, 1, date("Y"))) ?>",
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(23, 59, 59, date("m") + 1, 0, date("Y"))) ?>"
],
"<?= lang('Datepicker.last_year') ?>": [
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(0, 0, 0, 1, 1, date("Y") - 1)) ?>",
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(23, 59, 59, 12, 31, date("Y") - 1)) ?>"
],
"<?= lang('Datepicker.this_financial_year') ?>": [
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(0, 0, 0, $config['financial_year'], 1, date("Y"))) ?>",
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(23, 59, 59, date("m") + 1, 0, date("Y"))) ?>"
],
"<?= lang('Datepicker.last_financial_year') ?>": [
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(0, 0, 0, $config['financial_year'], 1, date("Y") - 1)) ?>",
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(23, 59, 59, $config['financial_year'], 0, date("Y"))) ?>"
],
"<?= lang('Datepicker.all_time') ?>": [
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(0, 0, 0, 1, 1, 2010)) ?>",
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(23, 59, 59, date("m"), date("d"), date("Y"))) ?>"
],
"ranges": {
"<?= lang('Datepicker.today') ?>": [
"<?= date($config['dateformat'] . ' ' . $config['dateformat'], mktime(0, 0, 0, date("m"), date("d"), date("Y"))) ?>",
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(23, 59, 59, date("m"), date("d"), date("Y"))) ?>"
],
"<?= lang('Datepicker.today_last_year') ?>": [
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(0, 0, 0, date("m"), date("d"), date("Y") - 1)) ?>",
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(23, 59, 59, date("m"), date("d"), date("Y") - 1)) ?>"
],
"<?= lang('Datepicker.yesterday') ?>": [
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(0, 0, 0, date("m"), date("d") - 1, date("Y"))) ?>",
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(23, 59, 59, date("m"), date("d") - 1, date("Y"))) ?>"
],
"<?= lang('Datepicker.last_7') ?>": [
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(0, 0, 0, date("m"), date("d") - 6, date("Y"))) ?>",
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(23, 59, 59, date("m"), date("d"), date("Y"))) ?>"
],
"<?= lang('Datepicker.last_30') ?>": [
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(0, 0, 0, date("m"), date("d") - 29, date("Y"))) ?>",
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(23, 59, 59, date("m"), date("d"), date("Y"))) ?>"
],
"<?= lang('Datepicker.this_month') ?>": [
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(0, 0, 0, date("m"), 1, date("Y"))) ?>",
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(23, 59, 59, date("m"), date("d"), date("Y"))) ?>"
],
"<?= lang('Datepicker.same_month_to_same_day_last_year') ?>": [
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(0, 0, 0, date("m"), 1, date("Y") - 1)) ?>",
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(23, 59, 59, date("m"), date("d"), date("Y") - 1)) ?>"
],
"<?= lang('Datepicker.same_month_last_year') ?>": [
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(0, 0, 0, date("m"), 1, date("Y") - 1)) ?>",
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(23, 59, 59, date("m") + 1, 0, date("Y") - 1)) ?>"
],
"<?= lang('Datepicker.last_month') ?>": [
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(0, 0, 0, date("m") - 1, 1, date("Y"))) ?>",
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(23, 59, 59, date("m"), 0, date("Y"))) ?>"
],
"<?= lang('Datepicker.this_year') ?>": [
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(0, 0, 0, 1, 1, date("Y"))) ?>",
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(23, 59, 59, date("m") + 1, 0, date("Y"))) ?>"
],
"<?= lang('Datepicker.last_year') ?>": [
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(0, 0, 0, 1, 1, date("Y") - 1)) ?>",
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(23, 59, 59, 12, 31, date("Y") - 1)) ?>"
],
"<?= lang('Datepicker.this_financial_year') ?>": [
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(0, 0, 0, $config['financial_year'], 1, date("Y"))) ?>",
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(23, 59, 59, date("m") + 1, 0, date("Y"))) ?>"
],
"<?= lang('Datepicker.last_financial_year') ?>": [
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(0, 0, 0, $config['financial_year'], 1, date("Y") - 1)) ?>",
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(23, 59, 59, $config['financial_year'], 0, date("Y"))) ?>"
],
"<?= lang('Datepicker.all_time') ?>": [
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(0, 0, 0, 1, 1, 2010)) ?>",
"<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(23, 59, 59, date("m"), date("d"), date("Y"))) ?>"
],
},
"locale": {
"format": '<?= dateformat_momentjs($config['dateformat'] . ' ' . $config['timeformat']) ?>',
"separator": " - ",
"applyLabel": "<?= lang('Datepicker.apply') ?>",
"cancelLabel": "<?= lang('Datepicker.cancel') ?>",
"fromLabel": "<?= lang('Datepicker.from') ?>",
"toLabel": "<?= lang('Datepicker.to') ?>",
"customRangeLabel": "<?= lang('Datepicker.custom') ?>",
"daysOfWeek": [
"<?= lang('Calendar.su') ?>",
"<?= lang('Calendar.mo') ?>",
"<?= lang('Calendar.tu') ?>",
"<?= lang('Calendar.we') ?>",
"<?= lang('Calendar.th') ?>",
"<?= lang('Calendar.fr') ?>",
"<?= lang('Calendar.sa') ?>"
],
"monthNames": [
"<?= lang('Calendar.january') ?>",
"<?= lang('Calendar.february') ?>",
"<?= lang('Calendar.march') ?>",
"<?= lang('Calendar.april') ?>",
"<?= lang('Calendar.may') ?>",
"<?= lang('Calendar.june') ?>",
"<?= lang('Calendar.july') ?>",
"<?= lang('Calendar.august') ?>",
"<?= lang('Calendar.september') ?>",
"<?= lang('Calendar.october') ?>",
"<?= lang('Calendar.november') ?>",
"<?= lang('Calendar.december') ?>"
],
"firstDay": <?= lang('Datepicker.weekstart') ?>
"format": '<?= dateformat_momentjs($config['dateformat'] . ' ' . $config['timeformat']) ?>',
"separator": " - ",
"applyLabel": "<?= lang('Datepicker.apply') ?>",
"cancelLabel": "<?= lang('Datepicker.cancel') ?>",
"fromLabel": "<?= lang('Datepicker.from') ?>",
"toLabel": "<?= lang('Datepicker.to') ?>",
"customRangeLabel": "<?= lang('Datepicker.custom') ?>",
"daysOfWeek": [
"<?= lang('Calendar.su') ?>",
"<?= lang('Calendar.mo') ?>",
"<?= lang('Calendar.tu') ?>",
"<?= lang('Calendar.we') ?>",
"<?= lang('Calendar.th') ?>",
"<?= lang('Calendar.fr') ?>",
"<?= lang('Calendar.sa') ?>"
],
"monthNames": [
"<?= lang('Calendar.january') ?>",
"<?= lang('Calendar.february') ?>",
"<?= lang('Calendar.march') ?>",
"<?= lang('Calendar.april') ?>",
"<?= lang('Calendar.may') ?>",
"<?= lang('Calendar.june') ?>",
"<?= lang('Calendar.july') ?>",
"<?= lang('Calendar.august') ?>",
"<?= lang('Calendar.september') ?>",
"<?= lang('Calendar.october') ?>",
"<?= lang('Calendar.november') ?>",
"<?= lang('Calendar.december') ?>"
],
"firstDay": <?= lang('Datepicker.weekstart') ?>
},
"timePicker": true,
"timePickerSeconds": true,
@@ -212,9 +215,13 @@
"startDate": "<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(0, 0, 0, date("m"), date("d"), date("Y"))) ?>",
"endDate": "<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(23, 59, 59, date("m"), date("d"), date("Y"))) ?>",
"minDate": "<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(0, 0, 0, 01, 01, 2010)) ?>",
"maxDate": "<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(23, 59, 59, date("m"), date("d"), date("Y"))) ?>"
}, function(start, end, label) {
start_date = start.format('YYYY-MM-DD HH:mm:ss');
end_date = end.format('YYYY-MM-DD HH:mm:ss');
"maxDate": "<?= date($config['dateformat'] . ' ' . $config['timeformat'], mktime(23, 59, 59, date("m"), date("d"), date("Y"))) ?>",
"buttonClasses": "btn",
"applyButtonClasses": "btn-primary",
"cancelClass": "btn-secondary"
},
function(start, end, label) {
start_date = start.format('YYYY-MM-DD HH:mm:ss');
end_date = end.format('YYYY-MM-DD HH:mm:ss');
});
<?php } ?>

View File

@@ -4,6 +4,10 @@
*/
?>
<span class="d-flex justify-content-start add_dinner_table">
<button type="button" class="btn btn-outline-success mb-3"><i class="bi bi-plus-lg"></i>&nbsp;Add table</button> <!-- TODO-BS5 translate -->
</span>
<?php
$i = 0;
@@ -13,24 +17,13 @@ foreach ($dinner_tables as $table_key => $table) {
++$i;
?>
<div class="form-group form-group-sm" style="<?= $table['deleted'] ? 'display: none;' : 'display: block;' ?>">
<?= form_label(lang('Config.dinner_table') . " $i", "dinner_table_$i", ['class' => 'required control-label col-xs-2']) ?>
<div class="col-xs-2">
<?php $form_data = [
'name' => "dinner_table_$dinner_table_id",
'id' => "dinner_table_$dinner_table_id",
'class' => 'dinner_table valid_chars form-control input-sm required',
'value' => $dinner_table_name
];
$table['deleted'] && $form_data['disabled'] = 'disabled';
echo form_input($form_data);
?>
<div class="col-12 col-lg-6 <?= $table['deleted'] ? 'd-none' : '' ?>">
<label for="dinner_table_<?= $dinner_table_id ?>" class="form-label"><?= lang('Config.dinner_table') . " $i"; ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><?= $dinner_table_id ?>.</span>
<input type="text" class="form-control dinner_table valid_chars" name="dinner_table_<?= $dinner_table_id ?>" id="dinner_table_<?= $dinner_table_id ?>" value="<?= $dinner_table_name ?>" required <?= $table['deleted'] && $form_data['disabled'] = 'disabled' ?>>
<button type="button" class="btn btn-outline-danger remove_dinner_table"><i class="bi bi-x-lg"></i></button>
</div>
<span class="add_dinner_table glyphicon glyphicon-plus" style="padding-top: 0.5em;"></span>
<span>&nbsp;&nbsp;</span>
<span class="remove_dinner_table glyphicon glyphicon-minus" style="padding-top: 0.5em;"></span>
</div>
<?php } ?>

View File

@@ -4,20 +4,27 @@ use Config\OSPOS;
?>
</div>
</div>
</main>
<div id="footer">
<div class="jumbotron push-spaces">
<strong>
<?= lang('Common.copyrights', [date('Y')]) ?> ·
<a href="https://opensourcepos.org" target="_blank"><?= lang('Common.website') ?></a> ·
<?= esc(config('App')->application_version) ?> -
<a target="_blank" href="https://github.com/opensourcepos/opensourcepos/commit/<?= esc(config(OSPOS::class)->commit_sha1) ?>">
<?= esc(substr(config(OSPOS::class)->commit_sha1, 0, 6)); ?>
</a>
</strong>.
<footer class="flex-shrink-0 text-body-secondary small fw-semibold bg-secondary-subtle py-3 d-print-none">
<div class="container-lg d-flex flex-wrap justify-content-center align-items-center">
<div>
<span><?= lang('Common.copyrights', [date('Y')]) ?></span>
</div>
<div>
<span class="d-none d-xl-block">&nbsp;·&nbsp;<a href="https://opensourcepos.org" class="text-body-secondary" target="_blank" rel="noopener"><?= lang('Common.website') ?></a>&nbsp;·&nbsp;</span>
<span class="d-xl-none">&nbsp;·&nbsp;<?= lang('Common.website') ?>&nbsp;·&nbsp;</span>
</div>
<div>
<span><?= esc(config('App')->application_version) ?>&nbsp;-</span>
<span class="d-none d-xl-inline"><a href="https://github.com/opensourcepos/opensourcepos/commit/<?= esc(config(OSPOS::class)->commit_sha1) ?>" class="text-body-secondary" target="_blank" rel="noopener"><?= esc(substr(config(OSPOS::class)->commit_sha1, 0, 6)); ?></a></span>
<span class="d-xl-none"><?= esc(substr(config(OSPOS::class)->commit_sha1, 0, 6)); ?></span>
</div>
</div>
</body>
</footer>
<script type="text/javascript" src="js/bs-tooltips.js"></script>
<script type="text/javascript" src="js/bs-modal_switch_content.js"></script>
</body>
</html>

View File

@@ -9,17 +9,56 @@
use Config\Services;
$request = Services::request();
// Services::language()->setLocale('de-DE');
$theme = (empty($config['theme']) ? 'bootstrap' : $config['theme']);
$themeColors = [
'bootstrap' => '#0d6efd',
'flatly' => '#2c3e50',
'darkly' => '#375a7f',
'cosmo' => '#2780e3',
'cerulean' => '#2fa4e7',
'journal' => '#eb6864',
'litera' => '#4582ec',
'lumen' => '#158cba',
'lux' => '#1a1a1a',
'materia' => '#2196f3',
'minty' => '#78c2ad',
'morph' => '#378dfc',
'pulse' => '#593196',
'quartz' => '#6d45bb',
'sandstone' => '#93c54b',
'simplex' => '#d9230f',
'sketchy' => '#333333',
'slate' => '#3a3f44',
'solar' => '#b58900',
'spacelab' => '#446e9b',
'superhero' => '#df6919',
'united' => '#e95420',
'vapor' => '#6f42c1',
'yeti' => '#008cba',
'zephyr' => '#3459e6',
];
$themeColor = $themeColors[$theme] ?? '#0d6efd';
?>
<!doctype html>
<html lang="<?= $request->getLocale() ?>">
<html lang="<?= current_language_code() ?>" data-bs-theme="<?= $config['color_mode'] ?>" <?= $config['rtl_language'] == 1 ? 'dir="rtl"' : '' ?>>
<head>
<meta charset="utf-8">
<base href="<?= base_url() ?>">
<title><?= esc($config['company']) . ' | ' . lang('Common.powered_by') . ' OSPOS ' . esc(config('App')->application_version) ?></title>
<?= $config['responsive_design'] == 1 ? '<meta name="viewport" content="width=device-width, initial-scale=1">' : '' ?>
<meta name="robots" content="noindex, nofollow">
<link rel="shortcut icon" type="image/x-icon" href="images/favicon.ico">
<link rel="stylesheet" href="<?= 'resources/bootswatch/' . (empty($config['theme']) ? 'flatly' : esc($config['theme'])) . '/bootstrap.min.css' ?>">
<link rel="stylesheet" href="resources/bootswatch/<?= $theme ?>/bootstrap<?= esc($config['rtl_language']) == 1 ? '.rtl' : '' ?>.min.css">
<link rel="stylesheet" href="resources/bootstrap-icons/bootstrap-icons.min.css">
<meta name="theme-color" content="<?= $themeColor ?>">
<?php if (ENVIRONMENT == 'development' || get_cookie('debug') == 'true' || $request->getGet('debug') == 'true') : ?>
<!-- inject:debug:css -->
@@ -27,13 +66,8 @@ $request = Services::request();
<!-- inject:debug:js -->
<!-- endinject -->
<?php else : ?>
<!--inject:prod:css -->
<!-- inject:prod:css -->
<!-- endinject -->
<!-- Tweaks to the UI for a particular theme should drop here -->
<?php if ($config['theme'] != 'flatly' && file_exists($_SERVER['DOCUMENT_ROOT'] . '/public/css/' . esc($config['theme']) . '.css')) { ?>
<link rel="stylesheet" href="<?= 'css/' . esc($config['theme']) . '.css' ?>">
<?php } ?>
<!-- inject:prod:js -->
<!-- endinject -->
<?php endif; ?>
@@ -41,60 +75,51 @@ $request = Services::request();
<?= view('partial/header_js') ?>
<?= view('partial/lang_lines') ?>
<style>
html {
overflow: auto;
}
</style>
</head>
<body>
<div class="wrapper">
<div class="topbar">
<div class="container">
<div class="navbar-left">
<div id="liveclock"><?= date($config['dateformat'] . ' ' . $config['timeformat']) ?></div>
</div>
<div class="navbar-right" style="margin: 0;">
<?= anchor("home/changePassword/$user_info->person_id", "$user_info->first_name $user_info->last_name", ['class' => 'modal-dlg', 'data-btn-submit' => lang('Common.submit'), 'title' => lang('Employees.change_password')]) ?>
<span>&nbsp;|&nbsp;</span>
<?= anchor('home/logout', lang('Login.logout')) ?>
</div>
<div class="navbar-center" style="text-align: center;">
<strong><?= esc($config['company']) ?></strong>
</div>
<body class="d-flex flex-column">
<header class="flex-shrink-0 small bg-secondary-subtle py-1 d-print-none">
<div class="container-lg container-navbar d-flex flex-wrap-reverse justify-content-between align-items-center">
<div class="flex-grow-1 d-none d-md-block ps-md-3 ps-lg-0">
<span id="liveclock"><?= date($config['dateformat'] . ' ' . $config['timeformat']) ?></span>
</div>
<div class="fw-bold ps-3 ps-md-0">
<?= esc($config['company']) ?>
</div>
<div class="flex-grow-1 text-end pe-3 pe-lg-0">
<button type="button" class="btn btn-sm btn-outline-primary" onclick="removeAnimationBg()" data-bs-toggle="modal" data-bs-target="#profile-modal" title="<?= lang('Employees.change_password'); ?>">
<?= $user_info->first_name . '&nbsp;' . $user_info->last_name; ?>
</button>
<?= view('home/profile'); ?>
</div>
</div>
</header>
<div class="navbar navbar-default" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<nav class="navbar navbar-dark navbar-expand-lg bg-primary py-0 d-print-none">
<div class="container-lg container-navbar">
<a class="navbar-brand py-2 pe-1 ps-3 ps-lg-0 fs-4" href="<?= site_url() ?>"><i class="bi bi-house-fill"></i></a>
<button type="button" class="navbar-toggler my-2 mx-3" data-bs-toggle="collapse" data-bs-target="#navbar" aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<a class="navbar-brand hidden-sm" href="<?= site_url() ?>">OSPOS</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<?php foreach ($allowed_modules as $module): ?>
<li class="<?= $module->module_id == $request->getUri()->getSegment(1) ? 'active' : '' ?>">
<a href="<?= base_url($module->module_id) ?>" title="<?= lang("Module.$module->module_id") ?>" class="menu-icon">
<img src="<?= base_url("images/menubar/$module->module_id.svg") ?>" style="border: none;" alt="Module Icon"><br>
<?= lang('Module.' . $module->module_id) ?>
</a>
</li>
<?php endforeach; ?>
</ul>
</div>
<div class="collapse navbar-collapse" id="navbar">
<ul class="navbar-nav ms-0 ms-lg-auto">
<?php foreach($allowed_modules as $module): ?>
<li class="d-none d-lg-block nav-item ms-1 <?= $module->module_id == $request->getUri()->getSegment(1) ? 'active bg-light bg-opacity-25' : '' ?>" data-bs-toggle="tooltip" data-bs-placement="bottom" title="<?= lang("Module.$module->module_id") ?>">
<a class="nav-link p-2" href="<?= base_url($module->module_id) ?>">
<img src="<?= base_url("images/menubar/$module->module_id.svg") ?>" alt="<?= lang('Common.icon') . '&nbsp;' . lang("Module.$module->module_id") ?>">
</a>
</li>
<li class="d-lg-none nav-item py-1 <?= $module->module_id == $request->getUri()->getSegment(1) ? 'active bg-light bg-opacity-25' : '' ?>">
<a class="nav-link p-0" href="<?= base_url($module->module_id) ?>">
<img class="ps-3 pe-1 my-1" src="<?= base_url("images/menubar/$module->module_id.svg") ?>" alt="<?= lang('Common.icon') . '&nbsp;' . lang("Module.$module->module_id") ?>">
<span class="align-middle text-light"><?= lang("Module.$module->module_id") ?></span>
</a>
</li>
<?php endforeach; ?>
</ul>
</div>
</div>
</nav>
<div class="container">
<div class="row">
<main class="container-lg flex-grow-1 py-3">

View File

@@ -4,6 +4,10 @@
*/
?>
<span class="d-flex justify-content-start add_stock_location">
<button type="button" class="btn btn-outline-success mb-3"><i class="bi bi-plus-lg"></i>&nbsp;Add location</button> <!-- TODO-BS5 translate -->
</span>
<?php
$i = 0;
@@ -13,22 +17,13 @@ foreach ($stock_locations as $location => $location_data) {
++$i;
?>
<div class="form-group form-group-sm" style="<?= $location_data['deleted'] ? 'display: none;' : 'display: block;' ?>">
<?= form_label(lang('Config.stock_location') . " $i", "stock_location_$i", ['class' => 'required control-label col-xs-2']) ?>
<div class="col-xs-2">
<?php $form_data = [
'name' => "stock_location[$location_id]",
'id' => "stock_location[$location_id]",
'class' => 'stock_location valid_chars form-control input-sm required',
'value' => $location_name
];
$location_data['deleted'] && $form_data['disabled'] = 'disabled';
echo form_input($form_data);
?>
</div>
<span class="add_stock_location glyphicon glyphicon-plus" style="padding-top: 0.5em;"></span>
<span>&nbsp;&nbsp;</span>
<span class="remove_stock_location glyphicon glyphicon-minus" style="padding-top: 0.5em;"></span>
<div class="col-12 col-lg-6 <?= $location_data['deleted'] ? 'd-none' : '' ?>">
<label for="stock_location_<?= $i ?>" class="form-label"><?= lang('Config.stock_location') . " $i"; ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><?= $location_id ?>.</span>
<input type="text" class="form-control stock_location valid_chars" name="stock_location<?= $location_id ?>" id="stock_location<?= $location_id ?>" value="<?= $location_name ?>" required <?= $location_data['deleted'] ? 'disabled' : '' ?>>
<button type="button" class="btn btn-outline-danger remove_stock_location"><i class="bi bi-x-lg"></i></button>
</div>
</div>
<?php } ?>

View File

@@ -37,9 +37,9 @@ foreach ($tax_categories as $key => $category) {
echo form_input($form_data);
?>
</div>
<span class="add_tax_category glyphicon glyphicon-plus" style="padding-top: 0.5em;"></span>
<span class="add_tax_category bi bi-plus-circle" style="padding-top: 0.5em; display: inline-block; cursor: pointer;"></span>
<span>&nbsp;&nbsp;</span>
<span class="remove_tax_category glyphicon glyphicon-minus" style="padding-top: 0.5em;"></span>
<span class="remove_tax_category bi bi-dash-circle" style="padding-top: 0.5em; display: inline-block; cursor: pointer;"></span>
<?= form_hidden('tax_category_id[]', (string)$tax_category_id) ?>
</div>

View File

@@ -60,9 +60,9 @@ foreach ($tax_codes as $tax_code => $tax_code_data) {
?>
</div>
<span class="add_tax_code glyphicon glyphicon-plus" style="padding-top: 0.5em;"></span>
<span class="add_tax_code bi bi-plus-circle" style="padding-top: 0.5em; display: inline-block; cursor: pointer;"></span>
<span>&nbsp;&nbsp;</span>
<span class="remove_tax_code glyphicon glyphicon-minus" style="padding-top: 0.5em;"></span>
<span class="remove_tax_code bi bi-dash-circle" style="padding-top: 0.5em; display: inline-block; cursor: pointer;"></span>
<?= form_hidden('tax_code_id[]', (string)$tax_code_id) ?>
</div>

View File

@@ -80,9 +80,9 @@ foreach ($tax_jurisdictions as $tax_jurisdiction => $jurisdiction) {
echo form_input($form_data)
?>
</div>
<span class="add_tax_jurisdiction glyphicon glyphicon-plus" style="padding-top: 0.5em;"></span>
<span class="add_tax_jurisdiction bi bi-plus-circle" style="padding-top: 0.5em; display: inline-block; cursor: pointer;"></span>
<span>&nbsp;&nbsp;</span>
<span class="remove_tax_jurisdiction glyphicon glyphicon-minus" style="padding-top: 0.5em;"></span>
<span class="remove_tax_jurisdiction bi bi-dash-circle" style="padding-top: 0.5em; display: inline-block; cursor: pointer;"></span>
<?= form_hidden('jurisdiction_id[]', (string)$jurisdiction_id) ?>
</div>

View File

@@ -93,6 +93,6 @@ applySummaryVisibility();
var init_dialog = function () {
<?php if (isset($editable)): ?>
table_support.submit_handler('<?php echo site_url("reports/get_detailed_{$editable}_row") ?>');
dialog_support.init("a.modal-dlg");
dialog_support.init("a.modal-launch");
<?php endif; ?>
};

View File

@@ -5,167 +5,87 @@
*/
?>
<div class="form-group form-group-sm">
<?= form_label(lang('Common.first_name'), 'first_name', ['class' => 'required control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_input([
'name' => 'first_name',
'id' => 'first_name',
'class' => 'form-control input-sm',
'value' => $person_info->first_name
]) ?>
</div>
<label for="first_name" class="form-label"><?= lang('Common.first_name'); ?><sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup></label>
<div class="input-group mb-3">
<span class="input-group-text" id="first_name-icon"><i class="bi bi-person-square"></i></span>
<input type="text" class="form-control" name="first_name" id="first_name" aria-describedby="first_name-icon" value="<?= $person_info->first_name; ?>" required>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Common.last_name'), 'last_name', ['class' => 'required control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_input([
'name' => 'last_name',
'id' => 'last_name',
'class' => 'form-control input-sm',
'value' => $person_info->last_name
]) ?>
</div>
<label for="last_name" class="form-label"><?= lang('Common.last_name'); ?><sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup></label>
<div class="input-group mb-3">
<span class="input-group-text" id="last_name-icon"><i class="bi bi-person-square"></i></span>
<input type="text" class="form-control" name="last_name" id="last_name" aria-describedby="last_name-icon" value="<?= $person_info->last_name; ?>" required>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Common.gender'), 'gender', !empty($basic_version) ? ['class' => 'required control-label col-xs-3'] : ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-4">
<label class="radio-inline">
<?= form_radio([
'name' => 'gender',
'type' => 'radio',
'id' => 'gender',
'value' => 1,
'checked' => $person_info->gender === '1'
]) ?> <?= lang('Common.gender_male') ?>
</label>
<label class="radio-inline">
<?= form_radio([
'name' => 'gender',
'type' => 'radio',
'id' => 'gender',
'value' => 0,
'checked' => $person_info->gender === '0'
]) ?> <?= lang('Common.gender_female') ?>
</label>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Common.email'), 'email', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<label for="gender" class="form-label"><?= lang('Common.gender'); ?><?php if (!empty($basic_version)): ?><sup><span class="badge text-primary"><i class="bi bi-asterisk"></i></span></sup><?php endif ?></label>
<div class="row mb-3">
<div class="col-12">
<div class="input-group">
<span class="input-group-addon input-sm"><span class="glyphicon glyphicon-envelope"></span></span>
<?= form_input([
'name' => 'email',
'id' => 'email',
'class' => 'form-control input-sm',
'value' => $person_info->email
]) ?>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="gender" id="gender_male" value="1" <?= $person_info->gender === '1' ? 'checked' : '' ?>>
<label class="form-check-label" for="gender_male"><i class="bi bi-gender-male me-1"></i><?= lang('Common.gender_male') ?></label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="gender" id="gender_female" value="0" <?= $person_info->gender === '0' ? 'checked' : '' ?>>
<label class="form-check-label" for="gender_female"><i class="bi bi-gender-female me-1"></i><?= lang('Common.gender_female') ?></label>
</div>
</div>
</div>
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Common.phone_number'), 'phone_number', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<div class="input-group">
<span class="input-group-addon input-sm"><span class="glyphicon glyphicon-phone-alt"></span></span>
<?= form_input([
'name' => 'phone_number',
'id' => 'phone_number',
'class' => 'form-control input-sm',
'value' => $person_info->phone_number
]) ?>
</div>
</div>
<label for="email" class="form-label"><?= lang('Common.email'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="email-icon"><i class="bi bi-envelope"></i></span>
<input type="email" class="form-control" name="email" id="email" aria-describedby="email-icon" value="<?= $person_info->email; ?>">
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Common.address_1'), 'address_1', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_input([
'name' => 'address_1',
'id' => 'address_1',
'class' => 'form-control input-sm',
'value' => $person_info->address_1
]) ?>
</div>
<label for="phone_number" class="form-label"><?= lang('Common.phone_number'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="phone_number-icon"><i class="bi bi-telephone"></i></span>
<input type="tel" class="form-control" name="phone_number" id="phone_number" aria-describedby="phone_number-icon" value="<?= $person_info->phone_number; ?>">
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Common.address_2'), 'address_2', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_input([
'name' => 'address_2',
'id' => 'address_2',
'class' => 'form-control input-sm',
'value' => $person_info->address_2
]) ?>
</div>
<label for="address_1" class="form-label"><?= lang('Common.address_1'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="address_1-icon"><i class="bi bi-geo-alt"></i></span>
<input type="text" class="form-control" name="address_1" id="address_1" aria-describedby="address_1-icon" value="<?= $person_info->address_1; ?>">
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Common.city'), 'city', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_input([
'name' => 'city',
'id' => 'city',
'class' => 'form-control input-sm',
'value' => $person_info->city
]) ?>
</div>
<label for="address_2" class="form-label"><?= lang('Common.address_2'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="address_2-icon"><i class="bi bi-geo-alt"></i></span>
<input type="text" class="form-control" name="address_2" id="address_2" aria-describedby="address_2-icon" value="<?= $person_info->address_2; ?>">
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Common.state'), 'state', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_input([
'name' => 'state',
'id' => 'state',
'class' => 'form-control input-sm',
'value' => $person_info->state
]) ?>
</div>
<label for="city" class="form-label"><?= lang('Common.city'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="city-icon"><i class="bi bi-geo-alt"></i></span>
<input type="text" class="form-control" name="city" id="city" aria-describedby="city-icon" value="<?= $person_info->city; ?>">
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Common.zip'), 'zip', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_input([
'name' => 'zip',
'id' => 'postcode',
'class' => 'form-control input-sm',
'value' => $person_info->zip
]) ?>
</div>
<label for="state" class="form-label"><?= lang('Common.state'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="state-icon"><i class="bi bi-geo-alt"></i></span>
<input type="text" class="form-control" name="state" id="state" aria-describedby="state-icon" value="<?= $person_info->state; ?>">
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Common.country'), 'country', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_input([
'name' => 'country',
'id' => 'country',
'class' => 'form-control input-sm',
'value' => $person_info->country
]) ?>
</div>
<label for="postcode" class="form-label"><?= lang('Common.zip'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="zip-icon"><i class="bi bi-geo-alt"></i></span>
<input type="text" class="form-control" name="zip" id="postcode" aria-describedby="zip-icon" value="<?= $person_info->zip; ?>">
</div>
<div class="form-group form-group-sm">
<?= form_label(lang('Common.comments'), 'comments', ['class' => 'control-label col-xs-3']) ?>
<div class="col-xs-8">
<?= form_textarea([
'name' => 'comments',
'id' => 'comments',
'class' => 'form-control input-sm',
'value' => $person_info->comments
]) ?>
</div>
<label for="country" class="form-label"><?= lang('Common.country'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text" id="country-icon"><i class="bi bi-globe-americas"></i></span>
<input type="text" class="form-control" name="country" id="country" aria-describedby="country-icon" value="<?= $person_info->country; ?>">
</div>
<label for="comments" class="form-label"><?= lang('Common.comments'); ?></label>
<div class="input-group mb-3">
<span class="input-group-text"><i class="bi bi-chat"></i></span>
<textarea class="form-control" name="comments" id="comments" rows="6"><?= $person_info->comments; ?></textarea>
</div>
<script type="text/javascript">

View File

@@ -8,6 +8,11 @@
<?= view('partial/header') ?>
<?php
$title_info['config_title'] = 'People';
echo view('configs/config_header', $title_info);
?>
<script type="text/javascript">
$(document).ready(function() {
<?= view('partial/bootstrap_tables_locale') ?>
@@ -32,24 +37,24 @@
});
</script>
<div id="title_bar" class="btn-toolbar">
<?php if ($controller_name === 'customers') { ?>
<button class="btn btn-info btn-sm pull-right modal-dlg" data-btn-submit="<?= lang('Common.submit') ?>" data-href="<?= "$controller_name/csvImport" ?>" title="<?= lang(ucfirst($controller_name) . '.import_items_csv') ?>">
<span class="glyphicon glyphicon-import">&nbsp;</span><?= lang('Common.import_csv') ?>
</button>
<?php } ?>
<button class="btn btn-info btn-sm pull-right modal-dlg" data-btn-submit="<?= lang('Common.submit') ?>" data-href="<?= "$controller_name/view" ?>" title="<?= lang(ucfirst($controller_name) . '.new') ?>">
<span class="glyphicon glyphicon-user">&nbsp;</span><?= lang(ucfirst($controller_name) . '.new') ?>
<div class="d-flex gap-2 justify-content-end">
<button type="button" class="btn btn-primary modal-launch" data-btn-submit="<?= lang('Common.submit') ?>" data-href="<?= "$controller_name/view" ?>" title="<?= lang(ucfirst($controller_name) . '.new') ?>">
<i class="bi bi-person-add me-2"></i><?= lang(ucfirst($controller_name) . '.new') ?>
</button>
<?php if ($controller_name == 'customers') { ?>
<button type="button" class="btn btn-primary modal-launch" data-btn-submit="<?= lang('Common.submit') ?>" data-href="<?= "$controller_name/csvImport" ?>" title="<?= lang(ucfirst($controller_name) . '.import_items_csv') ?>">
<i class="bi bi-file-earmark-arrow-down me-2"></i><?= lang('Common.import_csv') ?>
</button>
<?php } ?>
</div>
<div id="toolbar">
<div class="pull-left btn-toolbar">
<button id="delete" class="btn btn-default btn-sm">
<span class="glyphicon glyphicon-trash">&nbsp;</span><?= lang('Common.delete') ?>
<div class="d-flex gap-2">
<button type="button" class="btn btn-secondary" id="delete">
<i class="bi bi-trash"></i><span class="d-none d-sm-inline ms-2"><?= lang('Common.delete') ?></span>
</button>
<button id="email" class="btn btn-default btn-sm">
<span class="glyphicon glyphicon-envelope">&nbsp;</span><?= lang('Common.email') ?>
<button type="button" class="btn btn-secondary" id="email">
<i class="bi bi-envelope"></i><span class="d-none d-sm-inline ms-2"><?= lang('Common.email') ?></span>
</button>
</div>
</div>

View File

@@ -28,9 +28,9 @@ echo view('partial/print_receipt', ['print_after_sale', $print_after_sale, 'sele
<div class="print_hide" id="control_buttons" style="text-align: right;">
<a href="javascript:printdoc();">
<div class="btn btn-info btn-sm" id="show_print_button"><?= '<span class="glyphicon glyphicon-print">&nbsp;</span>' . lang('Common.print') ?></div>
<div class="btn btn-info btn-sm" id="show_print_button"><?= '<i class="bi bi-printer me-2"></i>' . lang('Common.print') ?></div>
</a>
<?= anchor("receivings", '<span class="glyphicon glyphicon-save">&nbsp;</span>' . lang('Receivings.register'), ['class' => 'btn btn-info btn-sm', 'id' => 'show_sales_button']) ?>
<?= anchor("receivings", '<i class="bi bi-box me-2"></i>' . lang('Receivings.register'), ['class' => 'btn btn-info btn-sm', 'id' => 'show_sales_button']) ?>
</div>
<div id="receipt_wrapper">

View File

@@ -46,7 +46,7 @@ if (isset($success)) {
<label class="control-label"><?= lang(ucfirst($controller_name) . '.mode') ?></label>
</li>
<li class="pull-left">
<?= form_dropdown('mode', $modes, $mode, ['onchange' => "$('#mode_form').submit();", 'class' => 'selectpicker show-menu-arrow', 'data-style' => 'btn-default btn-sm', 'data-width' => 'fit']) ?>
<?= form_dropdown('mode', $modes, $mode, ['onchange' => "$('#mode_form').submit();", 'class' => 'selectpicker', 'data-style' => 'btn-default btn-sm', 'data-width' => 'fit']) ?>
</li>
<?php if ($show_stock_locations) { ?>
@@ -54,7 +54,7 @@ if (isset($success)) {
<label class="control-label"><?= lang(ucfirst($controller_name) . '.stock_source') ?></label>
</li>
<li class="pull-left">
<?= form_dropdown('stock_source', $stock_locations, $stock_source, ['onchange' => "$('#mode_form').submit();", 'class' => 'selectpicker show-menu-arrow', 'data-style' => 'btn-default btn-sm', 'data-width' => 'fit']) ?>
<?= form_dropdown('stock_source', $stock_locations, $stock_source, ['onchange' => "$('#mode_form').submit();", 'class' => 'selectpicker', 'data-style' => 'btn-default btn-sm', 'data-width' => 'fit']) ?>
</li>
<?php if ($mode == 'requisition') { ?>
@@ -62,7 +62,7 @@ if (isset($success)) {
<label class="control-label"><?= lang(ucfirst($controller_name) . '.stock_destination') ?></label>
</li>
<li class="pull-left">
<?= form_dropdown('stock_destination', $stock_locations, $stock_destination, ['onchange' => "$('#mode_form').submit();", 'class' => 'selectpicker show-menu-arrow', 'data-style' => 'btn-default btn-sm', 'data-width' => 'fit']) ?>
<?= form_dropdown('stock_destination', $stock_locations, $stock_destination, ['onchange' => "$('#mode_form').submit();", 'class' => 'selectpicker', 'data-style' => 'btn-default btn-sm', 'data-width' => 'fit']) ?>
</li>
<?php
}
@@ -92,8 +92,8 @@ if (isset($success)) {
</li>
<li class="pull-right">
<button id="new_item_button" class="btn btn-info btn-sm pull-right modal-dlg" data-btn-submit="<?= lang('Common.submit') ?>" data-btn-new="<?= lang('Common.new') ?>" data-href="<?= "items/view" ?>" title="<?= lang('Sales.new_item') ?>">
<span class="glyphicon glyphicon-tag">&nbsp;</span><?= lang('Sales.new_item') ?>
<button id="new_item_button" class="btn btn-info btn-sm pull-right modal-launch" data-btn-submit="<?= lang('Common.submit') ?>" data-btn-new="<?= lang('Common.new') ?>" data-href="<?= "items/view" ?>" title="<?= lang('Sales.new_item') ?>">
<i class="bi bi-tag me-2"></i><?= lang('Sales.new_item') ?>
</button>
</li>
</ul>
@@ -133,7 +133,7 @@ if (isset($success)) {
<?= form_open("$controller_name/editItem/$line", ['class' => 'form-horizontal', 'id' => "cart_$line"]) ?>
<tr>
<td><?= anchor("$controller_name/deleteItem/$line", '<span class="glyphicon glyphicon-trash"></span>') ?></td>
<td><?= anchor("$controller_name/deleteItem/$line", '<i class="bi bi-trash"></i>') ?></td>
<td><?= esc($item['item_number']) ?></td>
<td style="text-align: center;">
<?= esc($item['name'] . ' ' . implode(' ', [$item['attribute_values'], $item['attribute_dtvalues']])) ?><br>
@@ -178,7 +178,7 @@ if (isset($success)) {
'id' => 'discount_toggle',
'name' => 'discount_toggle',
'value' => 1,
'data-toggle' => "toggle",
'data-toggle' => 'toggle',
'data-size' => 'small',
'data-onstyle' => 'success',
'data-on' => '<b>' . $config['currency_symbol'] . '</b>',
@@ -198,7 +198,7 @@ if (isset($success)) {
</td>
<td>
<a href="javascript:$('#<?= esc("cart_$line", 'js') ?>').submit();" title=<?= lang(ucfirst($controller_name) . '.update') ?>>
<span class="glyphicon glyphicon-refresh"></span>
<i class="bi bi-arrow-repeat"></i>
</a>
</td>
</tr>
@@ -272,7 +272,7 @@ if (isset($success)) {
<?= anchor(
"$controller_name/removeSupplier",
'<span class="glyphicon glyphicon-remove">&nbsp;</span>' . lang('Common.remove') . ' ' . lang('Suppliers.supplier'),
'<i class="bi bi-x-circle me-2"></i>' . lang('Common.remove') . ' ' . lang('Suppliers.supplier'),
[
'class' => 'btn btn-danger btn-sm',
'id' => 'remove_supplier_button',
@@ -295,8 +295,8 @@ if (isset($success)) {
'value' => lang(ucfirst($controller_name) . '.start_typing_supplier_name')
]) ?>
<button id="new_supplier_button" class="btn btn-info btn-sm modal-dlg" data-btn-submit="<?= lang('Common.submit') ?>" data-href="<?= "suppliers/view" ?>" title="<?= lang(ucfirst($controller_name) . '.new_supplier') ?>">
<span class="glyphicon glyphicon-user">&nbsp;</span><?= lang(ucfirst($controller_name) . '.new_supplier') ?>
<button id="new_supplier_button" class="btn btn-info btn-sm modal-launch" data-btn-submit="<?= lang('Common.submit') ?>" data-href="<?= "suppliers/view" ?>" title="<?= lang(ucfirst($controller_name) . '.new_supplier') ?>">
<i class="bi bi-building-add me-2"></i><?= lang(ucfirst($controller_name) . '.new_supplier') ?>
</button>
</div>
@@ -334,10 +334,10 @@ if (isset($success)) {
]) ?>
<div class="btn btn-sm btn-danger pull-left" id="cancel_receiving_button">
<span class="glyphicon glyphicon-remove">&nbsp;</span><?= lang(ucfirst($controller_name) . '.cancel_receiving') ?>
<i class="bi bi-x-circle me-2"></i><?= lang(ucfirst($controller_name) . '.cancel_receiving') ?>
</div>
<div class="btn btn-sm btn-success pull-right" id="finish_receiving_button">
<span class="glyphicon glyphicon-ok">&nbsp;</span><?= lang(ucfirst($controller_name) . '.complete_receiving') ?>
<i class="bi bi-check-circle me-2"></i><?= lang(ucfirst($controller_name) . '.complete_receiving') ?>
</div>
</div>
@@ -393,7 +393,7 @@ if (isset($success)) {
[],
[
'id' => 'payment_types',
'class' => 'selectpicker show-menu-arrow',
'class' => 'selectpicker',
'data-style' => 'btn-default btn-sm',
'data-width' => 'auto'
]
@@ -415,10 +415,10 @@ if (isset($success)) {
</div>
<div class="btn btn-sm btn-danger pull-left" id="cancel_receiving_button">
<span class="glyphicon glyphicon-remove">&nbsp;</span><?= lang(ucfirst($controller_name) . '.cancel_receiving') ?>
<i class="bi bi-x-circle me-2"></i><?= lang(ucfirst($controller_name) . '.cancel_receiving') ?>
</div>
<div class="btn btn-sm btn-success pull-right" id="finish_receiving_button">
<span class="glyphicon glyphicon-ok">&nbsp;</span><?= lang(ucfirst($controller_name) . '.complete_receiving') ?>
<i class="bi bi-check-circle me-2"></i><?= lang(ucfirst($controller_name) . '.complete_receiving') ?>
</div>
</div>
@@ -489,7 +489,7 @@ if (isset($success)) {
}
});
dialog_support.init("a.modal-dlg, button.modal-dlg");
dialog_support.init("a.modal-launch, button.modal-launch");
$('#supplier').blur(function() {
$(this).attr('value', "<?= lang(ucfirst($controller_name) . '.start_typing_supplier_name') ?>");

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