├── .gitignore ├── deployment ├── 00-ns.yaml ├── db-service.yaml ├── odoo-service.yaml ├── iotbox-service.yaml ├── odoo-ingress.yaml ├── iotbox-ingress.yaml ├── odoo-pvc.yaml ├── db-statefulset.yaml ├── iotbox-deployment.yaml └── odoo-deployment.yaml ├── odoo ├── odoo.conf ├── addons │ └── pos_product_sequence │ │ ├── static │ │ ├── description │ │ │ ├── icon.png │ │ │ ├── logo.png │ │ │ └── index.html │ │ └── src │ │ │ └── js │ │ │ └── models.js │ │ ├── __init__.py │ │ ├── models │ │ └── __init__.py │ │ ├── COPYRIGHT │ │ ├── __manifest__.py │ │ └── LICENSE └── Dockerfile ├── contrib ├── posmon │ ├── 00-posmon-ns.yaml │ ├── servicemonitor.yaml │ ├── alertmanager.yaml │ ├── alertrules.yaml │ ├── grafana.yaml │ ├── blackbox-exporter.yaml │ ├── prometheus-rbac.yaml │ ├── healthchecks-cronjob.yaml │ ├── alertmanager-gotify.yaml │ └── prometheus.yaml ├── alertmanager.yaml ├── backup │ └── k8up-schedule.yaml └── pos-blackbox-exporter-scrape.yaml ├── docs ├── iotbox-config.png ├── orderprinter.png ├── configuration-bar-1.png ├── configuration-bar-2.png ├── configuration-festbeiz-1.png └── configuration-festbeiz-2.png ├── iotbox ├── odoo.conf ├── patches │ ├── utf8-to-printer.patch │ ├── disable-bluetooth-driver.patch │ ├── start-cups.patch │ ├── disable-disconnected-logging.patch │ ├── remove_get_printer_status.patch │ ├── python-v4l2-1664158-fix.patch │ └── cashbox-net.patch └── Dockerfile ├── docker-compose.yml ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | backup.env 2 | checkup.json 3 | addons/ 4 | addons_old/ 5 | -------------------------------------------------------------------------------- /deployment/00-ns.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: pos 5 | -------------------------------------------------------------------------------- /odoo/odoo.conf: -------------------------------------------------------------------------------- 1 | [options] 2 | data_dir = /var/lib/odoo 3 | admin_passwd = S3Cur3Passw0rd 4 | -------------------------------------------------------------------------------- /contrib/posmon/00-posmon-ns.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: posmon 5 | -------------------------------------------------------------------------------- /docs/iotbox-config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobru/odoo-pos-distribution/HEAD/docs/iotbox-config.png -------------------------------------------------------------------------------- /docs/orderprinter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobru/odoo-pos-distribution/HEAD/docs/orderprinter.png -------------------------------------------------------------------------------- /docs/configuration-bar-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobru/odoo-pos-distribution/HEAD/docs/configuration-bar-1.png -------------------------------------------------------------------------------- /docs/configuration-bar-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobru/odoo-pos-distribution/HEAD/docs/configuration-bar-2.png -------------------------------------------------------------------------------- /docs/configuration-festbeiz-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobru/odoo-pos-distribution/HEAD/docs/configuration-festbeiz-1.png -------------------------------------------------------------------------------- /docs/configuration-festbeiz-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobru/odoo-pos-distribution/HEAD/docs/configuration-festbeiz-2.png -------------------------------------------------------------------------------- /iotbox/odoo.conf: -------------------------------------------------------------------------------- 1 | [options] 2 | addons_path = /mnt/extra-addons,/opt/posbox/addons,/opt/posbox/cloud-addons 3 | data_dir = /var/lib/odoo 4 | admin_passwd = S3Cur3Passw0rd 5 | -------------------------------------------------------------------------------- /odoo/addons/pos_product_sequence/static/description/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobru/odoo-pos-distribution/HEAD/odoo/addons/pos_product_sequence/static/description/icon.png -------------------------------------------------------------------------------- /odoo/addons/pos_product_sequence/static/description/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tobru/odoo-pos-distribution/HEAD/odoo/addons/pos_product_sequence/static/description/logo.png -------------------------------------------------------------------------------- /odoo/addons/pos_product_sequence/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Powered by Kanak Infosystems LLP. 3 | # © 2020 Kanak Infosystems LLP. () 4 | 5 | from . import models 6 | -------------------------------------------------------------------------------- /odoo/addons/pos_product_sequence/models/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Powered by Kanak Infosystems LLP. 3 | # © 2020 Kanak Infosystems LLP. () 4 | 5 | from . import knk_product 6 | -------------------------------------------------------------------------------- /deployment/db-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app: db 6 | name: db 7 | namespace: pos 8 | spec: 9 | ports: 10 | - name: postgres 11 | port: 5432 12 | targetPort: 5432 13 | selector: 14 | app: db 15 | -------------------------------------------------------------------------------- /deployment/odoo-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app: odoo 6 | name: odoo 7 | namespace: pos 8 | spec: 9 | ports: 10 | - name: http 11 | port: 80 12 | targetPort: 8069 13 | selector: 14 | app: odoo 15 | -------------------------------------------------------------------------------- /deployment/iotbox-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app: iotbox 6 | name: iotbox 7 | namespace: pos 8 | spec: 9 | ports: 10 | - name: http 11 | port: 80 12 | targetPort: 8069 13 | selector: 14 | app: iotbox 15 | -------------------------------------------------------------------------------- /contrib/alertmanager.yaml: -------------------------------------------------------------------------------- 1 | global: 2 | resolve_timeout: 5m 3 | route: 4 | group_by: ['job'] 5 | group_wait: 30s 6 | group_interval: 5m 7 | repeat_interval: 12h 8 | receiver: 'webhook' 9 | receivers: 10 | - name: 'webhook' 11 | webhook_configs: 12 | - url: 'http://alertmanagerwh:30500/' 13 | -------------------------------------------------------------------------------- /contrib/posmon/servicemonitor.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: monitoring.coreos.com/v1 2 | kind: ServiceMonitor 3 | metadata: 4 | name: blackboxmon 5 | namespace: posmon 6 | labels: 7 | app: pos 8 | spec: 9 | selector: 10 | matchLabels: 11 | app: blackbox-exporter 12 | endpoints: 13 | - port: http 14 | -------------------------------------------------------------------------------- /contrib/backup/k8up-schedule.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: backup.appuio.ch/v1alpha1 2 | kind: Schedule 3 | metadata: 4 | name: pos-backup 5 | namespace: pos 6 | spec: 7 | backup: 8 | schedule: '*/15 * * * *' 9 | keepJobs: 4 10 | prune: 11 | schedule: '0 * * * *' 12 | retention: 13 | keepLast: 10 14 | 15 | 16 | -------------------------------------------------------------------------------- /iotbox/patches/utf8-to-printer.patch: -------------------------------------------------------------------------------- 1 | --- printer.py.orig 2019-06-30 14:11:38.387716789 +0200 2 | +++ printer.py 2019-06-30 14:12:37.508289596 +0200 3 | @@ -211,6 +211,8 @@ 4 | 5 | 6 | def _raw(self, msg): 7 | + if type(msg) is str: 8 | + msg = msg.encode("utf-8") 9 | self.device.send(msg) 10 | 11 | 12 | -------------------------------------------------------------------------------- /iotbox/patches/disable-bluetooth-driver.patch: -------------------------------------------------------------------------------- 1 | --- driver.py.orig 2019-06-27 22:11:55.411759929 +0200 2 | +++ driver.py 2019-06-27 22:12:02.794867070 +0200 3 | @@ -396,6 +396,6 @@ 4 | m.daemon = True 5 | m.start() 6 | 7 | -bm = BtManager() 8 | -bm.daemon = True 9 | -bm.start() 10 | +#bm = BtManager() 11 | +#bm.daemon = True 12 | +#bm.start() 13 | -------------------------------------------------------------------------------- /deployment/odoo-ingress.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1beta1 2 | kind: Ingress 3 | metadata: 4 | labels: 5 | app: odoo 6 | name: odoo 7 | namespace: pos 8 | spec: 9 | rules: 10 | - host: pos 11 | http: 12 | paths: 13 | - path: / 14 | backend: 15 | serviceName: odoo 16 | servicePort: 80 17 | -------------------------------------------------------------------------------- /deployment/iotbox-ingress.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.k8s.io/v1beta1 2 | kind: Ingress 3 | metadata: 4 | labels: 5 | app: iotbox 6 | name: iotbox 7 | namespace: pos 8 | spec: 9 | rules: 10 | - host: iotbox 11 | http: 12 | paths: 13 | - path: / 14 | backend: 15 | serviceName: iotbox 16 | servicePort: 80 17 | -------------------------------------------------------------------------------- /iotbox/patches/start-cups.patch: -------------------------------------------------------------------------------- 1 | --- entrypoint.sh.orig 2019-06-27 22:17:01.881714065 +0200 2 | +++ entrypoint.sh 2019-06-27 22:16:08.094244835 +0200 3 | @@ -26,6 +26,7 @@ 4 | case "$1" in 5 | -- | odoo) 6 | shift 7 | + /etc/init.d/cups start 8 | if [[ "$1" == "scaffold" ]] ; then 9 | exec odoo "$@" 10 | else 11 | -------------------------------------------------------------------------------- /deployment/odoo-pvc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolumeClaim 3 | metadata: 4 | labels: 5 | app: odoo 6 | name: odoo-data 7 | namespace: pos 8 | annotations: 9 | appuio.ch/backup: "true" 10 | spec: 11 | accessModes: 12 | - ReadWriteOnce 13 | resources: 14 | requests: 15 | storage: 500Mi 16 | storageClassName: local-path 17 | -------------------------------------------------------------------------------- /iotbox/patches/disable-disconnected-logging.patch: -------------------------------------------------------------------------------- 1 | --- main.py.orig 2019-07-23 21:09:59.278876123 +0200 2 | +++ main.py 2019-07-23 21:19:12.726843102 +0200 3 | @@ -112,7 +112,6 @@ 4 | ) 5 | return print_dev 6 | else: 7 | - self.set_status('disconnected','Printer Not Found') 8 | return None 9 | 10 | def get_status(self): 11 | -------------------------------------------------------------------------------- /iotbox/patches/remove_get_printer_status.patch: -------------------------------------------------------------------------------- 1 | --- escpos.py.orig 2019-08-27 10:48:53.402884574 +0200 2 | +++ escpos.py 2019-08-27 10:49:01.762946864 +0200 3 | @@ -908,8 +908,6 @@ 4 | else: 5 | raise CashDrawerError() 6 | 7 | - self.get_printer_status() 8 | - 9 | def hw(self, hw): 10 | """ Hardware operations """ 11 | if hw.upper() == "INIT": 12 | -------------------------------------------------------------------------------- /contrib/posmon/alertmanager.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: monitoring.coreos.com/v1 2 | kind: Alertmanager 3 | metadata: 4 | name: posmon 5 | namespace: posmon 6 | spec: 7 | replicas: 1 8 | --- 9 | apiVersion: v1 10 | kind: Service 11 | metadata: 12 | name: alertmanager-posmon 13 | namespace: posmon 14 | spec: 15 | type: NodePort 16 | ports: 17 | - name: web 18 | nodePort: 30903 19 | port: 9093 20 | protocol: TCP 21 | targetPort: web 22 | selector: 23 | alertmanager: posmon 24 | -------------------------------------------------------------------------------- /contrib/posmon/alertrules.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: monitoring.coreos.com/v1 2 | kind: PrometheusRule 3 | metadata: 4 | labels: 5 | prometheus: posmon 6 | role: alert-rules 7 | name: posmon-rules 8 | namespace: posmon 9 | spec: 10 | groups: 11 | - name: ./posmon.rules 12 | rules: 13 | - alert: TargetDown 14 | expr: probe_success < 1 15 | labels: 16 | severity: critical 17 | annotations: 18 | description: The target {{$labels.instance}} is down 19 | title: Target Down 20 | -------------------------------------------------------------------------------- /odoo/addons/pos_product_sequence/COPYRIGHT: -------------------------------------------------------------------------------- 1 | 2 | Most of the files are 3 | 4 | Copyright (c) 2012-TODAY Kanak Infosystems LLP 5 | 6 | Many files also contain contributions from third 7 | parties. In this case the original copyright of 8 | the contributions can be traced through the 9 | history of the source version control system. 10 | 11 | When that is not the case, the files contain a prominent 12 | notice stating the original copyright and applicable 13 | license, or come with their own dedicated COPYRIGHT 14 | and/or LICENSE file. 15 | 16 | -------------------------------------------------------------------------------- /iotbox/patches/python-v4l2-1664158-fix.patch: -------------------------------------------------------------------------------- 1 | === modified file 'v4l2.py' 2 | --- v4l2.py 2010-07-22 01:07:58 +0000 3 | +++ v4l2.py 2018-03-03 01:59:16 +0000 4 | @@ -194,7 +194,7 @@ 5 | V4L2_BUF_TYPE_SLICED_VBI_OUTPUT, 6 | V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY, 7 | V4L2_BUF_TYPE_PRIVATE, 8 | -) = range(1, 9) + [0x80] 9 | +) = list(range(1, 9)) + [0x80] 10 | 11 | 12 | v4l2_ctrl_type = enum 13 | @@ -245,7 +245,7 @@ 14 | V4L2_PRIORITY_INTERACTIVE, 15 | V4L2_PRIORITY_RECORD, 16 | V4L2_PRIORITY_DEFAULT, 17 | -) = range(0, 4) + [2] 18 | +) = list(range(0, 4)) + [2] 19 | 20 | 21 | class v4l2_rect(ctypes.Structure): 22 | 23 | -------------------------------------------------------------------------------- /odoo/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM odoo:15 2 | 3 | USER root 4 | 5 | ## Get pos-addons for pos_printer_network 6 | #RUN set -x; apt-get update \ 7 | # && apt-get -y install --no-install-recommends git \ 8 | # && rm -rf /var/lib/apt/lists/* \ 9 | # && git clone --depth=1 -b 13.0 https://github.com/it-projects-llc/pos-addons.git \ 10 | # /opt/posbox/pos-addons \ 11 | # && git clone --depth=1 -b 13.0 https://github.com/camptocamp/odoo-cloud-platform.git \ 12 | # /opt/posbox/cloud-addons \ 13 | # && git clone --depth=1 -b 13.0 https://github.com/CybroOdoo/CybroAddons.git \ 14 | # /opt/posbox/cybro-addons 15 | 16 | COPY odoo.conf /etc/odoo/odoo.conf 17 | #COPY addons/ /opt/posbox/extra-addons 18 | 19 | #RUN chown -R odoo.odoo /opt/posbox 20 | 21 | USER odoo 22 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | web: 4 | #image: docker.io/tobru/odoo-pos:latest-pos 5 | image: docker.io/library/odoo:15 6 | #build: ./odoo 7 | depends_on: 8 | - db 9 | ports: 10 | - 80:8069 11 | volumes: 12 | - odoo-web-data:/var/lib/odoo 13 | - ./odoo/addons:/mnt/extra-addons 14 | environment: 15 | - HOST=db 16 | - USER=odoo 17 | - PASSWORD=odoo 18 | db: 19 | image: postgres:14 20 | environment: 21 | - POSTGRES_DB=postgres 22 | - POSTGRES_PASSWORD=odoo 23 | - POSTGRES_USER=odoo 24 | - PGDATA=/var/lib/postgresql/data/pgdata 25 | volumes: 26 | - odoo-db-data:/var/lib/postgresql/data/pgdata 27 | volumes: 28 | odoo-web-data: 29 | odoo-db-data: 30 | -------------------------------------------------------------------------------- /contrib/posmon/grafana.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | labels: 5 | app: grafana 6 | name: grafana 7 | namespace: posmon 8 | spec: 9 | replicas: 1 10 | selector: 11 | matchLabels: 12 | app: grafana 13 | template: 14 | metadata: 15 | labels: 16 | app: grafana 17 | spec: 18 | containers: 19 | - image: grafana/grafana:6.3.0-beta4 20 | name: grafana 21 | ports: 22 | - containerPort: 3000 23 | name: web 24 | --- 25 | apiVersion: v1 26 | kind: Service 27 | metadata: 28 | name: grafana-nodeport 29 | namespace: posmon 30 | spec: 31 | ports: 32 | - name: web 33 | nodePort: 30904 34 | port: 3000 35 | protocol: TCP 36 | targetPort: web 37 | selector: 38 | app: grafana 39 | type: NodePort 40 | -------------------------------------------------------------------------------- /contrib/posmon/blackbox-exporter.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: blackbox-exporter 5 | namespace: posmon 6 | spec: 7 | replicas: 1 8 | selector: 9 | matchLabels: 10 | app: blackbox-exporter 11 | template: 12 | metadata: 13 | labels: 14 | app: blackbox-exporter 15 | spec: 16 | containers: 17 | - image: prom/blackbox-exporter:master 18 | name: blackbox-exporter 19 | ports: 20 | - containerPort: 9115 21 | --- 22 | apiVersion: v1 23 | kind: Service 24 | metadata: 25 | name: blackbox-exporter 26 | namespace: posmon 27 | labels: 28 | app: blackbox-exporter 29 | spec: 30 | ports: 31 | - name: http 32 | port: 9115 33 | protocol: TCP 34 | targetPort: 9115 35 | selector: 36 | app: blackbox-exporter 37 | type: ClusterIP 38 | -------------------------------------------------------------------------------- /contrib/posmon/prometheus-rbac.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1beta1 2 | kind: ClusterRole 3 | metadata: 4 | name: prometheus 5 | rules: 6 | - apiGroups: [""] 7 | resources: 8 | - nodes 9 | - services 10 | - endpoints 11 | - pods 12 | verbs: ["get", "list", "watch"] 13 | - apiGroups: [""] 14 | resources: 15 | - configmaps 16 | verbs: ["get"] 17 | - nonResourceURLs: ["/metrics"] 18 | verbs: ["get"] 19 | --- 20 | apiVersion: v1 21 | kind: ServiceAccount 22 | metadata: 23 | name: prometheus 24 | namespace: posmon 25 | --- 26 | apiVersion: rbac.authorization.k8s.io/v1beta1 27 | kind: ClusterRoleBinding 28 | metadata: 29 | name: prometheus 30 | roleRef: 31 | apiGroup: rbac.authorization.k8s.io 32 | kind: ClusterRole 33 | name: prometheus 34 | subjects: 35 | - kind: ServiceAccount 36 | name: prometheus 37 | namespace: posmon 38 | -------------------------------------------------------------------------------- /contrib/posmon/healthchecks-cronjob.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1beta1 2 | kind: CronJob 3 | metadata: 4 | name: healthchecks-io 5 | namespace: posmon 6 | spec: 7 | schedule: "*/1 * * * *" 8 | concurrencyPolicy: Forbid 9 | successfulJobsHistoryLimit: 1 10 | failedJobsHistoryLimit: 1 11 | startingDeadlineSeconds: 200 12 | jobTemplate: 13 | spec: 14 | template: 15 | spec: 16 | containers: 17 | - name: pinghc 18 | env: 19 | - name: HCURL 20 | valueFrom: 21 | secretKeyRef: 22 | name: healthchecks-io 23 | key: HCURL 24 | image: busybox 25 | args: 26 | - /bin/sh 27 | - -c 28 | - "date && echo $HCURL && /bin/wget -q -O - --no-check-certificate $HCURL" 29 | restartPolicy: OnFailure 30 | 31 | -------------------------------------------------------------------------------- /contrib/posmon/alertmanager-gotify.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | labels: 5 | app: alertmanager-gotify 6 | name: alertmanager-gotify 7 | namespace: posmon 8 | spec: 9 | replicas: 1 10 | selector: 11 | matchLabels: 12 | app: alertmanager-gotify 13 | template: 14 | metadata: 15 | labels: 16 | app: alertmanager-gotify 17 | spec: 18 | containers: 19 | - image: r.sbruder.de/alertmanager-gotify:latest 20 | name: alertmanager-gotify 21 | env: 22 | - name: GOTIFY_URL 23 | value: https://gotify.tbrnt.ch 24 | ports: 25 | - containerPort: 8081 26 | name: web 27 | --- 28 | apiVersion: v1 29 | kind: Service 30 | metadata: 31 | name: alertmanager-gotify 32 | namespace: posmon 33 | spec: 34 | ports: 35 | - name: web 36 | port: 8081 37 | protocol: TCP 38 | targetPort: web 39 | selector: 40 | app: alertmanager-gotify 41 | type: ClusterIP 42 | -------------------------------------------------------------------------------- /contrib/posmon/prometheus.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: monitoring.coreos.com/v1 2 | kind: Prometheus 3 | metadata: 4 | name: posmon 5 | namespace: posmon 6 | spec: 7 | serviceAccountName: prometheus 8 | serviceMonitorSelector: 9 | matchLabels: 10 | app: pos 11 | resources: 12 | requests: 13 | memory: 400Mi 14 | enableAdminAPI: false 15 | additionalScrapeConfigs: 16 | name: additional-scrape-configs 17 | key: pos-blackbox-exporter-scrape.yaml 18 | alerting: 19 | alertmanagers: 20 | - namespace: posmon 21 | name: alertmanager-posmon 22 | port: web 23 | ruleSelector: 24 | matchLabels: 25 | role: alert-rules 26 | prometheus: posmon 27 | --- 28 | apiVersion: v1 29 | kind: Service 30 | metadata: 31 | name: prometheus-posmon 32 | namespace: posmon 33 | spec: 34 | type: NodePort 35 | ports: 36 | - name: web 37 | nodePort: 30909 38 | port: 9090 39 | protocol: TCP 40 | targetPort: web 41 | selector: 42 | prometheus: posmon 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Tobias Brunner 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /odoo/addons/pos_product_sequence/__manifest__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Powered by Kanak Infosystems LLP. 3 | # © 2020 Kanak Infosystems LLP. () 4 | 5 | { 6 | 'name': 'POS Product Sequence', 7 | 'version': '15.0.1.0', 8 | 'summary': 'POS Product Sequence module is used in Odoo POS to display the products position in POS Session according to the sequence or numbers assigned. If you have 5 products in backend and you want to set its sequence from 1 to 5, then same sequence wise product show in POS Session in odoo.', 9 | 'description': """ 10 | Point of Sale Product Sequence 11 | """, 12 | 'license': 'OPL-1', 13 | 'author': 'Kanak Infosystems LLP.', 14 | 'website': 'https://www.kanakinfosystems.com', 15 | 'images': ['static/description/banner.jpeg'], 16 | 'category': 'Sales/Point of Sale', 17 | 'depends': ['point_of_sale'], 18 | 'data': [ 19 | 'views/knk_pos_product_sequence_views.xml', 20 | ], 21 | 'assets': { 22 | 'point_of_sale.assets': [ 23 | 'pos_product_sequence/static/src/js/models.js', 24 | ], 25 | }, 26 | 'sequence': 1, 27 | 'installable': True, 28 | 'application': False, 29 | 'auto_install': False, 30 | 'price': 10, 31 | 'currency': 'EUR', 32 | 'live_test_url': 'https://youtu.be/pYVNy3A3ieE', 33 | } 34 | -------------------------------------------------------------------------------- /deployment/db-statefulset.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: StatefulSet 3 | metadata: 4 | labels: 5 | app: db 6 | name: db 7 | namespace: pos 8 | spec: 9 | selector: 10 | matchLabels: 11 | app: db 12 | serviceName: db 13 | replicas: 1 14 | template: 15 | metadata: 16 | annotations: 17 | appuio.ch/backupcommand: pg_dumpall 18 | labels: 19 | app: db 20 | spec: 21 | terminationGracePeriodSeconds: 10 22 | containers: 23 | - name: db 24 | image: postgres:10 25 | env: 26 | - name: PGDATA 27 | value: /var/lib/postgresql/data/pgdata 28 | - name: POSTGRES_DB 29 | value: postgres 30 | - name: POSTGRES_PASSWORD 31 | value: odoo 32 | - name: PGPASSWORD 33 | value: odoo 34 | - name: POSTGRES_USER 35 | value: odoo 36 | - name: PGUSER 37 | value: odoo 38 | ports: 39 | - containerPort: 5432 40 | name: postgres 41 | volumeMounts: 42 | - name: db-data 43 | mountPath: /var/lib/postgresql/data/pgdata 44 | volumeClaimTemplates: 45 | - metadata: 46 | name: db-data 47 | annotations: 48 | appuio.ch/backup: "true" 49 | spec: 50 | accessModes: 51 | - ReadWriteOnce 52 | storageClassName: local-path 53 | resources: 54 | requests: 55 | storage: 1Gi 56 | -------------------------------------------------------------------------------- /contrib/pos-blackbox-exporter-scrape.yaml: -------------------------------------------------------------------------------- 1 | - job_name: 'blackbox_http' 2 | metrics_path: /probe 3 | scrape_interval: 1m 4 | params: 5 | module: [http_2xx] 6 | static_configs: 7 | - targets: 8 | - http://odoo.pos.svc.cluster.local 9 | - http://iotbox.pos.svc.cluster.local 10 | - http://192.168.233.1 11 | relabel_configs: 12 | - source_labels: [__address__] 13 | target_label: __param_target 14 | - source_labels: [__param_target] 15 | target_label: instance 16 | - target_label: __address__ 17 | replacement: blackbox-exporter:9115 18 | - job_name: 'blackbox_tcp' 19 | metrics_path: /probe 20 | scrape_interval: 1m 21 | params: 22 | module: [tcp_connect] 23 | static_configs: 24 | - targets: 25 | - db.pos.svc.cluster.local:5432 26 | relabel_configs: 27 | - source_labels: [__address__] 28 | target_label: __param_target 29 | - source_labels: [__param_target] 30 | target_label: instance 31 | - target_label: __address__ 32 | replacement: blackbox-exporter:9115 33 | - job_name: 'blackbox_icmp' 34 | metrics_path: /probe 35 | scrape_interval: 1m 36 | params: 37 | module: [icmp] 38 | static_configs: 39 | - targets: 40 | - 192.168.233.3 41 | - 192.168.233.5 42 | relabel_configs: 43 | - source_labels: [__address__] 44 | target_label: __param_target 45 | - source_labels: [__param_target] 46 | target_label: instance 47 | - target_label: __address__ 48 | replacement: blackbox-exporter:9115 49 | -------------------------------------------------------------------------------- /deployment/iotbox-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | labels: 5 | app: iotbox 6 | name: iotbox 7 | namespace: pos 8 | spec: 9 | replicas: 1 10 | strategy: 11 | type: Recreate 12 | selector: 13 | matchLabels: 14 | app: iotbox 15 | template: 16 | metadata: 17 | labels: 18 | app: iotbox 19 | spec: 20 | containers: 21 | - args: 22 | - -- 23 | - --load=web,hw_proxy,hw_posbox_homepage,hw_posbox_upgrade,hw_scale,hw_scanner,hw_escpos,hw_blackbox_be,hw_screen,hw_drivers,hw_printer_network 24 | env: 25 | - name: HOST 26 | value: db 27 | - name: PASSWORD 28 | value: odoo 29 | - name: USER 30 | value: odoo 31 | image: docker.io/tobru/odoo-pos:latest-iotbox 32 | imagePullPolicy: Always 33 | name: iotbox 34 | ports: 35 | - name: http 36 | containerPort: 8069 37 | livenessProbe: 38 | httpGet: 39 | path: / 40 | port: http 41 | initialDelaySeconds: 300 42 | periodSeconds: 30 43 | timeoutSeconds: 5 44 | successThreshold: 1 45 | failureThreshold: 6 46 | readinessProbe: 47 | httpGet: 48 | path: / 49 | port: http 50 | initialDelaySeconds: 30 51 | periodSeconds: 10 52 | timeoutSeconds: 5 53 | successThreshold: 1 54 | failureThreshold: 6 55 | hostname: iotbox 56 | restartPolicy: Always 57 | -------------------------------------------------------------------------------- /deployment/odoo-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | labels: 5 | app: odoo 6 | name: odoo 7 | namespace: pos 8 | spec: 9 | replicas: 1 10 | strategy: 11 | type: Recreate 12 | selector: 13 | matchLabels: 14 | app: odoo 15 | template: 16 | metadata: 17 | labels: 18 | app: odoo 19 | spec: 20 | containers: 21 | - env: 22 | - name: HOST 23 | value: db 24 | - name: PASSWORD 25 | value: odoo 26 | - name: USER 27 | value: odoo 28 | image: docker.io/tobru/odoo-pos:latest-pos 29 | imagePullPolicy: Always 30 | name: web 31 | ports: 32 | - name: http 33 | containerPort: 8069 34 | livenessProbe: 35 | httpGet: 36 | path: / 37 | port: http 38 | initialDelaySeconds: 300 39 | periodSeconds: 30 40 | timeoutSeconds: 5 41 | successThreshold: 1 42 | failureThreshold: 6 43 | readinessProbe: 44 | httpGet: 45 | path: / 46 | port: http 47 | initialDelaySeconds: 30 48 | periodSeconds: 10 49 | timeoutSeconds: 5 50 | successThreshold: 1 51 | failureThreshold: 6 52 | volumeMounts: 53 | - mountPath: /var/lib/odoo 54 | name: odoo-data 55 | hostname: web 56 | restartPolicy: Always 57 | volumes: 58 | - name: odoo-data 59 | persistentVolumeClaim: 60 | claimName: odoo-data 61 | -------------------------------------------------------------------------------- /odoo/addons/pos_product_sequence/LICENSE: -------------------------------------------------------------------------------- 1 | Odoo Proprietary License v1.0 2 | 3 | This software and associated files (the "Software") may only be used (executed, 4 | modified, executed after modifications) if you have purchased a valid license 5 | from the authors, typically via Odoo Apps, or if you have received a written 6 | agreement from the authors of the Software (see the COPYRIGHT file). 7 | 8 | You may develop Odoo modules that use the Software as a library (typically 9 | by depending on it, importing it and using its resources), but without copying 10 | any source code or material from the Software. You may distribute those 11 | modules under the license of your choice, provided that this license is 12 | compatible with the terms of the Odoo Proprietary License (For example: 13 | LGPL, MIT, or proprietary licenses similar to this one). 14 | 15 | It is forbidden to publish, distribute, sublicense, or sell copies of the Software 16 | or modified copies of the Software. 17 | 18 | The above copyright notice and this permission notice must be included in all 19 | copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 24 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 25 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 26 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 27 | DEALINGS IN THE SOFTWARE. 28 | -------------------------------------------------------------------------------- /iotbox/patches/cashbox-net.patch: -------------------------------------------------------------------------------- 1 | --- hw_printer_network_controller.py.orig 2019-06-30 16:49:26.148283215 +0200 2 | +++ hw_printer_network_controller.py 2019-06-30 16:51:36.655439168 +0200 3 | @@ -129,6 +129,21 @@ 4 | # add a missed order to queue 5 | time.sleep(3) 6 | self.queue.put((timestamp, task, data)) 7 | + elif task == 'cashbox': 8 | + printer_info = self.get_network_printer(data) 9 | + printer = self.printer_objects.get(data, None) 10 | + if printer_info and printer_info['status'] == 'online' and printer: 11 | + _logger.info('Opening cashbox on printer %s...', data) 12 | + try: 13 | + printer.cashdraw(2) 14 | + printer.cashdraw(5) 15 | + except socket.error: 16 | + printer.open() 17 | + printer.cashdraw(2) 18 | + printer.cashdraw(5) 19 | + _logger.info('Done opening cashbox on printer %s', data) 20 | + else: 21 | + _logger.error('cashbox: printer offline!') 22 | elif task == 'printstatus': 23 | pass 24 | elif task == 'status': 25 | @@ -168,10 +183,16 @@ 26 | @http.route('/hw_proxy/print_xml_receipt', type='json', auth='none', cors='*') 27 | def print_xml_receipt(self, receipt, proxy=None): 28 | if proxy: 29 | + _logger.info('print_xml_receipt proxy %s', proxy) 30 | network_driver.push_task('xml_receipt', (receipt, proxy)) 31 | else: 32 | super(UpdatedEscposProxy, self).print_xml_receipt(receipt) 33 | 34 | + @http.route('/hw_proxy/open_cashbox', type='json', auth='none', cors='*') 35 | + def open_cashbox(self, proxy=None): 36 | + _logger.info('Open cashbox via network printer') 37 | + network_driver.push_task('cashbox', '192.168.233.3') 38 | + 39 | @http.route('/hw_proxy/network_printers', type='json', auth='none', cors='*') 40 | def network_printers(self, network_printers=None): 41 | for printer in network_printers: 42 | @@ -180,3 +201,8 @@ 43 | @http.route('/hw_proxy/status_network_printers', type='json', auth='none', cors='*') 44 | def network_printers_status(self): 45 | return network_driver.network_printers 46 | + 47 | + @http.route('/hw_proxy/without_usb', type='http', auth='none', cors='*') 48 | + def without_usb(self): 49 | + """ Old pos_printer_network module expects this to work """ 50 | + return "ping" 51 | -------------------------------------------------------------------------------- /odoo/addons/pos_product_sequence/static/src/js/models.js: -------------------------------------------------------------------------------- 1 | odoo.define('pos_product_sequence.models', function(require) { 2 | "use strict"; 3 | 4 | var models = require('point_of_sale.models'); 5 | var core = require('web.core'); 6 | 7 | var QWeb = core.qweb; 8 | var _t = core._t; 9 | var PosDB = require('point_of_sale.DB'); 10 | const Registries = require('point_of_sale.Registries'); 11 | const ProductsWidget = require('point_of_sale.ProductsWidget'); 12 | 13 | PosDB.include({ 14 | get_product_by_category: function(category_id) { 15 | var product_ids = this.product_by_category_id[category_id]; 16 | var list = []; 17 | if (product_ids) { 18 | for (var i = 0, len = Math.min(product_ids.length, this.limit); i < len; i++) { 19 | list.push(this.product_by_id[product_ids[i]]); 20 | } 21 | } 22 | if (list.length) { 23 | var new_list = _.sortBy(list, function(num) { 24 | return num.pos_sequence; 25 | }); 26 | return new_list; 27 | } 28 | return list; 29 | }, 30 | }); 31 | 32 | models.PosModel.prototype.models.some(function(model) { 33 | if (model.model !== 'product.product') { 34 | return false; 35 | } 36 | // add name and attribute_value_ids to list of fields 37 | // to fetch for product.product 38 | ['pos_sequence'].forEach(function(field) { 39 | if (model.fields.indexOf(field) == -1) { 40 | model.fields.push(field); 41 | } 42 | }); 43 | model['order'] = _.map(['pos_sequence', 'sequence', 'default_code', 'name'], function(name) { return { name: name }; }); 44 | return true; //exit early the iteration of this.models 45 | }); 46 | 47 | const BiProductsTemplateWidget = (ProductsWidget) => 48 | class extends ProductsWidget { 49 | constructor() { 50 | super(...arguments); 51 | } 52 | 53 | get productsToDisplay() { 54 | let list = []; 55 | if (this.searchWord !== '') { 56 | list = this.env.pos.db.search_product_in_category( 57 | this.selectedCategoryId, 58 | this.searchWord 59 | ); 60 | } else { 61 | list = this.env.pos.db.get_product_by_category(this.selectedCategoryId); 62 | } 63 | return list 64 | } 65 | }; 66 | 67 | Registries.Component.extend(ProductsWidget, BiProductsTemplateWidget); 68 | 69 | return ProductsWidget; 70 | }); -------------------------------------------------------------------------------- /iotbox/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM odoo:12 2 | 3 | USER root 4 | 5 | ## Dependencies for iotbox 6 | ## See also https://github.com/odoo/odoo/blob/master/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/init_posbox_image.sh 7 | RUN set -x; apt-get update \ 8 | && apt-get -y install --no-install-recommends \ 9 | bluez \ 10 | cups \ 11 | cups-ipp-utils \ 12 | dbus \ 13 | gcc \ 14 | git \ 15 | libcups2-dev \ 16 | python3-babel \ 17 | python3-dateutil \ 18 | python3-dbus \ 19 | python3-decorator \ 20 | python3-dev \ 21 | python3-docutils \ 22 | python3-feedparser \ 23 | python3-gi \ 24 | python3-html2text \ 25 | python3-jinja2 \ 26 | python3-ldap3 \ 27 | python3-libsass \ 28 | python3-lxml \ 29 | python3-mako \ 30 | python3-mock \ 31 | python3-netifaces \ 32 | python3-openid \ 33 | python3-passlib \ 34 | python3-pil \ 35 | python3-pip \ 36 | python3-psutil \ 37 | python3-psycopg2 \ 38 | python3-pydot \ 39 | python3-pyparsing \ 40 | python3-pypdf2 \ 41 | python3-pyscard \ 42 | python3-qrcode \ 43 | python3-reportlab \ 44 | python3-requests \ 45 | python3-serial \ 46 | python3-simplejson \ 47 | python3-simplejson \ 48 | python3-tz \ 49 | python3-unittest2 \ 50 | python3-urllib3 \ 51 | python3-vatnumber \ 52 | python3-werkzeug \ 53 | python3-wheel \ 54 | && rm -rf /var/lib/apt/lists/* \ 55 | && mkdir -p /opt/posbox/addons \ 56 | && chown -R odoo.odoo /opt/posbox \ 57 | && mkdir /usr/lib/python3/dist-packages/odoo/addons/hw_drivers/drivers 58 | 59 | RUN pip3 install \ 60 | evdev \ 61 | gatt \ 62 | phonenumbers \ 63 | polib \ 64 | pycups \ 65 | pyusb==1.0.0b1 \ 66 | v4l2 67 | 68 | # Add odoo.conf which sets addons path 69 | COPY odoo.conf /etc/odoo/odoo.conf 70 | 71 | ## Get pos-addons for pos_printer_network 72 | RUN git clone --depth=1 -b 12.0 https://github.com/it-projects-llc/pos-addons.git \ 73 | /opt/posbox/addons \ 74 | && git clone --depth=1 -b 12.0 https://github.com/camptocamp/odoo-cloud-platform.git \ 75 | /opt/posbox/cloud-addons 76 | 77 | ## Apply some patches 78 | COPY patches/*.patch /tmp/ 79 | # See https://bugs.launchpad.net/python-v4l2/+bug/1664158 80 | RUN patch -p0 /usr/local/lib/python3.5/dist-packages/v4l2.py < /tmp/python-v4l2-1664158-fix.patch \ 81 | # Disable Bluetooth in driver, doesn't work in Docker and isn't needed for the PoS use-case 82 | && patch -p0 /usr/lib/python3/dist-packages/odoo/addons/hw_drivers/controllers/driver.py < /tmp/disable-bluetooth-driver.patch \ 83 | # Start CUPS - IoTBox connects to it and complains if it isn't running 84 | && patch -p0 /entrypoint.sh < /tmp/start-cups.patch \ 85 | # Strings must be UTF-8 for correct printing 86 | && patch -p0 /usr/lib/python3/dist-packages/odoo/addons/hw_escpos/escpos/printer.py < /tmp/utf8-to-printer.patch \ 87 | # Disable log messages about disconnected drivers - unneeded and clutters logfile with useless messages 88 | && patch -p0 /usr/lib/python3/dist-packages/odoo/addons/hw_escpos/controllers/main.py < /tmp/disable-disconnected-logging.patch 89 | # Add cashbox networking support 90 | #&& patch -p0 /opt/posbox/addons/hw_printer_network/controllers/hw_printer_network_controller.py < /tmp/cashbox-net.patch \ 91 | # Remove fix from https://github.com/odoo/odoo/pull/35368 as this breaks network printing 92 | #&& patch -p0 /usr/lib/python3/dist-packages/odoo/addons/hw_escpos/escpos/escpos.py < /tmp/remove_get_printer_status.patch 93 | 94 | ## Cannot switch to Odoo as CUPS must run as root and CUPS must run - otherwise IoTBox complains 95 | #USER odoo 96 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Odoo Point of Sale - PoS - Distribution 2 | 3 | ❗**ARCHIVED** ❗ 4 | 5 | This project was based on Odoo 12. 6 | When I started to work on it again, Odoo 15 was the current version. 7 | The Point of Sale application has _greatly_ improved since Odoo 12: 8 | 9 | * Receipt printing on network printers fully available out-of-the box 10 | * No iotbox needed anymore 11 | * Many quirks and workarounds present in this repo are outdated and not necessary anymore 12 | 13 | I'm now running Odoo in the cloud, no local deployment on a Raspberry Pi needed anymore. 14 | 15 | For this reason, I'm archiving this project and won't update any further. 16 | 17 | --- 18 | 19 | Dockerfiles, Docker Compose and Kubernetes configuration for running an Odoo based PoS 20 | in containers. 21 | 22 | ## Quickstart 23 | 24 | ### Docker Compose 25 | 26 | 1. `docker-compose up` 27 | 28 | Continue with "Odoo PoS configuration" 29 | 30 | ### Kubernetes / K3s 31 | 32 | The provided YAML files have been developed and tested with [k3s](https://k3s.io/) on amd64 and arm64. 33 | Installation will happen in the namespace `pos`. 34 | 35 | 1. Install [k3s](https://k3s.io/), f.e. using [k3sup](https://k3sup.dev/) (any other Kubernetes should work as well) 36 | 1. Install [local-path-provisioner](https://github.com/rancher/local-path-provisioner) 37 | 1. Apply the deployment YAMLs: `kubectl apply -f deployment/` 38 | 39 | Continue with "Odoo PoS configuration" 40 | 41 | ## Odoo PoS configuration 42 | 43 | 1. Connect to Odoo and create a new database 44 | On Kubernetes the Ingress defines the hostnames `pos` and `iotbox` 45 | 1. Install some Odoo Addons: 46 | * "Point of Sale" 47 | * "POS Network Printer" 48 | 1. (Enable "Developer mode" under Odoo settings) 49 | 1. Configure PoS for IoT Box (see screenshots under `docs/`) 50 | 1. Configure Order Printer (see screenshots under `docs/`) 51 | 52 | ## Odoo Addons 53 | 54 | The default addons from Odoo core are not enough for a smooth PoS experience, 55 | therefore a good amount of PoS addons can be used. This distributions adds 56 | the following addon sources: 57 | 58 | * [pos-addons](https://github.com/it-projects-llc/pos-addons): 59 | * `hw_printer_network` && `pos_printer_network`: Support for network receipt printer 60 | * [odoo-cloud-platform](https://github.com/camptocamp/odoo-cloud-platform): 61 | * `monitoring_status`: Status endpoint for Odoo 62 | * [CybroAddons](https://github.com/CybroOdoo/CybroAddons): 63 | * `pos_product_category_filter`: Only show selected product categories on the PoS view 64 | 65 | The following addons are delivered in this repository: 66 | 67 | * `ip_pos_ticket_order_number`: Custom made module to print a big order number both on 68 | the receipt and kitchen order 69 | * `pos_product_sequence`: Commercial module to manually order products (default is 70 | alphabetically). You're not allowed to use this module unless you bought it as 71 | well. See [POS Product Sequence](https://apps.odoo.com/apps/modules/12.0/pos_product_sequence/) 72 | on the Odoo app store. 73 | 74 | ## Hardware and Networking 75 | 76 | ``` 77 | + 78 | +----------------+ | 79 | | Raspberry Pi 4 | WLAN| 80 | | (K3s, Pi-hole) | +-----+ 81 | | DHCP, DNS | 82 | | 192.168.233.9 | 83 | +-------+--------+ 84 | | 85 | | 86 | +---------------+-----------------+ 87 | +---------+ | Router, Switch and Access Point | 88 | |WLAN | (Mikrotik RB2011) | 89 | | | 102.168.233.1 | 90 | | +-----+---------------------+-----+ 91 | + | | 92 | | | 93 | +-----------+ +--------+-------+ +-------+--------+ 94 | | Cash desk | | Printer 1 | | Printer 2 | 95 | | tablet | | (Cash desk) | | (Kitchen) | 96 | | | | 192.168.233.3 | | 192.168.233.5 | 97 | +-----------+ +-------+--------+ +----------------+ 98 | | 99 | | 100 | +-------+--------+ 101 | | Cash drawer | 102 | +----------------+ 103 | ``` 104 | 105 | * Default network - the posnet - assumed: `192.168.233.0/24` 106 | * IPs: 107 | * `192.168.233.1`: Mikrotik: WLAN and Switch 108 | * `192.168.233.3`: Cashdesk receipt printer with cash drawer 109 | * `192.168.233.5`: Kitchen printer 110 | * `192.168.233.9`: Raspberry Pi (pospi) 111 | * `192.168.233.10-50`: DHCP Range 112 | * Printers: [Epson TM-T20II](https://www.epson.ch/products/sd/pos-printer/epson-tm-t20ii) 113 | 114 | The Raspberry Pi 4 provides DNS and DHCP to the network with [Pi-hole](https://pi-hole.net/). 115 | Static DNS entries `pos` and `iotbox` are added to `/etc/hosts` which 116 | then are served by the Pi-hole DNS server. The Pi-hole Lighttpd must 117 | be configured to listen on f.e. port 8080 so it doesn't conflict with 118 | K3s ingress. The Raspberry Pi is connected to the PoS network using an 119 | Ethernet connection and to the internet using WLAN. This optionally allows 120 | to use it as an internet gateway by adding some IPtables rules: 121 | 122 | ``` 123 | iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE 124 | iptables -A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT 125 | iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPT 126 | ``` 127 | 128 | A good thing is to install Wireguard and use it as remote access to the 129 | Raspberry Pi. 130 | 131 | When using an Android tablet, a "kiosk" browsing app is the recommended way to 132 | provide the PoS webapp to the user. F.e. [Fully Single App Kiosk](https://play.google.com/store/apps/details?id=com.fullykiosk.singleapp&hl=en). 133 | For iPad just add the webapp to the home screen using Safari, no additional 134 | app is needed. 135 | 136 | An UPS is also recommended to power the setup so that short power outages don't 137 | interrupt the ordering process. 138 | 139 | ## Monitoring 140 | 141 | There are two kinds of monitoring prepared: The cluster itself and the PoS 142 | application. 143 | 144 | ### Simple Cluster Healthcheck 145 | 146 | Under `contrib/healthchecks-cronjob.yaml` a simple Kubernetes cronjob is 147 | provided which regularly pings [Healthchecks.io](https://healthchecks.io/). 148 | This helps to see if the whole thing is up and running. 149 | 150 | A secret with the ping URL needs to be added before the CronJobs can do it's work: 151 | 152 | ``` 153 | kubectl -n posmon create secret generic healthchecks-io --from-literal=HCURL=https://hc-ping.com/MYUUID 154 | ``` 155 | 156 | ### Application and network monitoring 157 | 158 | Application monitoring is done using Prometheus, Alertmanager and 159 | Blackbox exporter. No application specific exporters are used, so 160 | it's just a base monitoring to answer the question: "Is it up?". 161 | 162 | 1. Install [prometheus-operator](https://github.com/coreos/prometheus-operator) 163 | F.e.: `kubectl apply -f https://raw.githubusercontent.com/coreos/prometheus-operator/master/bundle.yaml` 164 | 2. Apply manifests: `kubectl apply -f contrib/posmon/` 165 | 3. Create secret for extra scrape config: 166 | `kubectl -n posmon create secret generic additional-scrape-configs --from-file=contrib/pos-blackbox-exporter-scrape.yaml` 167 | 4. Create secret for Alertmanager config: 168 | `kubectl -n posmon create secret generic alertmanager-posmon --from-file=contrib/alertmanager.yaml` 169 | 170 | ## Backup 171 | 172 | Backup is done using [K8up](https://k8up.io/). 173 | 174 | 1. Install K8up 175 | 2. Apply manifests under `contrib/backup` 176 | 177 | ### Restore 178 | 179 | Restore from Restic and then do a database import: 180 | 181 | ``` 182 | createdb -T template0 restoretest 183 | pg_restore -d restoretest /data/odoo_data.dump 184 | ``` 185 | 186 | ## Docker Images 187 | 188 | Docker images are automatically built on [Docker Hub](https://cloud.docker.com/repository/docker/tobru/odoo-pos) (for amd64 arch). 189 | 190 | * `docker.io/tobru/odoo-pos:latest-iotbox`: IoT Box 191 | * `docker.io/tobru/odoo-pos:latest-pos`: Odoo 192 | 193 | ## A word on ARM / Raspberry Pi support 194 | 195 | TL;DR: It's not easy to run things out of the box on Raspberry Pi / ARM. 196 | 197 | Images for ARM64 (f.e. Raspberry Pi) are _not_ automatically built as this 198 | is not supported by Docker Hub. They are built manually on a Raspberry Pi 199 | and uploaded to Docker Hub. 200 | 201 | * `docker.io/tobru/odoo-pos:latest-iotbox-arm64v7`: IoT Box 202 | * `docker.io/tobru/odoo-pos:latest-pos-arm64v7`: Odoo 203 | 204 | As the [upstream Odoo](https://hub.docker.com/_/odoo/) doesn't support 205 | `linux/arm/v7` even the base image needs to be built on the Raspberry Pi: 206 | 207 | 1. Clone https://github.com/odoo/docker 208 | 2. Change `wkhtmltox` to install `raspbian.stretch_armhf.deb` 209 | 3. Build with `docker build -t local/odoo:12 .` 210 | 4. Patch local Dockerfiles to use this as base image 211 | 212 | A good amount of upstream stuff doesn't work on Raspberry Pi as no multiarch 213 | images are provided. F.e. the proposed monitoring stack with Prometheus doesn't 214 | work out of the box and K8up doesn't provide arm binaries (yet). 215 | 216 | The Postgres client installed in the Odoo images is version 9.6 (it's based 217 | on Debian Stretch and upstream doesn't provide `armhf` packages). 218 | If you're using a newer Postgres version, the DB management functionality of 219 | Odoo (Backup/Restore) won't work because of version mismatch. 220 | 221 | ## Random notes 222 | 223 | * Connection from PoS tablet to IoT Box is a direct connection, not via Odoo server! 224 | * Support for opening the cashbox via network printer has been patched. The IP is hardcoded 225 | to 192.168.233.3. See [0c6ecfdd](https://github.com/tobru/posbox-docker/commit/0c6ecfdd470dad07b9f9c26ecc0fd413c6d605b1) 226 | and [#730](https://github.com/it-projects-llc/pos-addons/issues/730). 227 | * Odoo 13 will probably change a lot for PoS and will need some additional work. See f.e. 228 | * Commit: [pos: Replace hw_escpos by PrinterDriver](https://github.com/odoo/odoo/commit/03b2f7b77dc6189bb485e0b834dba5f6d3d4da2c#diff-14c0ea7767d884151475e057ad05ec56) 229 | * Addon: [pos_epson_printer](https://github.com/odoo/odoo/tree/master/addons/pos_epson_printer) 230 | 231 | ## TODOs 232 | 233 | There are some things which could be improved: 234 | 235 | ### Distribution 236 | 237 | * [ ] Pre-install `monitoring_status` and use for K8s probes 238 | * [ ] Point Blackbox Monitoring to `/monitoring/status` 239 | * [ ] Tweak monitoring rules 240 | * [ ] Mirror important add-ons to this repository 241 | * [ ] Configure `server_wide_modules` (instead of using command line parameters) 242 | * [ ] Odoo: `base,web,monitoring_status` 243 | * [ ] Automatically install PoS modules 244 | * [ ] Improve arm builds and overall support (Monitoring, Backup) 245 | * [ ] Support for adding third-party commercial Odoo addons 246 | 247 | ### PoS Usage 248 | 249 | * [ ] Configure default payment option (cash) 250 | * [ ] Don't open cash drawer for virtual payment (Twint, SumUp) 251 | * [ ] Possibility to print a kitchen order ticket per position (not summarized) 252 | 253 | ## Disclaimer 254 | 255 | This is a hobby project and is not actively maintained. I don't provide _any_ 256 | support! If you feel like contributing something, that's of course appreciated. 257 | Feel free to open a Pull Request. 258 | -------------------------------------------------------------------------------- /odoo/addons/pos_product_sequence/static/description/index.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |

