From 6cc7e121b667783ac8bd6446b227b303df32142c Mon Sep 17 00:00:00 2001 From: Suherdy Yacob Date: Tue, 12 May 2026 16:34:03 +0700 Subject: [PATCH] first commit --- .gitignore | 6 +++ README.md | 23 +++++++++++ __init__.py | 1 + __manifest__.py | 17 ++++++++ models/__init__.py | 1 + models/pos_config.py | 10 +++++ models/res_config_settings.py | 7 ++++ static/src/app/services/pos_store_patch.js | 25 ++++++++++++ static/src/app/utils/imin_printer_patch.js | 47 ++++++++++++++++++++++ views/res_config_settings_views.xml | 24 +++++++++++ 10 files changed, 161 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 __init__.py create mode 100644 __manifest__.py create mode 100644 models/__init__.py create mode 100644 models/pos_config.py create mode 100644 models/res_config_settings.py create mode 100644 static/src/app/services/pos_store_patch.js create mode 100644 static/src/app/utils/imin_printer_patch.js create mode 100644 views/res_config_settings_views.xml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ae5ab10 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +__pycache__/ +*.py[cod] +*$py.class +.DS_Store +.vscode/ +.idea/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..19940b4 --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +# POS iMin Extended + +This module extends the standard `pos_imin` functionality for Odoo 19 POS, allowing for direct printing to iMin built-in printers with customizable parameters. + +## Features + +- **Bypass Printer Dialog**: Uses the iMin JS SDK to print directly, avoiding the browser's print dialog. +- **Customizable Copies**: Set the number of copies to be printed for each receipt in POS settings. +- **Paper Size Support**: Choose between 80mm and 58mm paper sizes in the configuration. +- **Automatic Cutting**: Supports automatic paper cutting between copies (on supported iMin hardware). + +## Configuration + +1. Install the module. +2. Go to **Point of Sale > Configuration > Settings**. +3. Under the **iMin Printer** section: + - Set the **Print Copies**. + - Select the **Paper Size**. +4. To fully automate the process (no manual clicks after payment), enable **Automatic Receipt Printing** in the POS settings. + +## Dependencies + +- `pos_imin`: This module patches the core iMin integration. diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..0650744 --- /dev/null +++ b/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/__manifest__.py b/__manifest__.py new file mode 100644 index 0000000..9f3dc9d --- /dev/null +++ b/__manifest__.py @@ -0,0 +1,17 @@ +{ + 'name': 'POS iMin Extended', + 'version': '1.0', + 'category': 'Sales/Point of Sale', + 'summary': 'Extended configuration for iMin printers', + 'depends': ['pos_imin'], + 'data': [ + 'views/res_config_settings_views.xml', + ], + 'assets': { + 'point_of_sale._assets_pos': [ + 'pos_imin_extended/static/src/app/**/*', + ], + }, + 'installable': True, + 'license': 'LGPL-3', +} diff --git a/models/__init__.py b/models/__init__.py new file mode 100644 index 0000000..737009c --- /dev/null +++ b/models/__init__.py @@ -0,0 +1 @@ +from . import pos_config, res_config_settings diff --git a/models/pos_config.py b/models/pos_config.py new file mode 100644 index 0000000..0e985ae --- /dev/null +++ b/models/pos_config.py @@ -0,0 +1,10 @@ +from odoo import fields, models + +class PosConfig(models.Model): + _inherit = 'pos.config' + + imin_print_copies = fields.Integer(string='iMin Print Copies', default=1) + imin_paper_size = fields.Selection([ + ('0', '80mm'), + ('1', '58mm') + ], string='iMin Paper Size', default='0') diff --git a/models/res_config_settings.py b/models/res_config_settings.py new file mode 100644 index 0000000..f95e0ff --- /dev/null +++ b/models/res_config_settings.py @@ -0,0 +1,7 @@ +from odoo import fields, models + +class ResConfigSettings(models.TransientModel): + _inherit = 'res.config.settings' + + pos_imin_print_copies = fields.Integer(related='pos_config_id.imin_print_copies', readonly=False) + pos_imin_paper_size = fields.Selection(related='pos_config_id.imin_paper_size', readonly=False) diff --git a/static/src/app/services/pos_store_patch.js b/static/src/app/services/pos_store_patch.js new file mode 100644 index 0000000..2646ee4 --- /dev/null +++ b/static/src/app/services/pos_store_patch.js @@ -0,0 +1,25 @@ +/** @odoo-module */ + +import { patch } from "@web/core/utils/patch"; +import { PosStore } from "@point_of_sale/app/services/pos_store"; +import { IminPrinterAdapter } from "@pos_imin/app/utils/imin_printer"; + +patch(PosStore.prototype, { + async detectIminPrinter() { + // We override this to pass 'pos' to the adapter + try { + const iminPrinterAdapter = new IminPrinterAdapter({ + fallbackPrinter: this.hardwareProxy.printer, + pos: this, // Pass the pos store instance + }); + const isAvailable = await iminPrinterAdapter.isAvailable(); + if (isAvailable) { + this.iminPrinterAdapter = iminPrinterAdapter; + this.hardwareProxy.printer = this.iminPrinterAdapter; + await this.iminPrinterAdapter.connect(); + } + } catch (error) { + console.error("Unable to detect Imin printer:", error); + } + }, +}); diff --git a/static/src/app/utils/imin_printer_patch.js b/static/src/app/utils/imin_printer_patch.js new file mode 100644 index 0000000..6d18495 --- /dev/null +++ b/static/src/app/utils/imin_printer_patch.js @@ -0,0 +1,47 @@ +/** @odoo-module */ + +import { patch } from "@web/core/utils/patch"; +import { IminPrinterAdapter } from "@pos_imin/app/utils/imin_printer"; + +patch(IminPrinterAdapter.prototype, { + setup({ fallbackPrinter, pos } = {}) { + super.setup(...arguments); + this.pos = pos; + }, + + async sendPrintingJob(img) { + try { + const status = await this.printerStatus(); + if (status.value !== 0) { + return { result: false, errorCode: status.value, canRetry: true }; + } + + const config = this.pos?.config; + const paperSize = config?.imin_paper_size || '0'; + const copies = config?.imin_print_copies || 1; + + // Set paper size + await this.iminPrinter.setPaperSize(parseInt(paperSize)); + + for (let i = 0; i < copies; i++) { + await this.iminPrinter.printSingleBitmap(img); + + // Add some feed lines + this.iminPrinter.printAndLineFeed(); + this.iminPrinter.printAndLineFeed(); + this.iminPrinter.printAndLineFeed(); + + // If the printer has a cutter, we can use it + // Based on documentation, partialCutPaper() is recommended + if (typeof this.iminPrinter.partialCutPaper === 'function') { + this.iminPrinter.partialCutPaper(); + } + } + + return { result: true }; + } catch (error) { + console.error("IminPrinterAdapter: Printing job failed", error); + return { result: false, errorCode: error.message, canRetry: true }; + } + } +}); diff --git a/views/res_config_settings_views.xml b/views/res_config_settings_views.xml new file mode 100644 index 0000000..e13daf6 --- /dev/null +++ b/views/res_config_settings_views.xml @@ -0,0 +1,24 @@ + + + + res.config.settings.view.form.inherit.pos.imin.extended + res.config.settings + + + + +
+
+
+
+
+
+
+
+
+
+