diff --git a/.github/workflows/README.md b/.github/workflows/README.md
new file mode 100644
index 000000000..ff51f5276
--- /dev/null
+++ b/.github/workflows/README.md
@@ -0,0 +1,61 @@
+# GitHub Actions
+
+This document describes the CI/CD workflows for OSPOS.
+
+## Build and Release Workflow (`.github/workflows/build-release.yml`)
+
+### Build Process
+- Setup PHP 8.2 with required extensions
+- Setup Node.js 20
+- Install composer dependencies
+- Install npm dependencies
+- Build frontend assets with Gulp
+
+### Docker Images
+- Build and push `opensourcepos` Docker image for multiple architectures (linux/amd64, linux/arm64)
+- On master: tagged with version and `latest`
+- On other branches: tagged with version only
+- Pushed to Docker Hub
+
+### Releases
+- Create distribution archives (tar.gz, zip)
+- Create/update GitHub "unstable" release on master branch only
+
+## Required Secrets
+
+To use this workflow, you need to add the following secrets to your repository:
+
+1. **DOCKER_USERNAME** - Docker Hub username for pushing images
+2. **DOCKER_PASSWORD** - Docker Hub password/token for pushing images
+
+### How to add secrets
+
+1. Go to your repository on GitHub
+2. Click **Settings** â **Secrets and variables** â **Actions**
+3. Click **New repository secret**
+4. Add `DOCKER_USERNAME` and `DOCKER_PASSWORD`
+
+The `GITHUB_TOKEN` is automatically provided by GitHub Actions.
+
+## Workflow Triggers
+
+- **Push to master** - Runs build, Docker push (with `latest` tag), and release
+- **Push to other branches** - Runs build and Docker push (version tag only)
+- **Push tags** - Runs build and Docker push (version tag only)
+- **Pull requests** - Runs build only (PHPUnit tests run in parallel via phpunit.yml)
+
+## Existing Workflows
+
+This repository also has these workflows:
+- `.github/workflows/main.yml` - PHP linting with PHP-CS-Fixer
+- `.github/workflows/phpunit.yml` - PHPUnit tests (runs on all PHP versions 8.1-8.4)
+- `.github/workflows/php-linter.yml` - PHP linting
+
+## Testing
+
+PHPUnit tests are run separately via `.github/workflows/phpunit.yml` on every push and pull request, testing against PHP 8.1, 8.2, 8.3, and 8.4.
+
+To test the build workflow:
+1. Add the required secrets
+2. Push to master or create a PR
+3. Monitor the Actions tab in GitHub
\ No newline at end of file
diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml
new file mode 100644
index 000000000..d7433d35c
--- /dev/null
+++ b/.github/workflows/build-release.yml
@@ -0,0 +1,218 @@
+name: Build and Release
+
+on:
+ push:
+ branches:
+ - master
+ tags:
+ - '*'
+ pull_request:
+ branches:
+ - master
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
+ cancel-in-progress: true
+
+permissions:
+ contents: read
+
+jobs:
+ build:
+ name: Build
+ runs-on: ubuntu-22.04
+
+ outputs:
+ version: ${{ steps.version.outputs.version }}
+ version-tag: ${{ steps.version.outputs.version-tag }}
+ short-sha: ${{ steps.version.outputs.short-sha }}
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: '8.2'
+ extensions: intl, mbstring, mysqli, gd, bcmath, zip
+ coverage: none
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: '20'
+
+ - name: Get composer cache directory
+ run: echo "COMPOSER_CACHE_FILES_DIR=$(composer config cache-files-dir)" >> $GITHUB_ENV
+
+ - name: Cache composer dependencies
+ uses: actions/cache@v4
+ with:
+ path: ${{ env.COMPOSER_CACHE_FILES_DIR }}
+ key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-composer-
+
+ - name: Get npm cache directory
+ run: echo "NPM_CACHE_DIR=$(npm config get cache)" >> $GITHUB_ENV
+
+ - name: Cache npm dependencies
+ uses: actions/cache@v4
+ with:
+ path: ${{ env.NPM_CACHE_DIR }}
+ key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
+ restore-keys: |
+ ${{ runner.os }}-node-
+
+ - name: Install composer dependencies
+ run: composer install --no-dev --optimize-autoloader
+
+ - name: Install npm dependencies
+ run: npm ci
+
+ - name: Install gulp globally
+ run: npm install -g gulp-cli
+
+ - name: Get version info
+ id: version
+ run: |
+ VERSION=$(grep "application_version" app/Config/App.php | sed "s/.*= '\(.*\)';/\1/g")
+ BRANCH=$(echo "${GITHUB_REF#refs/heads/}" | sed 's/feature\///')
+ TAG=$(echo "${GITHUB_TAG:-$BRANCH}" | tr '/' '-')
+ SHORT_SHA=$(git rev-parse --short=6 HEAD)
+ echo "version=$VERSION" >> $GITHUB_OUTPUT
+ echo "version-tag=$VERSION-$BRANCH-$SHORT_SHA" >> $GITHUB_OUTPUT
+ echo "short-sha=$SHORT_SHA" >> $GITHUB_OUTPUT
+ echo "branch=$BRANCH" >> $GITHUB_OUTPUT
+ env:
+ GITHUB_TAG: ${{ github.ref_name }}
+
+ - name: Create .env file
+ run: |
+ cp .env.example .env
+ sed -i 's/production/development/g' .env
+
+ - name: Update commit hash
+ run: |
+ SHORT_SHA="${{ steps.version.outputs.short-sha }}"
+ sed -i "s/commit_sha1 = 'dev'/commit_sha1 = '$SHORT_SHA'/g" app/Config/OSPOS.php
+
+ - name: Build frontend assets
+ run: npm run build
+
+ - name: Create distribution archives
+ run: |
+ set -euo pipefail
+ gulp compress
+ VERSION="${{ steps.version.outputs.version }}"
+ SHORT_SHA="${{ steps.version.outputs.short-sha }}"
+ mv dist/opensourcepos.tar "dist/opensourcepos.$VERSION.$SHORT_SHA.tar"
+ mv dist/opensourcepos.zip "dist/opensourcepos.$VERSION.$SHORT_SHA.zip"
+
+ - name: Upload build artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: dist-${{ steps.version.outputs.short-sha }}
+ path: dist/
+ retention-days: 7
+
+ - name: Upload build context for Docker
+ uses: actions/upload-artifact@v4
+ with:
+ name: build-context-${{ steps.version.outputs.short-sha }}
+ path: |
+ .
+ !.git
+ !node_modules
+ retention-days: 1
+
+ docker:
+ name: Build Docker Image
+ runs-on: ubuntu-22.04
+ needs: build
+ if: github.event_name == 'push'
+
+ steps:
+ - name: Download build context
+ uses: actions/download-artifact@v4
+ with:
+ name: build-context-${{ needs.build.outputs.short-sha }}
+ path: .
+
+ - name: Set up QEMU
+ uses: docker/setup-qemu-action@v3
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ - name: Login to Docker Hub
+ uses: docker/login-action@v3
+ with:
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_PASSWORD }}
+
+ - name: Determine Docker tags
+ id: tags
+ run: |
+ BRANCH=$(echo "${GITHUB_REF#refs/heads/}" | tr '/' '-')
+ if [ "$BRANCH" = "master" ]; then
+ echo "tags=${{ secrets.DOCKER_USERNAME }}/opensourcepos:${{ needs.build.outputs.version-tag }},${{ secrets.DOCKER_USERNAME }}/opensourcepos:latest" >> $GITHUB_OUTPUT
+ else
+ echo "tags=${{ secrets.DOCKER_USERNAME }}/opensourcepos:${{ needs.build.outputs.version-tag }}" >> $GITHUB_OUTPUT
+ fi
+ env:
+ GITHUB_REF: ${{ github.ref }}
+
+ - name: Build and push Docker images
+ uses: docker/build-push-action@v5
+ with:
+ context: .
+ target: ospos
+ platforms: linux/amd64,linux/arm64
+ push: true
+ tags: ${{ steps.tags.outputs.tags }}
+
+ release:
+ name: Create Release
+ needs: build
+ runs-on: ubuntu-22.04
+ if: github.event_name == 'push' && github.ref == 'refs/heads/master'
+ permissions:
+ contents: write
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Download build artifacts
+ uses: actions/download-artifact@v4
+ with:
+ name: dist-${{ needs.build.outputs.short-sha }}
+ path: dist/
+
+ - name: Get version info
+ id: version
+ run: |
+ VERSION="${{ needs.build.outputs.version }}"
+ SHORT_SHA=$(git rev-parse --short=6 HEAD)
+ echo "version=$VERSION" >> $GITHUB_OUTPUT
+ echo "short-sha=$SHORT_SHA" >> $GITHUB_OUTPUT
+
+ - name: Create/Update unstable release
+ uses: softprops/action-gh-release@v2
+ with:
+ tag_name: unstable
+ name: Unstable OpenSourcePOS
+ body: |
+ This is a build of the latest master which might contain bugs. Use at your own risk.
+
+ Check the releases section for the latest official release.
+ files: |
+ dist/opensourcepos.${{ steps.version.outputs.version }}.${{ steps.version.outputs.short-sha }}.zip
+ prerelease: true
+ draft: false
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
deleted file mode 100644
index 6218fde3a..000000000
--- a/.github/workflows/codeql-analysis.yml
+++ /dev/null
@@ -1,71 +0,0 @@
-# For most projects, this workflow file will not need changing; you simply need
-# to commit it to your repository.
-#
-# You may wish to alter this file to override the set of languages analyzed,
-# or to provide custom queries or build logic.
-#
-# ******** NOTE ********
-# We have attempted to detect the languages in your repository. Please check
-# the `language` matrix defined below to confirm you have the correct set of
-# supported CodeQL languages.
-#
-name: "CodeQL"
-
-on:
- push:
- branches: [ master ]
- pull_request:
- # The branches below must be a subset of the branches above
- branches: [ master ]
- schedule:
- - cron: '21 12 * * 3'
-
-jobs:
- analyze:
- name: Analyze
- runs-on: ubuntu-latest
- permissions:
- actions: read
- contents: read
- security-events: write
-
- strategy:
- fail-fast: false
- matrix:
- language: [ 'javascript' ]
- # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
- # Learn more:
- # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
-
- steps:
- - name: Checkout repository
- uses: actions/checkout@v2
-
- # Initializes the CodeQL tools for scanning.
- - name: Initialize CodeQL
- uses: github/codeql-action/init@v1
- with:
- languages: ${{ matrix.language }}
- # If you wish to specify custom queries, you can do so here or in a config file.
- # By default, queries listed here will override any specified in a config file.
- # Prefix the list here with "+" to use these queries and those in the config file.
- # queries: ./path/to/local/query, your-org/your-repo/queries@main
-
- # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
- # If this step fails, then you should remove it and run the build manually (see below)
- - name: Autobuild
- uses: github/codeql-action/autobuild@v1
-
- # âšī¸ Command-line programs to run using the OS shell.
- # đ https://git.io/JvXDl
-
- # âī¸ If the Autobuild fails above, remove it and uncomment the following three lines
- # and modify them (or add more) to build your code if your project
- # uses a compiled language
-
- #- run: |
- # make bootstrap
- # make release
-
- - name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v1
diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml
index fe7b3ff48..2198acaf8 100644
--- a/.github/workflows/phpunit.yml
+++ b/.github/workflows/phpunit.yml
@@ -69,9 +69,6 @@ jobs:
- name: Install npm dependencies
run: npm install
- - name: Build database.sql
- run: npm run gulp build-database
-
- name: Start MariaDB
run: |
docker run -d --name mysql \
@@ -79,7 +76,6 @@ jobs:
-e MYSQL_DATABASE=ospos \
-e MYSQL_USER=admin \
-e MYSQL_PASSWORD=pointofsale \
- -v $PWD/app/Database/database.sql:/docker-entrypoint-initdb.d/database.sql \
-p 3306:3306 \
mariadb:10.5
# Wait for MariaDB to be ready
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 908983cfd..000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,54 +0,0 @@
-sudo: required
-
-branches:
- except:
- - unstable
- - weblate
-services:
- - docker
-
-dist: jammy
-language: node_js
-node_js:
- - 20
-script:
- - echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
- - docker run --rm -u $(id -u) -v $(pwd):/app opensourcepos/composer:ci4 composer install
- - version=$(grep application_version app/Config/App.php | sed "s/.*=\s'\(.*\)';/\1/g")
- - cp .env.example .env && sed -i 's/production/development/g' .env
- - sed -i "s/commit_sha1 = 'dev'/commit_sha1 = '$rev'/g" app/Config/OSPOS.php
- - echo "$version-$branch-$rev"
- - npm version "$version-$branch-$rev" --force || true
- - sed -i 's/opensourcepos.tar.gz/opensourcepos.$version.tgz/g' package.json
- - npm ci && npm install -g gulp && npm run build
- - docker build . --target ospos -t ospos
- - docker build . --target ospos_test -t ospos_test
- - docker run --rm ospos_test /app/vendor/bin/phpunit --testdox
- - docker build app/Database/ -t "jekkos/opensourcepos:sql-$TAG"
-env:
- global:
- - BRANCH=$(echo ${TRAVIS_BRANCH} | sed s/feature\\///)
- - TAG=$(echo "${TRAVIS_TAG:-$BRANCH}" | tr '/' '-')
- - date=`date +%Y%m%d%H%M%S` && branch=${TRAVIS_BRANCH} && rev=`git rev-parse --short=6 HEAD`
-after_success:
- - docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD" && docker tag "ospos:latest"
- "jekkos/opensourcepos:$TAG" && docker push "jekkos/opensourcepos:$TAG" && docker push "jekkos/opensourcepos:sql-$TAG"
- - gulp compress
- - mv dist/opensourcepos.tar.gz "dist/opensourcepos.$version.$rev.tgz"
- - mv dist/opensourcepos.zip "dist/opensourcepos.$version.$rev.zip"
-deploy:
- - provider: releases
- edge: true
- file: dist/opensourcepos.$version.$rev.zip
- name: "Unstable OpensourcePos"
- overwrite: true
- release_notes: "This is a build of the latest master which might contain bugs. Use at your own risk. Check releases section for the latest official release"
- prerelease: true
- tag_name: unstable
- user: jekkos
-
- api_key:
- secure: "KOukL8IFf/uL/BjMyCSKjf2vylydjcWqgEx0eMqFCg3nZ4ybMaOwPORRthIfyT72/FvGX/aoxxEn0uR/AEtb+hYQXHmNS+kZdX72JCe8LpGuZ7FJ5X+Eo9mhJcsmS+smd1sC95DySSc/GolKPo+0WtJYONY/xGCLxm+9Ay4HREg="
-
- on:
- branch: master
diff --git a/Dockerfile b/Dockerfile
index 376b0834d..ca1b5a46c 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -11,19 +11,6 @@ COPY . /app
RUN ln -s /app/*[^public] /var/www && rm -rf /var/www/html && ln -nsf /app/public /var/www/html
RUN chmod -R 770 /app/writable/uploads /app/writable/logs /app/writable/cache && chown -R www-data:www-data /app
-FROM ospos AS ospos_test
-
-COPY --from=composer /usr/bin/composer /usr/bin/composer
-
-RUN apt-get install -y libzip-dev wget git
-RUN wget https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh -O /bin/wait-for-it.sh && chmod +x /bin/wait-for-it.sh
-RUN docker-php-ext-install zip
-RUN composer install -d/app
-#RUN sed -i 's/backupGlobals="true"/backupGlobals="false"/g' /app/tests/phpunit.xml
-WORKDIR /app/tests
-
-CMD ["/app/vendor/phpunit/phpunit/phpunit", "/app/test/helpers"]
-
FROM ospos AS ospos_dev
ARG USERID
diff --git a/INSTALL.md b/INSTALL.md
index df08c0afc..b63ff893f 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -38,20 +38,21 @@ FORCE_HTTPS = true
## Local install
-First of all, if you're seeing the message `system folder missing` after launching your browser, or cannot find `database.sql`, that most likely means you have cloned the repository and have not built the project. To build the project from a source commit point instead of from an official release check out [Building OSPOS](BUILD.md). Otherwise, continue with the following steps.
+First of all, if you're seeing the message `system folder missing` after launching your browser, that most likely means you have cloned the repository and have not built the project. To build the project from a source commit point instead of from an official release check out [Building OSPOS](BUILD.md). Otherwise, continue with the following steps.
1. Download the a [pre-release for a specific branch](https://github.com/opensourcepos/opensourcepos/releases) or the latest stable [from GitHub here](https://github.com/opensourcepos/opensourcepos/releases). A repository clone will not work unless know how to build the project.
2. Create/locate a new MySQL database to install Open Source Point of Sale into.
-3. Execute the file `app/Database/database.sql` to create the tables needed.
-4. Unzip and upload Open Source Point of Sale files to the web-server.
-5. Open `.env` file and modify credentials to connect to your database if needed. (First copy .env.example to .env and update)
+3. Unzip and upload Open Source Point of Sale files to the web-server.
+4. If `.env` does not exist, copy `.env.example` to `.env`.
+5. Open `.env` and modify credentials to connect to your database if needed.
+6. The database schema will be automatically created when you first access the application. Migrations run automatically on fresh installs.
7. Go to your install `public` dir via the browser.
8. Log in using
- Username: admin
- Password: pointofsale
9. If everything works, then set the `CI_ENVIRONMENT` variable to `production` in the .env file
-9. Enjoy!
-10. Oops, an issue? Please make sure you read the FAQ, wiki page, and you checked open and closed issues on GitHub. PHP `display_errors` is disabled by default. Create an` app/Config/.env` file from the `.env.example` to enable it in a development environment.
+10. Enjoy!
+11. Oops, an issue? Please make sure you read the FAQ, wiki page, and you checked open and closed issues on GitHub. PHP `display_errors` is disabled by default. Create an` app/Config/.env` file from the `.env.example` to enable it in a development environment.
## Local install using Docker
diff --git a/README.md b/README.md
index 755c73f60..1a46a4386 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@
-
+
@@ -137,7 +137,7 @@ Any person or company found breaching the license agreement might find a bunch o
## đ Credits
-|
DigitalOcean
| JetBrains
| Travis CI
|
+| DigitalOcean
| JetBrains
| GitHub
|
| --- | --- | --- |
-| | | |
-| Many thanks to [DigitalOcean](https://www.digitalocean.com) for providing the project with hosting credits. | Many thanks to [JetBrains](https://www.jetbrains.com/) for providing a free license of [IntelliJ IDEA](https://www.jetbrains.com/idea/) to kindly support the development of OSPOS. | Many thanks to [Travis CI](https://www.travis-ci.com/) for providing a free continuous integration service for open source projects. |
+| | | |
+| Many thanks to [DigitalOcean](https://www.digitalocean.com) for providing the project with hosting credits. | Many thanks to [JetBrains](https://www.jetbrains.com/) for providing a free license of [IntelliJ IDEA](https://www.jetbrains.com/idea/) to kindly support the development of OSPOS. | Many thanks to [GitHub](https://github.com) for providing free continuous integration via GitHub Actions for open-source projects. |
diff --git a/app/Database/Migrations/20170501000000_initial_schema.php b/app/Database/Migrations/20170501000000_initial_schema.php
new file mode 100644
index 000000000..0424dba03
--- /dev/null
+++ b/app/Database/Migrations/20170501000000_initial_schema.php
@@ -0,0 +1,60 @@
+db->listTables();
+
+ // Check for a core application table, not just migrations table
+ foreach ($tables as $table) {
+ // Strip prefix if present for comparison
+ $tableName = str_replace($this->db->getPrefix(), '', $table);
+ if (in_array($tableName, ['app_config', 'items', 'employees', 'people'])) {
+ // Database already populated - skip initial schema
+ // This is an existing installation upgrading from older version
+ return;
+ }
+ }
+
+ // Fresh install - load initial schema
+ helper('migration');
+ execute_script(APPPATH . 'Database/Migrations/sqlscripts/initial_schema.sql');
+ }
+
+ /**
+ * Revert a migration step.
+ * Cannot revert initial schema - would lose all data.
+ */
+ public function down(): void
+ {
+ // Cannot safely revert initial schema
+ // Would require dropping all tables which would lose all data
+ $this->db->query('SET FOREIGN_KEY_CHECKS = 0');
+
+ foreach ($this->db->listTables() as $table) {
+ $this->db->query('DROP TABLE IF EXISTS `' . $table . '`');
+ }
+
+ $this->db->query('SET FOREIGN_KEY_CHECKS = 1');
+ }
+}
\ No newline at end of file
diff --git a/app/Database/Migrations/sqlscripts/initial_schema.sql b/app/Database/Migrations/sqlscripts/initial_schema.sql
new file mode 100644
index 000000000..0823793a5
--- /dev/null
+++ b/app/Database/Migrations/sqlscripts/initial_schema.sql
@@ -0,0 +1,877 @@
+
+--
+-- Table structure for table `ospos_app_config`
+--
+
+CREATE TABLE `ospos_app_config` (
+ `key` varchar(50) NOT NULL,
+ `value` varchar(500) NOT NULL,
+ PRIMARY KEY (`key`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `ospos_app_config`
+--
+
+INSERT INTO `ospos_app_config` (`key`, `value`) VALUES
+ ('address', '123 Nowhere street'),
+ ('company', 'Open Source Point of Sale'),
+ ('default_tax_rate', '8'),
+ ('email', 'changeme@example.com'),
+ ('fax', ''),
+ ('phone', '555-555-5555'),
+ ('return_policy', 'Test'),
+ ('timezone', 'America/New_York'),
+ ('website', ''),
+ ('company_logo', ''),
+ ('tax_included', '0'),
+ ('barcode_content', 'id'),
+ ('barcode_type', 'Code39'),
+ ('barcode_width', '250'),
+ ('barcode_height', '50'),
+ ('barcode_quality', '100'),
+ ('barcode_font', 'Arial'),
+ ('barcode_font_size', '10'),
+ ('barcode_first_row', 'category'),
+ ('barcode_second_row', 'item_code'),
+ ('barcode_third_row', 'unit_price'),
+ ('barcode_num_in_row', '2'),
+ ('barcode_page_width', '100'),
+ ('barcode_page_cellspacing', '20'),
+ ('barcode_generate_if_empty', '0'),
+ ('receipt_show_taxes', '0'),
+ ('receipt_show_total_discount', '1'),
+ ('receipt_show_description', '1'),
+ ('receipt_show_serialnumber', '1'),
+ ('invoice_enable', '1'),
+ ('recv_invoice_format', '$CO'),
+ ('sales_invoice_format', '$CO'),
+ ('invoice_email_message', 'Dear $CU, In attachment the receipt for sale $INV'),
+ ('invoice_default_comments', 'This is a default comment'),
+ ('print_silently', '1'),
+ ('print_header', '0'),
+ ('print_footer', '0'),
+ ('print_top_margin', '0'),
+ ('print_left_margin', '0'),
+ ('print_bottom_margin', '0'),
+ ('print_right_margin', '0'),
+ ('default_sales_discount', '0'),
+ ('lines_per_page', '25'),
+ ('dateformat', 'm/d/Y'),
+ ('timeformat', 'H:i:s'),
+ ('currency_symbol', '$'),
+ ('number_locale', 'en_US'),
+ ('thousands_separator', '1'),
+ ('currency_decimals', '2'),
+ ('tax_decimals', '2'),
+ ('quantity_decimals', '0'),
+ ('country_codes', 'us'),
+ ('msg_msg', ''),
+ ('msg_uid', ''),
+ ('msg_src', ''),
+ ('msg_pwd', ''),
+ ('notify_horizontal_position', 'center'),
+ ('notify_vertical_position', 'bottom'),
+ ('payment_options_order', 'cashdebitcredit'),
+ ('protocol', 'mail'),
+ ('mailpath', '/usr/sbin/sendmail'),
+ ('smtp_port', '465'),
+ ('smtp_timeout', '5'),
+ ('smtp_crypto', 'ssl'),
+ ('receipt_template', 'receipt_default'),
+ ('theme', 'flatly'),
+ ('statistics', '1'),
+ ('language', 'english'),
+ ('language_code', 'en');
+
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ospos_customers`
+--
+
+CREATE TABLE `ospos_customers` (
+ `person_id` int(10) NOT NULL,
+ `company_name` varchar(255) DEFAULT NULL,
+ `account_number` varchar(255) DEFAULT NULL,
+ `taxable` int(1) NOT NULL DEFAULT '1',
+ `discount_percent` decimal(15,2) NOT NULL DEFAULT '0',
+ `deleted` int(1) NOT NULL DEFAULT '0',
+ PRIMARY KEY `person_id` (`person_id`),
+ UNIQUE KEY `account_number` (`account_number`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `ospos_customers`
+--
+
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ospos_employees`
+--
+
+CREATE TABLE `ospos_employees` (
+ `username` varchar(255) NOT NULL,
+ `password` varchar(255) NOT NULL,
+ `person_id` int(10) NOT NULL,
+ `deleted` int(1) NOT NULL DEFAULT '0',
+ `hash_version` int(1) NOT NULL DEFAULT '2',
+ PRIMARY KEY `person_id` (`person_id`),
+ UNIQUE KEY `username` (`username`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `ospos_employees`
+--
+
+INSERT INTO `ospos_employees` (`username`, `password`, `person_id`, `deleted`, `hash_version`) VALUES
+ ('admin', '$2y$10$vJBSMlD02EC7ENSrKfVQXuvq9tNRHMtcOA8MSK2NYS748HHWm.gcG', 1, 0, 2);
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ospos_giftcards`
+--
+
+CREATE TABLE `ospos_giftcards` (
+ `record_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `giftcard_id` int(11) NOT NULL AUTO_INCREMENT,
+ `giftcard_number` int(10) NOT NULL,
+ `value` decimal(15,2) NOT NULL,
+ `deleted` int(1) NOT NULL DEFAULT '0',
+ `person_id` INT(10) DEFAULT NULL,
+ PRIMARY KEY (`giftcard_id`),
+ UNIQUE KEY `giftcard_number` (`giftcard_number`),
+ KEY `person_id` (`person_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `ospos_giftcards`
+--
+
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ospos_inventory`
+--
+
+CREATE TABLE `ospos_inventory` (
+ `trans_id` int(11) NOT NULL AUTO_INCREMENT,
+ `trans_items` int(11) NOT NULL DEFAULT '0',
+ `trans_user` int(11) NOT NULL DEFAULT '0',
+ `trans_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `trans_comment` text NOT NULL,
+ `trans_location` int(11) NOT NULL,
+ `trans_inventory` decimal(15,3) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`trans_id`),
+ KEY `trans_items` (`trans_items`),
+ KEY `trans_user` (`trans_user`),
+ KEY `trans_location` (`trans_location`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
+
+--
+-- Dumping data for table `ospos_inventory`
+--
+
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ospos_items`
+--
+
+CREATE TABLE `ospos_items` (
+ `name` varchar(255) NOT NULL,
+ `category` varchar(255) NOT NULL,
+ `supplier_id` int(11) DEFAULT NULL,
+ `item_number` varchar(255) DEFAULT NULL,
+ `description` varchar(255) NOT NULL,
+ `cost_price` decimal(15,2) NOT NULL,
+ `unit_price` decimal(15,2) NOT NULL,
+ `reorder_level` decimal(15,3) NOT NULL DEFAULT '0',
+ `receiving_quantity` decimal(15,3) NOT NULL DEFAULT '1',
+ `item_id` int(10) NOT NULL AUTO_INCREMENT,
+ `pic_id` int(10) DEFAULT NULL,
+ `allow_alt_description` tinyint(1) NOT NULL,
+ `is_serialized` tinyint(1) NOT NULL,
+ `deleted` int(1) NOT NULL DEFAULT '0',
+ `custom1` VARCHAR(25) NOT NULL,
+ `custom2` VARCHAR(25) NOT NULL,
+ `custom3` VARCHAR(25) NOT NULL,
+ `custom4` VARCHAR(25) NOT NULL,
+ `custom5` VARCHAR(25) NOT NULL,
+ `custom6` VARCHAR(25) NOT NULL,
+ `custom7` VARCHAR(25) NOT NULL,
+ `custom8` VARCHAR(25) NOT NULL,
+ `custom9` VARCHAR(25) NOT NULL,
+ `custom10` VARCHAR(25) NOT NULL,
+ PRIMARY KEY (`item_id`),
+ UNIQUE KEY `item_number` (`item_number`),
+ KEY `supplier_id` (`supplier_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
+
+--
+-- Dumping data for table `ospos_items`
+--
+
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ospos_items_taxes`
+--
+
+CREATE TABLE `ospos_items_taxes` (
+ `item_id` int(10) NOT NULL,
+ `name` varchar(255) NOT NULL,
+ `percent` decimal(15,3) NOT NULL,
+ PRIMARY KEY (`item_id`,`name`,`percent`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `ospos_items_taxes`
+--
+
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ospos_item_kits`
+--
+
+CREATE TABLE `ospos_item_kits` (
+ `item_kit_id` int(11) NOT NULL AUTO_INCREMENT,
+ `name` varchar(255) NOT NULL,
+ `description` varchar(255) NOT NULL,
+ PRIMARY KEY (`item_kit_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
+
+--
+-- Dumping data for table `ospos_item_kits`
+--
+
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ospos_item_kit_items`
+--
+
+CREATE TABLE `ospos_item_kit_items` (
+ `item_kit_id` int(11) NOT NULL,
+ `item_id` int(11) NOT NULL,
+ `quantity` decimal(15,3) NOT NULL,
+ PRIMARY KEY (`item_kit_id`,`item_id`,`quantity`),
+ KEY `ospos_item_kit_items_ibfk_2` (`item_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `ospos_item_kit_items`
+--
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ospos_item_quantities`
+--
+
+CREATE TABLE IF NOT EXISTS `ospos_item_quantities` (
+ `item_id` int(11) NOT NULL,
+ `location_id` int(11) NOT NULL,
+ `quantity` decimal(15,3) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`item_id`,`location_id`),
+ KEY `item_id` (`item_id`),
+ KEY `location_id` (`location_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ospos_modules`
+--
+
+CREATE TABLE `ospos_modules` (
+ `name_lang_key` varchar(255) NOT NULL,
+ `desc_lang_key` varchar(255) NOT NULL,
+ `sort` int(10) NOT NULL,
+ `module_id` varchar(255) NOT NULL,
+ PRIMARY KEY (`module_id`),
+ UNIQUE KEY `desc_lang_key` (`desc_lang_key`),
+ UNIQUE KEY `name_lang_key` (`name_lang_key`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `ospos_modules`
+--
+
+INSERT INTO `ospos_modules` (`name_lang_key`, `desc_lang_key`, `sort`, `module_id`) VALUES
+ ('module_config', 'module_config_desc', 110, 'config'),
+ ('module_customers', 'module_customers_desc', 10, 'customers'),
+ ('module_employees', 'module_employees_desc', 80, 'employees'),
+ ('module_giftcards', 'module_giftcards_desc', 90, 'giftcards'),
+ ('module_items', 'module_items_desc', 20, 'items'),
+ ('module_item_kits', 'module_item_kits_desc', 30, 'item_kits'),
+ ('module_messages', 'module_messages_desc', 100, 'messages'),
+ ('module_receivings', 'module_receivings_desc', 60, 'receivings'),
+ ('module_reports', 'module_reports_desc', 50, 'reports'),
+ ('module_sales', 'module_sales_desc', 70, 'sales'),
+ ('module_suppliers', 'module_suppliers_desc', 40, 'suppliers');
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ospos_people`
+--
+
+CREATE TABLE `ospos_people` (
+ `first_name` varchar(255) NOT NULL,
+ `last_name` varchar(255) NOT NULL,
+ `gender` int(1) DEFAULT NULL,
+ `phone_number` varchar(255) NOT NULL,
+ `email` varchar(255) NOT NULL,
+ `address_1` varchar(255) NOT NULL,
+ `address_2` varchar(255) NOT NULL,
+ `city` varchar(255) NOT NULL,
+ `state` varchar(255) NOT NULL,
+ `zip` varchar(255) NOT NULL,
+ `country` varchar(255) NOT NULL,
+ `comments` text NOT NULL,
+ `person_id` int(10) NOT NULL AUTO_INCREMENT,
+ PRIMARY KEY (`person_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
+
+--
+-- Dumping data for table `ospos_people`
+--
+
+INSERT INTO `ospos_people` (`first_name`, `last_name`, `phone_number`, `email`, `address_1`, `address_2`, `city`, `state`, `zip`, `country`, `comments`, `person_id`) VALUES
+ ('John', 'Doe', '555-555-5555', 'changeme@example.com', 'Address 1', '', '', '', '', '', '', 1);
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ospos_permissions`
+--
+
+CREATE TABLE `ospos_permissions` (
+ `permission_id` varchar(255) NOT NULL,
+ `module_id` varchar(255) NOT NULL,
+ `location_id` int(10) DEFAULT NULL,
+ PRIMARY KEY (`permission_id`),
+ KEY `module_id` (`module_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `ospos_permissions`
+--
+
+INSERT INTO `ospos_permissions` (`permission_id`, `module_id`) VALUES
+ ('reports_customers', 'reports'),
+ ('reports_receivings', 'reports'),
+ ('reports_items', 'reports'),
+ ('reports_employees', 'reports'),
+ ('reports_suppliers', 'reports'),
+ ('reports_sales', 'reports'),
+ ('reports_discounts', 'reports'),
+ ('reports_taxes', 'reports'),
+ ('reports_inventory', 'reports'),
+ ('reports_categories', 'reports'),
+ ('reports_payments', 'reports'),
+ ('customers', 'customers'),
+ ('employees', 'employees'),
+ ('giftcards', 'giftcards'),
+ ('items', 'items'),
+ ('item_kits', 'item_kits'),
+ ('messages', 'messages'),
+ ('receivings', 'receivings'),
+ ('reports', 'reports'),
+ ('sales', 'sales'),
+ ('config', 'config'),
+ ('suppliers', 'suppliers');
+
+INSERT INTO `ospos_permissions` (`permission_id`, `module_id`, `location_id`) VALUES
+ ('items_stock', 'items', 1),
+ ('sales_stock', 'sales', 1),
+ ('receivings_stock', 'receivings', 1);
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ospos_grants`
+--
+
+CREATE TABLE `ospos_grants` (
+ `permission_id` varchar(255) NOT NULL,
+ `person_id` int(10) NOT NULL,
+ PRIMARY KEY (`permission_id`,`person_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `ospos_grants`
+--
+-- --------------------------------------------------------
+
+INSERT INTO `ospos_grants` (`permission_id`, `person_id`) VALUES
+ ('reports_customers', 1),
+ ('reports_receivings', 1),
+ ('reports_items', 1),
+ ('reports_inventory', 1),
+ ('reports_employees', 1),
+ ('reports_suppliers', 1),
+ ('reports_sales', 1),
+ ('reports_discounts', 1),
+ ('reports_taxes', 1),
+ ('reports_categories', 1),
+ ('reports_payments', 1),
+ ('customers', 1),
+ ('employees', 1),
+ ('giftcards', 1),
+ ('items', 1),
+ ('item_kits', 1),
+ ('messages', 1),
+ ('receivings', 1),
+ ('reports', 1),
+ ('sales', 1),
+ ('config', 1),
+ ('items_stock', 1),
+ ('sales_stock', 1),
+ ('receivings_stock', 1),
+ ('suppliers', 1);
+
+--
+-- Table structure for table `ospos_receivings`
+--
+
+CREATE TABLE `ospos_receivings` (
+ `receiving_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `supplier_id` int(10) DEFAULT NULL,
+ `employee_id` int(10) NOT NULL DEFAULT '0',
+ `comment` text NOT NULL,
+ `receiving_id` int(10) NOT NULL AUTO_INCREMENT,
+ `payment_type` varchar(20) DEFAULT NULL,
+ `reference` varchar(32) DEFAULT NULL,
+ PRIMARY KEY (`receiving_id`),
+ KEY `supplier_id` (`supplier_id`),
+ KEY `employee_id` (`employee_id`),
+ KEY `reference` (`reference`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
+
+--
+-- Dumping data for table `ospos_receivings`
+--
+
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ospos_receivings_items`
+--
+
+CREATE TABLE `ospos_receivings_items` (
+ `receiving_id` int(10) NOT NULL DEFAULT '0',
+ `item_id` int(10) NOT NULL DEFAULT '0',
+ `description` varchar(30) DEFAULT NULL,
+ `serialnumber` varchar(30) DEFAULT NULL,
+ `line` int(3) NOT NULL,
+ `quantity_purchased` decimal(15,3) NOT NULL DEFAULT '0',
+ `item_cost_price` decimal(15,2) NOT NULL,
+ `item_unit_price` decimal(15,2) NOT NULL,
+ `discount_percent` decimal(15,2) NOT NULL DEFAULT '0',
+ `item_location` int(11) NOT NULL,
+ `receiving_quantity` decimal(15,3) NOT NULL DEFAULT '1',
+ PRIMARY KEY (`receiving_id`,`item_id`,`line`),
+ KEY `item_id` (`item_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `ospos_receivings_items`
+--
+
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ospos_sales`
+--
+
+CREATE TABLE `ospos_sales` (
+ `sale_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `customer_id` int(10) DEFAULT NULL,
+ `employee_id` int(10) NOT NULL DEFAULT '0',
+ `comment` text NOT NULL,
+ `invoice_number` varchar(32) DEFAULT NULL,
+ `sale_id` int(10) NOT NULL AUTO_INCREMENT,
+ PRIMARY KEY (`sale_id`),
+ KEY `customer_id` (`customer_id`),
+ KEY `employee_id` (`employee_id`),
+ KEY `sale_time` (`sale_time`),
+ UNIQUE KEY `invoice_number` (`invoice_number`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
+
+--
+-- Dumping data for table `ospos_sales`
+--
+
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ospos_sales_items`
+--
+
+CREATE TABLE `ospos_sales_items` (
+ `sale_id` int(10) NOT NULL DEFAULT '0',
+ `item_id` int(10) NOT NULL DEFAULT '0',
+ `description` varchar(30) DEFAULT NULL,
+ `serialnumber` varchar(30) DEFAULT NULL,
+ `line` int(3) NOT NULL DEFAULT '0',
+ `quantity_purchased` decimal(15,3) NOT NULL DEFAULT '0',
+ `item_cost_price` decimal(15,2) NOT NULL,
+ `item_unit_price` decimal(15,2) NOT NULL,
+ `discount_percent` decimal(15,2) NOT NULL DEFAULT '0',
+ `item_location` int(11) NOT NULL,
+ PRIMARY KEY (`sale_id`,`item_id`,`line`),
+ KEY `sale_id` (`sale_id`),
+ KEY `item_id` (`item_id`),
+ KEY `item_location` (`item_location`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `ospos_sales_items`
+--
+
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ospos_sales_items_taxes`
+--
+
+CREATE TABLE `ospos_sales_items_taxes` (
+ `sale_id` int(10) NOT NULL,
+ `item_id` int(10) NOT NULL,
+ `line` int(3) NOT NULL DEFAULT '0',
+ `name` varchar(255) NOT NULL,
+ `percent` decimal(15,3) NOT NULL,
+ PRIMARY KEY (`sale_id`,`item_id`,`line`,`name`,`percent`),
+ KEY `sale_id` (`sale_id`),
+ KEY `item_id` (`item_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `ospos_sales_items_taxes`
+--
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ospos_sales_payments`
+--
+
+CREATE TABLE `ospos_sales_payments` (
+ `sale_id` int(10) NOT NULL,
+ `payment_type` varchar(40) NOT NULL,
+ `payment_amount` decimal(15,2) NOT NULL,
+ PRIMARY KEY (`sale_id`,`payment_type`),
+ KEY `sale_id` (`sale_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `ospos_sales_payments`
+--
+
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ospos_sales_suspended`
+--
+
+CREATE TABLE `ospos_sales_suspended` (
+ `sale_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `customer_id` int(10) DEFAULT NULL,
+ `employee_id` int(10) NOT NULL DEFAULT '0',
+ `comment` text NOT NULL,
+ `invoice_number` varchar(32) DEFAULT NULL,
+ `sale_id` int(10) NOT NULL AUTO_INCREMENT,
+ PRIMARY KEY (`sale_id`),
+ KEY `customer_id` (`customer_id`),
+ KEY `employee_id` (`employee_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
+
+--
+-- Dumping data for table `ospos_sales_suspended`
+--
+
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ospos_sales_suspended_items`
+--
+
+CREATE TABLE `ospos_sales_suspended_items` (
+ `sale_id` int(10) NOT NULL DEFAULT '0',
+ `item_id` int(10) NOT NULL DEFAULT '0',
+ `description` varchar(30) DEFAULT NULL,
+ `serialnumber` varchar(30) DEFAULT NULL,
+ `line` int(3) NOT NULL DEFAULT '0',
+ `quantity_purchased` decimal(15,3) NOT NULL DEFAULT '0',
+ `item_cost_price` decimal(15,2) NOT NULL,
+ `item_unit_price` decimal(15,2) NOT NULL,
+ `discount_percent` decimal(15,2) NOT NULL DEFAULT '0',
+ `item_location` int(11) NOT NULL,
+ PRIMARY KEY (`sale_id`,`item_id`,`line`),
+ KEY `sale_id` (`sale_id`),
+ KEY `item_id` (`item_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `ospos_sales_suspended_items`
+--
+
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ospos_sales_suspended_items_taxes`
+--
+
+CREATE TABLE `ospos_sales_suspended_items_taxes` (
+ `sale_id` int(10) NOT NULL,
+ `item_id` int(10) NOT NULL,
+ `line` int(3) NOT NULL DEFAULT '0',
+ `name` varchar(255) NOT NULL,
+ `percent` decimal(15,3) NOT NULL,
+ PRIMARY KEY (`sale_id`,`item_id`,`line`,`name`,`percent`),
+ KEY `item_id` (`item_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `ospos_sales_suspended_items_taxes`
+--
+
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ospos_sales_suspended_payments`
+--
+
+CREATE TABLE `ospos_sales_suspended_payments` (
+ `sale_id` int(10) NOT NULL,
+ `payment_type` varchar(40) NOT NULL,
+ `payment_amount` decimal(15,2) NOT NULL,
+ PRIMARY KEY (`sale_id`,`payment_type`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `ospos_sales_suspended_payments`
+--
+
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ospos_sessions`
+--
+
+CREATE TABLE `ospos_sessions` (
+ `id` varchar(40) NOT NULL,
+ `ip_address` varchar(45) NOT NULL,
+ `timestamp` int(10) unsigned DEFAULT 0 NOT NULL,
+ `data` blob NOT NULL,
+ KEY `ci_sessions_timestamp` (`timestamp`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `ospos_sessions`
+--
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ospos_stock_locations`
+--
+
+CREATE TABLE `ospos_stock_locations` (
+ `location_id` int(11) NOT NULL AUTO_INCREMENT,
+ `location_name` varchar(255) DEFAULT NULL,
+ `deleted` int(1) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`location_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
+
+--
+-- Dumping data for table `ospos_stock_locations`
+--
+
+INSERT INTO `ospos_stock_locations` ( `deleted`, `location_name` ) VALUES ('0', 'stock');
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `ospos_suppliers`
+--
+
+CREATE TABLE `ospos_suppliers` (
+ `person_id` int(10) NOT NULL,
+ `company_name` varchar(255) NOT NULL,
+ `agency_name` varchar(255) NOT NULL,
+ `account_number` varchar(255) DEFAULT NULL,
+ `deleted` int(1) NOT NULL DEFAULT '0',
+ PRIMARY KEY `person_id` (`person_id`),
+ UNIQUE KEY `account_number` (`account_number`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `ospos_suppliers`
+--
+--
+-- Constraints for dumped tables
+--
+
+--
+-- Constraints for table `ospos_customers`
+--
+ALTER TABLE `ospos_customers`
+ ADD CONSTRAINT `ospos_customers_ibfk_1` FOREIGN KEY (`person_id`) REFERENCES `ospos_people` (`person_id`);
+
+--
+-- Constraints for table `ospos_employees`
+--
+ALTER TABLE `ospos_employees`
+ ADD CONSTRAINT `ospos_employees_ibfk_1` FOREIGN KEY (`person_id`) REFERENCES `ospos_people` (`person_id`);
+
+--
+-- Constraints for table `ospos_inventory`
+--
+ALTER TABLE `ospos_inventory`
+ ADD CONSTRAINT `ospos_inventory_ibfk_1` FOREIGN KEY (`trans_items`) REFERENCES `ospos_items` (`item_id`),
+ ADD CONSTRAINT `ospos_inventory_ibfk_2` FOREIGN KEY (`trans_user`) REFERENCES `ospos_employees` (`person_id`),
+ ADD CONSTRAINT `ospos_inventory_ibfk_3` FOREIGN KEY (`trans_location`) REFERENCES `ospos_stock_locations` (`location_id`);
+
+--
+-- Constraints for table `ospos_items`
+--
+ALTER TABLE `ospos_items`
+ ADD CONSTRAINT `ospos_items_ibfk_1` FOREIGN KEY (`supplier_id`) REFERENCES `ospos_suppliers` (`person_id`);
+
+--
+-- Constraints for table `ospos_items_taxes`
+--
+ALTER TABLE `ospos_items_taxes`
+ ADD CONSTRAINT `ospos_items_taxes_ibfk_1` FOREIGN KEY (`item_id`) REFERENCES `ospos_items` (`item_id`) ON DELETE CASCADE;
+
+--
+-- Constraints for table `ospos_item_kit_items`
+--
+ALTER TABLE `ospos_item_kit_items`
+ ADD CONSTRAINT `ospos_item_kit_items_ibfk_1` FOREIGN KEY (`item_kit_id`) REFERENCES `ospos_item_kits` (`item_kit_id`) ON DELETE CASCADE,
+ ADD CONSTRAINT `ospos_item_kit_items_ibfk_2` FOREIGN KEY (`item_id`) REFERENCES `ospos_items` (`item_id`) ON DELETE CASCADE;
+
+--
+-- Constraints for table `ospos_permissions`
+--
+ALTER TABLE `ospos_permissions`
+ ADD CONSTRAINT `ospos_permissions_ibfk_1` FOREIGN KEY (`module_id`) REFERENCES `ospos_modules` (`module_id`) ON DELETE CASCADE,
+ ADD CONSTRAINT `ospos_permissions_ibfk_2` FOREIGN KEY (`location_id`) REFERENCES `ospos_stock_locations` (`location_id`) ON DELETE CASCADE;
+
+--
+-- Constraints for table `ospos_grants`
+--
+ALTER TABLE `ospos_grants`
+ ADD CONSTRAINT `ospos_grants_ibfk_1` foreign key (`permission_id`) references `ospos_permissions` (`permission_id`) ON DELETE CASCADE,
+ ADD CONSTRAINT `ospos_grants_ibfk_2` foreign key (`person_id`) references `ospos_employees` (`person_id`) ON DELETE CASCADE;
+
+--
+-- Constraints for table `ospos_receivings`
+--
+ALTER TABLE `ospos_receivings`
+ ADD CONSTRAINT `ospos_receivings_ibfk_1` FOREIGN KEY (`employee_id`) REFERENCES `ospos_employees` (`person_id`),
+ ADD CONSTRAINT `ospos_receivings_ibfk_2` FOREIGN KEY (`supplier_id`) REFERENCES `ospos_suppliers` (`person_id`);
+
+--
+-- Constraints for table `ospos_receivings_items`
+--
+ALTER TABLE `ospos_receivings_items`
+ ADD CONSTRAINT `ospos_receivings_items_ibfk_1` FOREIGN KEY (`item_id`) REFERENCES `ospos_items` (`item_id`),
+ ADD CONSTRAINT `ospos_receivings_items_ibfk_2` FOREIGN KEY (`receiving_id`) REFERENCES `ospos_receivings` (`receiving_id`);
+
+--
+-- Constraints for table `ospos_sales`
+--
+ALTER TABLE `ospos_sales`
+ ADD CONSTRAINT `ospos_sales_ibfk_1` FOREIGN KEY (`employee_id`) REFERENCES `ospos_employees` (`person_id`),
+ ADD CONSTRAINT `ospos_sales_ibfk_2` FOREIGN KEY (`customer_id`) REFERENCES `ospos_customers` (`person_id`);
+
+--
+-- Constraints for table `ospos_sales_items`
+--
+ALTER TABLE `ospos_sales_items`
+ ADD CONSTRAINT `ospos_sales_items_ibfk_1` FOREIGN KEY (`item_id`) REFERENCES `ospos_items` (`item_id`),
+ ADD CONSTRAINT `ospos_sales_items_ibfk_2` FOREIGN KEY (`sale_id`) REFERENCES `ospos_sales` (`sale_id`),
+ ADD CONSTRAINT `ospos_sales_items_ibfk_3` FOREIGN KEY (`item_location`) REFERENCES `ospos_stock_locations` (`location_id`);
+
+--
+-- Constraints for table `ospos_sales_items_taxes`
+--
+ALTER TABLE `ospos_sales_items_taxes`
+ ADD CONSTRAINT `ospos_sales_items_taxes_ibfk_1` FOREIGN KEY (`sale_id`,`item_id`,`line`) REFERENCES `ospos_sales_items` (`sale_id`,`item_id`,`line`),
+ ADD CONSTRAINT `ospos_sales_items_taxes_ibfk_2` FOREIGN KEY (`item_id`) REFERENCES `ospos_items` (`item_id`);
+
+--
+-- Constraints for table `ospos_sales_payments`
+--
+ALTER TABLE `ospos_sales_payments`
+ ADD CONSTRAINT `ospos_sales_payments_ibfk_1` FOREIGN KEY (`sale_id`) REFERENCES `ospos_sales` (`sale_id`);
+
+--
+-- Constraints for table `ospos_sales_suspended`
+--
+ALTER TABLE `ospos_sales_suspended`
+ ADD CONSTRAINT `ospos_sales_suspended_ibfk_1` FOREIGN KEY (`employee_id`) REFERENCES `ospos_employees` (`person_id`),
+ ADD CONSTRAINT `ospos_sales_suspended_ibfk_2` FOREIGN KEY (`customer_id`) REFERENCES `ospos_customers` (`person_id`);
+
+--
+-- Constraints for table `ospos_sales_suspended_items`
+--
+ALTER TABLE `ospos_sales_suspended_items`
+ ADD CONSTRAINT `ospos_sales_suspended_items_ibfk_1` FOREIGN KEY (`item_id`) REFERENCES `ospos_items` (`item_id`),
+ ADD CONSTRAINT `ospos_sales_suspended_items_ibfk_2` FOREIGN KEY (`sale_id`) REFERENCES `ospos_sales_suspended` (`sale_id`),
+ ADD CONSTRAINT `ospos_sales_suspended_items_ibfk_3` FOREIGN KEY (`item_location`) REFERENCES `ospos_stock_locations` (`location_id`);
+
+--
+-- Constraints for table `ospos_sales_suspended_items_taxes`
+--
+ALTER TABLE `ospos_sales_suspended_items_taxes`
+ ADD CONSTRAINT `ospos_sales_suspended_items_taxes_ibfk_1` FOREIGN KEY (`sale_id`,`item_id`,`line`) REFERENCES `ospos_sales_suspended_items` (`sale_id`,`item_id`,`line`),
+ ADD CONSTRAINT `ospos_sales_suspended_items_taxes_ibfk_2` FOREIGN KEY (`item_id`) REFERENCES `ospos_items` (`item_id`);
+
+--
+-- Constraints for table `ospos_sales_suspended_payments`
+--
+ALTER TABLE `ospos_sales_suspended_payments`
+ ADD CONSTRAINT `ospos_sales_suspended_payments_ibfk_1` FOREIGN KEY (`sale_id`) REFERENCES `ospos_sales_suspended` (`sale_id`);
+
+--
+-- Constraints for table `ospos_item_quantities`
+--
+ALTER TABLE `ospos_item_quantities`
+ ADD CONSTRAINT `ospos_item_quantities_ibfk_1` FOREIGN KEY (`item_id`) REFERENCES `ospos_items` (`item_id`),
+ ADD CONSTRAINT `ospos_item_quantities_ibfk_2` FOREIGN KEY (`location_id`) REFERENCES `ospos_stock_locations` (`location_id`);
+
+--
+-- Constraints for table `ospos_suppliers`
+--
+ALTER TABLE `ospos_suppliers`
+ ADD CONSTRAINT `ospos_suppliers_ibfk_1` FOREIGN KEY (`person_id`) REFERENCES `ospos_people` (`person_id`);
+
+--
+-- Constraints for table `ospos_giftcards`
+--
+ALTER TABLE `ospos_giftcards`
+ ADD CONSTRAINT `ospos_giftcards_ibfk_1` FOREIGN KEY (`person_id`) REFERENCES `ospos_people` (`person_id`);
diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml
index 47f7ef996..56d3bb78e 100644
--- a/docker-compose.dev.yml
+++ b/docker-compose.dev.yml
@@ -20,7 +20,6 @@ services:
networks:
- app_net
volumes:
- - ./app/Database/database.sql:/docker-entrypoint-initdb.d/database.sql
- mysql:/var/lib/mysql:rw
environment:
- MYSQL_ROOT_PASSWORD=pointofsale
diff --git a/docker-compose.test.yml b/docker-compose.test.yml
deleted file mode 100644
index 4ff0e18fe..000000000
--- a/docker-compose.test.yml
+++ /dev/null
@@ -1,21 +0,0 @@
-include:
- - docker/docker-mysql.yml
-
-services:
- test:
- build:
- context: .
- target: ospos_test
- depends_on:
- - mysql
- container_name: ospos_test
- environment:
- - CI_ENVIRONMENT=testing
- - ENCRYPTION_KEY=
- - MYSQL_HOST_NAME=mysql
- - MYSQL_DATABASE=ospos
- - MYSQL_USERNAME=admin
- - MYSQL_PASSWORD=pointofsale
- command: [ "/bin/wait-for-it.sh", "mysql:3306", "--", "/app/vendor/bin/phpunit", "/app/tests" ]
- ports:
- - "80:80"
diff --git a/docker-compose.yml b/docker-compose.yml
index 2622a5906..e1ebc9791 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -2,9 +2,6 @@ include:
- docker/docker-mysql.yml
services:
- sqlscript:
- image: jekkos/opensourcepos:sql-master
- command: /bin/sh -c 'exit 0'
ospos:
image: jekkos/opensourcepos:master
restart: always
diff --git a/docker/docker-mysql.yml b/docker/docker-mysql.yml
index d3e9cf347..69171c645 100644
--- a/docker/docker-mysql.yml
+++ b/docker/docker-mysql.yml
@@ -19,8 +19,6 @@ services:
- "3306"
networks:
- app_net
- volumes_from:
- - sqlscript
volumes:
- mysql:/var/lib/mysql:rw
environment:
diff --git a/gulpfile.js b/gulpfile.js
index e234778dc..909cec7d5 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -259,35 +259,10 @@ gulp.task('copy-fonts', function() {
gulp.task('copy-menubar', function() {
- pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/star.svg"),rename("attributes.svg"),gulp.dest("public/images/menubar"));
- pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/bookshelf.svg"),rename("cashups.svg"),gulp.dest("public/images/menubar"));
- pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/gear.svg"),rename("config.svg"),gulp.dest("public/images/menubar"));
- pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/contacts.svg"),rename("customers.svg"),gulp.dest("public/images/menubar"));
- pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/profle.svg"),rename("employees.svg"),gulp.dest("public/images/menubar"));
- pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/compose.svg"),rename("expenses.svg"),gulp.dest("public/images/menubar"));
- pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/clipboard.svg"),rename("expenses_categories.svg"),gulp.dest("public/images/menubar"));
- pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/heart.svg"),rename("giftcards.svg"),gulp.dest("public/images/menubar"));
- pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/door.svg"),rename("home.svg"),gulp.dest("public/images/menubar"));
- pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/stack.svg"),rename("item_kits.svg"),gulp.dest("public/images/menubar"));
- pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/shop.svg"),rename("items.svg"),gulp.dest("public/images/menubar"));
- pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/smartphone.svg"),rename("messages.svg"),gulp.dest("public/images/menubar"));
- pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/tools.svg"),rename("migrate.svg"),gulp.dest("public/images/menubar"));
- pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/door.svg"),rename("office.svg"),gulp.dest("public/images/menubar"));
- pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/dolly.svg"),rename("receivings.svg"),gulp.dest("public/images/menubar"));
- pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/bar-chart.svg"),rename("reports.svg"),gulp.dest("public/images/menubar"));
- pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/cart.svg"),rename("sales.svg"),gulp.dest("public/images/menubar"));
- pipeline(gulp.src("./node_modules/elegant-circles/svg/full-color/briefcase.svg"),rename("suppliers.svg"),gulp.dest("public/images/menubar"));
return pipeline(gulp.src('./node_modules/elegant-circles/svg/full-color/money.svg'),rename("taxes.svg"),gulp.dest("public/images/menubar"));
});
-gulp.task('build-database', function() {
- return gulp.src(['./app/Database/tables.sql','./app/Database/constraints.sql'])
- .pipe(header('-- >> This file is autogenerated from tables.sql and constraints.sql. Do not modify directly << --'))
- .pipe(concat('database.sql'))
- .pipe(gulp.dest('./app/Database'));
-});
-
// Run all required tasks
gulp.task('default',
gulp.series('clean',
@@ -299,6 +274,5 @@ gulp.task('default',
'debug-css',
'prod-css',
'copy-fonts',
- 'copy-menubar',
- 'build-database'
+ 'copy-menubar'
));
diff --git a/tests/Libraries/Token_libTest.php b/tests/Libraries/Token_libTest.php
index fac3d92f0..96cd80a41 100644
--- a/tests/Libraries/Token_libTest.php
+++ b/tests/Libraries/Token_libTest.php
@@ -41,7 +41,7 @@ class Token_libTest extends CIUnitTestCase
{
$input = '%Y-%q-%bad';
$result = $this->tokenLib->render($input, [], false);
- $this->assertMatchesRegularExpression('/\d{4}-%q-%bad/', $result);
+ $this->assertMatchesRegularExpression('/\d{4}-%q-[A-Za-z]{3}ad/', $result);
}
public function testRenderHandlesStringWithPercentAPercent(): void