6 | POS Product Sequence 7 |

8 |
9 |
10 |
11 |
12 | 13 |
14 |
15 |
16 |
17 |
18 |
Supported Editions
19 |
20 |
Community
21 |
Enterprise
22 |
23 |
24 |
25 |
26 |

POS Product Sequence module is used in Odoo POS to display the product's position in POS Session according to the sequence of numbers assigned. If you have 5 products in the backend and you want to set its sequence from 1 to 5, then the same sequence wise product show in POS Session in odoo. 27 |

28 |
29 |
30 |
31 |
32 |
33 |

Key Features

34 |
35 |
36 |
37 |

38 | User can set the Product sequence number. 39 |

40 |
41 |
42 |

43 | It shows sequence wise products in Odoo POS. 44 |

45 |
46 |
47 |

48 | User can manage the POS Sequence of Product in the Backend. 49 |

50 |
51 |
52 |
53 |
54 |
55 | 69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | Before POS Product Sequence 77 |

78 |
79 |
80 |
81 |
82 |
83 |
84 | 85 |
86 |
87 |
88 |
89 | Set Product Sequence 90 |

91 |
    92 |
  • 93 | Navigate to the Point of Sale and click on the Products menu. 94 |
  • 95 |
  • 96 | Open Products Variants sub-menu and click on Point of Sale tab. 97 |
  • 98 |
  • 99 | Now, we will set POS Sequence number. 100 |
  • 101 |
102 |
103 |
104 |
105 |
106 | 107 |
108 |
109 |
110 |
111 | After POS Product Sequence 112 |

113 |
    114 |
  • 115 | Now, we will open Odoo POS and check the position of configured product. 116 |
  • 117 |
  • 118 | Here, we can see configured product is in 2nd position. 119 |
  • 120 |
121 |
122 |
123 |
124 |
125 | 126 |
127 |
128 |
129 |

130 |
131 |
132 |
133 |
134 | 135 |
136 |
137 | 4th 138 | January, 2021 139 |
140 |
141 |
142 |

Latest Release 1.0

143 |

144 | First version to release. 145 |

146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |

155 |

Here See Demo Video:-

156 |
157 | Demo Video 158 |
159 |
160 |

161 |
162 |
163 |
164 |

Frequently Asked Question:-

165 |
166 |
167 |
168 |
169 |
170 |
Is this app compatible with Odoo Enterprise? 171 |
172 | 173 |
174 |
175 |
176 |
177 | Yes, our app works with Odoo Enterprise as well as Community. 178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
Is this app compatible with Windows or Ubuntu? 189 |
190 | 191 |
192 |
193 |
194 |
195 | Yes, our app works with Windows or Ubuntu operating system. 196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
Is this app required any additional configuration? 207 |
208 | 209 |
210 |
211 |
212 |
213 | No, install module and use this features. 214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |

FREE 3 MONTHS SUPPORT

229 |
230 |
231 |
232 |

Kanak Infosystem will provide free 3 months support for bug fixes, any doubts or queries, installation, configuration support or any types of issues related to this module.

233 |

234 | NOTE: This module do not required extra configuration. 235 |
236 |
237 |
238 |
239 |
240 | 241 | sales@kanakinfosystems.com 242 |
243 |
244 | 245 | kanakinfosystems 246 |
247 |
248 | 249 | +91 9818108884 250 |
251 |
252 |
253 |
254 |
255 | 312 |
313 |
314 |
315 |
316 |
317 |
318 | SUGGESTED APPS 319 | 320 | App Link 321 |
322 |
323 |
324 |
325 | 347 | 369 | 391 |
392 |
393 | 494 |
495 |
--------------------------------------------------------------------------------