@ -0,0 +1,41 @@ |
|||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg |
|||
:target: https://www.gnu.org/licenses/agpl-3.0-standalone.html |
|||
:alt: License: AGPL-3 |
|||
|
|||
POS Receipt Design |
|||
================== |
|||
Option to select the customised Receipts for each POS |
|||
|
|||
Company |
|||
------- |
|||
* `Cybrosys Techno Solutions <https://cybrosys.com/>`__ |
|||
|
|||
Credits |
|||
------- |
|||
Developer: (V14) Syamili K, |
|||
(V15) Sajna Sherin T, |
|||
(V16 & V17) Sadique Kottekkat |
|||
(V18) Sreerag PM |
|||
Contact: odoo@cybrosys.com |
|||
|
|||
Contacts |
|||
-------- |
|||
* Mail Contact : odoo@cybrosys.com |
|||
* Website : https://cybrosys.com |
|||
|
|||
Bug Tracker |
|||
----------- |
|||
Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. |
|||
|
|||
Maintainer |
|||
========== |
|||
.. image:: https://cybrosys.com/images/logo.png |
|||
:target: https://cybrosys.com |
|||
|
|||
This module is maintained by Cybrosys Technologies. |
|||
|
|||
For support and more information, please visit `Our Website <https://cybrosys.com/>`__ |
|||
|
|||
Further information |
|||
=================== |
|||
HTML Description: `<static/description/index.html>`__ |
@ -0,0 +1,23 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################ |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Author: Sreerag PM (<https://www.cybrosys.com>) |
|||
# |
|||
# This program is free software: you can modify |
|||
# it under the terms of the GNU Affero General Public License (AGPL) as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <https://www.gnu.org/licenses/>. |
|||
# |
|||
################################################################################ |
|||
from . import models |
@ -0,0 +1,54 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################ |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Author: Sreerag PM (<https://www.cybrosys.com>) |
|||
# |
|||
# This program is free software: you can modify |
|||
# it under the terms of the GNU Affero General Public License (AGPL) as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <https://www.gnu.org/licenses/>. |
|||
# |
|||
################################################################################ |
|||
{ |
|||
'name': 'POS Receipt Design', |
|||
'version': '18.0.1.0.0', |
|||
'category': 'Point of Sale', |
|||
'summary': "Customize POS receipts with unique templates for each POS in " |
|||
"Odoo 18", |
|||
'description': "Option to select the customised Receipts for each POS. So, " |
|||
"we can easily updated the Receipt Design for better styles", |
|||
'author': 'Cybrosys Techno Solutions', |
|||
'company': 'Cybrosys Techno Solutions', |
|||
'maintainer': 'Cybrosys Techno Solutions', |
|||
'website': 'https://www.cybrosys.com', |
|||
'depends': ['base', 'point_of_sale'], |
|||
'data': [ |
|||
'security/ir.model.access.csv', |
|||
'data/pos_receipt_design1_data.xml', |
|||
'data/pos_receipt_design2_data.xml', |
|||
'views/pos_receipt_views.xml', |
|||
'views/pos_config_views.xml' |
|||
], |
|||
'assets': { |
|||
'point_of_sale._assets_pos': [ |
|||
'custom_receipts_for_pos/static/src/js/receipt_design.js', |
|||
'custom_receipts_for_pos/static/src/xml/order_receipt.xml', |
|||
], |
|||
}, |
|||
'images': ['static/description/banner.png'], |
|||
'license': 'AGPL-3', |
|||
'installable': True, |
|||
'auto_install': False, |
|||
'application': False |
|||
} |
@ -0,0 +1,154 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<!-- Examples for receipt design: which can be used or modified --> |
|||
<record id="pos_receipt_design1" model="pos.receipt"> |
|||
<field name="name">Design 1</field> |
|||
<field name="design_receipt"><![CDATA[ |
|||
<div class="pos-receipt"> |
|||
<t t-if="env.services.pos.config.logo"> |
|||
<img t-att-src="'data:image/png;base64,' + env.services.pos.config.logo" |
|||
alt="Logo" class="pos-receipt-logo"/> |
|||
<br /> |
|||
</t> |
|||
<div class="pos-receipt-contact"> |
|||
<t t-if="env.services.pos.company.name"> |
|||
<div><t t-esc="env.services.pos.company.name" /></div> |
|||
</t> |
|||
<t t-if="env.services.pos.company.phone"> |
|||
<div>Tel:<t t-esc="env.services.pos.company.phone" /></div> |
|||
</t> |
|||
<t t-if="env.services.pos.company.vat"> |
|||
<div><t t-esc="env.services.pos.company.vat_label"/>:<t t-esc="env.services.pos.company.vat" /></div> |
|||
</t> |
|||
<t t-if="env.services.pos.company.email"> |
|||
<div><t t-esc="env.services.pos.company.email" /></div> |
|||
</t> |
|||
<t t-if="env.services.pos.company.website"> |
|||
<div><t t-esc="env.services.pos.company.website" /></div> |
|||
</t> |
|||
<t t-if="props.receipt.headerData.header"> |
|||
<t t-out="props.receipt.headerData.header" /> |
|||
</t> |
|||
<t t-if="props.receipt.headerData.cashier"> |
|||
<div class="cashier"> |
|||
<div>--------------------------------</div> |
|||
<div>Served by <t t-esc="props.receipt.headerData.cashier" /></div> |
|||
</div> |
|||
</t> |
|||
</div> |
|||
<br/> |
|||
<t t-if="props.receipt.headerData.header"> |
|||
<div style='text-align:center; font-size:13px'> |
|||
<t t-esc="props.receipt.headerData.header" /> |
|||
</div> |
|||
<br /> |
|||
</t> |
|||
<div> |
|||
<table class='receipt-orderlines' style="font-size:15px; border-style:double; border-left:none; border-right:none; border-bottom:none; width:100%;"> |
|||
<colgroup> |
|||
<col width='40%' /> |
|||
<col width='30%' /> |
|||
<col width='30%' /> |
|||
</colgroup> |
|||
<tr style="border-bottom:1px dashed black;"> |
|||
<th style="text-align:left;">Product</th> |
|||
<th style="text-align:right;">Qty</th> |
|||
<th style="text-align:right;">Amount</th> |
|||
</tr> |
|||
<t t-if="props.order and props.order.length and props.order and props.order.pos and props.order.pos.mainScreen and props.order.pos.mainScreen.props and props.order.pos.mainScreen.props.order and props.order.pos.mainScreen.props.order.orderlines and props.order.pos.mainScreen.props.order.orderlines.length"> |
|||
<t t-if="props.order.pos.mainScreen.props"> |
|||
<tr t-foreach="props.order.pos.mainScreen.props.order.orderlines" t-as="orderline" t-key="index_orderlines"> |
|||
<td style="padding-top:1%; padding-bottom:1%; text-align:left;"> |
|||
<t t-esc="orderline.get_product().display_name"/> |
|||
<t t-if="orderline.get_discount() > 0"> |
|||
<div style="font-size:12px; font-style:italic; color:#808080;"> |
|||
<t t-esc="orderline.get_discount()"/>% discount |
|||
</div> |
|||
</t> |
|||
<t t-if="orderline.customerNote"> |
|||
<div style="font-size:14px;" t-esc="orderline.customerNote"/> |
|||
</t> |
|||
</td> |
|||
<td style="text-align:right; font-size:14px;"> |
|||
<t t-esc="orderline.get_quantity_str_with_unit()"/> |
|||
</td> |
|||
<td style="text-align:right; font-size:14px;"> |
|||
<t t-esc="env.utils.formatCurrency(orderline.get_display_price())"/> |
|||
</td> |
|||
</tr> |
|||
</t> |
|||
</t> |
|||
<t t-else=""> |
|||
<t t-if="props.orderlines and props.orderlines.length"> |
|||
<tr t-foreach="props.orderlines" t-as="orderline" t-key="orderline.id"> |
|||
<td style="padding-top:1%; padding-bottom:1%; text-align:left;"> |
|||
<t t-esc="orderline.get_product().display_name"/> |
|||
<t t-if="orderline.get_discount() > 0"> |
|||
<div style="font-size:12px; font-style:italic; color:#808080;"> |
|||
<t t-esc="orderline.get_discount()"/>% discount |
|||
</div> |
|||
</t> |
|||
<t t-if="orderline.customerNote"> |
|||
<div style="font-size:14px;" t-esc="orderline.customerNote"/> |
|||
</t> |
|||
</td> |
|||
<td style="text-align:right; font-size:14px;"> |
|||
<t t-esc="orderline.get_quantity_str_with_unit()"/> |
|||
</td> |
|||
<td style="text-align:right; font-size:14px;"> |
|||
<t t-esc="env.utils.formatCurrency(orderline.get_display_price())"/> |
|||
</td> |
|||
</tr> |
|||
</t> |
|||
</t> |
|||
|
|||
</table> |
|||
</div> |
|||
<br /> |
|||
<div style="padding-top:6px;"> |
|||
<t t-set='taxincluded' t-value='Math.abs(props.receipt.amount_total - props.receipt.total_with_tax) <= 0.000001' /> |
|||
<t t-if='!taxincluded'> |
|||
<br/> |
|||
<div style="font-weight:700; font-size:14px; border-top:1px dashed;"> |
|||
<span style="margin-left:40%;">Subtotal : </span> |
|||
<span t-esc='env.utils.formatCurrency(props.data.total_without_tax)' |
|||
class="pos-receipt-right-align"/> |
|||
</div> |
|||
<t t-log='props'/> |
|||
<t t-foreach='props.data.tax_details' t-as='tax' t-key="index_tax_details"> |
|||
<div style="font-weight:700; font-size:14px;"> |
|||
<span style="margin-left:40%;"><t t-esc='tax.name' /></span> |
|||
<span t-esc='env.utils.formatCurrency(tax.amount)' |
|||
class="pos-receipt-right-align"/> |
|||
</div> |
|||
</t> |
|||
</t> |
|||
<!-- Total --> |
|||
<br/> |
|||
<div style="font-weight:700; font-size:14px;"> |
|||
<span style="margin-left:40%;">TOTAL : </span> |
|||
<span t-esc='env.utils.formatCurrency(props.data.amount_total)' class="pos-receipt-right-align"/> |
|||
</div> |
|||
<br/><br/> |
|||
</div> |
|||
<div class='before-footer' /> |
|||
<br/><br/> |
|||
<!-- Footer --> |
|||
<div class="pos-receipt-order-data"> |
|||
<div><t t-esc="props.receipt.name" /> |
|||
</div> |
|||
<t t-if="props.receipt.date"> |
|||
<div><t t-esc="props.receipt.date" /></div> |
|||
</t> |
|||
<t t-else=""> |
|||
<div><t t-esc="props.receipt.date" /></div> |
|||
</t> |
|||
</div> |
|||
<br/><br/> |
|||
<div style="font-size:14px; text-align:center;"> |
|||
Thank You... Please Visit Again ... |
|||
</div> |
|||
</div>]]></field> |
|||
</record> |
|||
|
|||
</odoo> |
@ -0,0 +1,188 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<!-- Examples for receipt design: which can be used or modified --> |
|||
<record id="pos_receipt_design2_demo" model="pos.receipt"> |
|||
<field name="name">Design 2</field> |
|||
<field name="design_receipt"><![CDATA[ |
|||
<div class="pos-receipt"> |
|||
<t t-if="env.services.pos.config.logo"> |
|||
<img t-att-src="'data:image/png;base64,' + env.services.pos.config.logo" |
|||
alt="Logo" class="pos-receipt-logo"/> |
|||
<br /> |
|||
</t> |
|||
<div style="font-size:13px; text-align:center;"> |
|||
<t t-esc="env.services.pos.company.name"/><br /> |
|||
Phone:<t t-esc="env.services.pos.company.phone || ''"/><br /> |
|||
</div> |
|||
<br/> |
|||
<div style="font-size:13px; text-align:center;"> |
|||
Date : |
|||
<t t-if="props.receipt.date"> |
|||
<t t-esc="props.receipt.date"/> |
|||
</t> |
|||
<t t-else=""> |
|||
<t t-esc="props.order.validation_date"/> |
|||
</t> |
|||
<br /> |
|||
Order : <t t-esc="props.order.name"/><br /> |
|||
</div> |
|||
<br /> |
|||
<div style="font-size:13px; text-align:center;"> |
|||
Cashier : <t t-esc='props.receipt.headerData.cashier' /><br /> |
|||
<t t-if="props.order.partner_id"> |
|||
Customer : <t t-esc='props.order.partner_id.name' style="font-style:bold" /> |
|||
</t> |
|||
<br /> |
|||
</div> |
|||
<br/> |
|||
<t t-if="props.receipt.headerData.header"> |
|||
<div style='text-align:center; font-size:13px'> |
|||
<t t-esc="props.receipt.headerData.header" /> |
|||
</div> |
|||
<br /> |
|||
</t> |
|||
<div> |
|||
<table class='receipt-orderlines' style="font-size:15px; border-style:double; |
|||
border-left:none; border-right:none; border-bottom:none; width:100%;"> |
|||
<colgroup> |
|||
<col width='40%' /> |
|||
<col width='30%' /> |
|||
<col width='30%' /> |
|||
</colgroup> |
|||
<tr style="border-bottom:1px dashed black;"> |
|||
<th style="text-align:left;">Product</th> |
|||
<th style="text-align:right;">Qty</th> |
|||
<th style="text-align:right;">Amount</th> |
|||
</tr> |
|||
<t t-if="props.order and props.order.length and props.order and props.order.pos and props.order.pos.mainScreen and props.order.pos.mainScreen.props and props.order.pos.mainScreen.props.order and props.order.pos.mainScreen.props.order.orderlines and props.order.pos.mainScreen.props.order.orderlines.length"> |
|||
<t t-if="props.order.pos.mainScreen.props"> |
|||
<tr t-foreach="props.order.pos.mainScreen.props.order.orderlines" t-as="orderline" t-key="index_orderlines"> |
|||
<td style="padding-top:1%; padding-bottom:1%; text-align:left;"> |
|||
<t t-esc="orderline.get_product().display_name"/> |
|||
<t t-if="orderline.get_discount() > 0"> |
|||
<div style="font-size:12px; font-style:italic; color:#808080;"> |
|||
<t t-esc="orderline.get_discount()"/>% discount |
|||
</div> |
|||
</t> |
|||
<t t-if="orderline.customerNote"> |
|||
<div style="font-size:14px;" t-esc="orderline.customerNote"/> |
|||
</t> |
|||
</td> |
|||
<td style="text-align:right; font-size:14px;"> |
|||
<t t-esc="orderline.get_quantity_str_with_unit()"/> |
|||
</td> |
|||
<td style="text-align:right; font-size:14px;"> |
|||
<t t-esc="env.utils.formatCurrency(orderline.get_display_price())"/> |
|||
</td> |
|||
</tr> |
|||
</t> |
|||
</t> |
|||
<t t-else=""> |
|||
<t t-if="props.orderlines and props.orderlines.length"> |
|||
<tr t-foreach="props.orderlines" t-as="orderline" t-key="orderline.id"> |
|||
<td style="padding-top:1%; padding-bottom:1%; text-align:left;"> |
|||
<t t-esc="orderline.get_product().display_name"/> |
|||
<t t-if="orderline.get_discount() > 0"> |
|||
<div style="font-size:12px; font-style:italic; color:#808080;"> |
|||
<t t-esc="orderline.get_discount()"/>% discount |
|||
</div> |
|||
</t> |
|||
<t t-if="orderline.customerNote"> |
|||
<div style="font-size:14px;" t-esc="orderline.customerNote"/> |
|||
</t> |
|||
</td> |
|||
<td style="text-align:right; font-size:14px;"> |
|||
<t t-esc="orderline.get_quantity_str_with_unit()"/> |
|||
</td> |
|||
<td style="text-align:right; font-size:14px;"> |
|||
<t t-esc="env.utils.formatCurrency(orderline.get_display_price())"/> |
|||
</td> |
|||
</tr> |
|||
</t> |
|||
</t> |
|||
</table> |
|||
</div> |
|||
<br /> |
|||
<div style="padding-top:6px;"> |
|||
<t t-set='taxincluded' t-value='Math.abs(props.receipt.amount_total - props.receipt.total_with_tax) <= 0.000001' /> |
|||
<t t-if='!taxincluded'> |
|||
<br/> |
|||
<div style="font-weight:700; font-size:14px; border-top:1px dashed;"><span style="margin-left:40%;">Subtotal : </span><span t-esc='env.utils.formatCurrency(props.data.total_without_tax)' class="pos-receipt-right-align"/></div> |
|||
<t t-if="props.data.tax_details"> |
|||
<t t-foreach='props.data.tax_details' t-as='tax' t-key="index_tax_details"> |
|||
<div style="font-weight:700; font-size:14px;"> |
|||
<span style="margin-left:40%;"><t t-esc='tax.name' /></span> |
|||
<span t-esc='env.utils.formatCurrency(tax.amount)' class="pos-receipt-right-align"/> |
|||
</div> |
|||
</t> |
|||
</t> |
|||
</t> |
|||
<!-- Total --> |
|||
<br/> |
|||
<div style="font-weight:700; font-size:14px;"> |
|||
<span style="margin-left:40%;">TOTAL : </span> |
|||
<span t-esc='env.utils.formatCurrency(props.data.amount_total)' class="pos-receipt-right-align"/> |
|||
</div> |
|||
<br/><br/> |
|||
</div> |
|||
<!-- Payment Lines --> |
|||
<t t-foreach='props.paymentlines' t-as='line' t-key="index_paymentlines"> |
|||
<div style="font-size:14px; border-top:1px dashed; padding-top:5px;"> |
|||
<span style="margin-left:40%;"><t t-esc='line.name' /></span> |
|||
<span t-esc='env.utils.formatCurrency(line.amount)' class="pos-receipt-right-align"/> |
|||
</div> |
|||
</t> |
|||
<br/> |
|||
<div class="receipt-change" style="font-size:14px;"> |
|||
<span style="margin-left:40%;">CHANGE : </span> |
|||
<span t-esc='env.utils.formatCurrency(props.receipt.change)' class="pos-receipt-right-align"/> |
|||
</div> |
|||
<br/> |
|||
<!-- Extra Payment Info --> |
|||
<t t-if='props.receipt.total_discount'> |
|||
<div style="font-size:14px; border-top:1px dashed; padding-top:5px;"> |
|||
<span style="margin-left:40%;">Discounts : </span> |
|||
<span t-esc='env.utils.formatCurrency(props.receipt.total_discount)' class="pos-receipt-right-align"/> |
|||
</div> |
|||
</t> |
|||
<t t-if='taxincluded'> |
|||
<t t-if="props.receipt.tax_details"> |
|||
<t t-foreach='props.receipt.tax_details' t-as='tax' t-key="index_receipt_tax_details"> |
|||
<div style="font-size:14px;"> |
|||
<span style="margin-left:40%;"><t t-esc='tax.name' /></span> |
|||
<span t-esc='env.utils.formatCurrency(tax.amount)' class="pos-receipt-right-align"/> |
|||
</div> |
|||
</t> |
|||
</t> |
|||
<div style="font-size:14px;"> |
|||
<span style="margin-left:40%;">Total Taxes : </span> |
|||
<span t-esc='env.utils.formatCurrency(props.receipt.total_tax)' class="pos-receipt-right-align"/> |
|||
</div> |
|||
</t> |
|||
<div class='before-footer' /> |
|||
<!-- Footer --> |
|||
<div t-if='props.receipt.footer_html' style="text-align:center; font-size:14px;"> |
|||
<t t-raw='props.receipt.footer_html'/> |
|||
</div> |
|||
<div t-if='!props.receipt.footer_html and props.receipt.footer' style="text-align:center; font-size:14px;"> |
|||
<br/> |
|||
<t t-esc='props.receipt.footer'/> |
|||
<br/><br/> |
|||
</div> |
|||
<div class='after-footer' style="font-size:14px;"> |
|||
<t t-foreach='props.paymentlines' t-as='line' t-key="index_payment"> |
|||
<t t-if='line.ticket'> |
|||
<br /> |
|||
<div class="pos-payment-terminal-receipt"> |
|||
<t t-raw='line.ticket'/> |
|||
</div> |
|||
</t> |
|||
</t> |
|||
</div> |
|||
<br/><br/> |
|||
<div style="font-size:14px; text-align:center;"> |
|||
Thank You... Please Visit Again ... |
|||
</div> |
|||
</div>]]></field> |
|||
</record> |
|||
</odoo> |
@ -0,0 +1,6 @@ |
|||
## Module <custom_receipts_for_pos> |
|||
|
|||
#### 30.10.2024 |
|||
#### Version 18.0.1.0.0 |
|||
##### ADD |
|||
- Initial Commit for POS Receipt Design |
@ -0,0 +1,25 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################ |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Author: Sreerag PM (<https://www.cybrosys.com>) |
|||
# |
|||
# This program is free software: you can modify |
|||
# it under the terms of the GNU Affero General Public License (AGPL) as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <https://www.gnu.org/licenses/>. |
|||
# |
|||
################################################################################ |
|||
from .import pos_receipt |
|||
from .import pos_config |
|||
from .import pos_session |
@ -0,0 +1,41 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################ |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Author: Sreerag PM (<https://www.cybrosys.com>) |
|||
# |
|||
# This program is free software: you can modify |
|||
# it under the terms of the GNU Affero General Public License (AGPL) as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <https://www.gnu.org/licenses/>. |
|||
# |
|||
################################################################################ |
|||
from odoo import fields, models |
|||
|
|||
|
|||
class PosConfig(models.Model): |
|||
""" |
|||
This is an Odoo model for Point of Sale (POS). |
|||
It inherits the 'pos.config' model to add new fields. |
|||
""" |
|||
_inherit = 'pos.config' |
|||
|
|||
receipt_design_id = fields.Many2one('pos.receipt', string='Receipt Design', |
|||
help='Choose any receipt design') |
|||
design_receipt = fields.Text(related='receipt_design_id.design_receipt', |
|||
string='Receipt XML') |
|||
logo = fields.Binary(related='company_id.logo', string='Logo', |
|||
readonly=False) |
|||
is_custom_receipt = fields.Boolean(string='Is Custom Receipt', |
|||
help='Indicates the receipt design is ' |
|||
'custom or not') |
@ -0,0 +1,37 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################ |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Author: Sreerag PM (<https://www.cybrosys.com>) |
|||
# |
|||
# This program is free software: you can modify |
|||
# it under the terms of the GNU Affero General Public License (AGPL) as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <https://www.gnu.org/licenses/>. |
|||
# |
|||
################################################################################ |
|||
from odoo import fields, models |
|||
|
|||
|
|||
class PosReceipt(models.Model): |
|||
""" |
|||
This is an Odoo model for Point of Sale (POS). |
|||
It creates a new model of pos.receipt for providing different types of |
|||
receipt design. |
|||
""" |
|||
_name = 'pos.receipt' |
|||
_description = 'POS Receipts' |
|||
|
|||
name = fields.Char(string='Name', help='Name of the pos receipt') |
|||
design_receipt = fields.Text(string='Receipt XML', |
|||
help='Add your customised receipts for pos') |
@ -0,0 +1,52 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################ |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Author: Sreerag PM (<https://www.cybrosys.com>) |
|||
# |
|||
# This program is free software: you can modify |
|||
# it under the terms of the GNU Affero General Public License (AGPL) as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <https://www.gnu.org/licenses/>. |
|||
# |
|||
################################################################################ |
|||
from odoo import models |
|||
|
|||
|
|||
class PosSession(models.Model): |
|||
""" |
|||
This is an Odoo model for Point of Sale (POS) sessions. |
|||
It inherits from the 'pos.session' model and extends its functionality. |
|||
|
|||
Methods: _loader_params_product_product(): Adds the 'qty_available' |
|||
field to the search parameters for the product loader. |
|||
""" |
|||
_inherit = 'pos.session' |
|||
|
|||
def _loader_params_product_product(self): |
|||
"""Function to load the product field to the product params""" |
|||
result = super()._loader_params_product_product() |
|||
result['search_params']['fields'].append('qty_available') |
|||
return result |
|||
|
|||
def _loader_params_pos_receipt(self): |
|||
"""Function that returns the product field pos Receipt""" |
|||
return { |
|||
'search_params': { |
|||
'fields': ['design_receipt', 'name'], |
|||
}, |
|||
} |
|||
|
|||
def _get_pos_ui_pos_receipt(self, params): |
|||
"""Used to Return the params value to the pos Receipts""" |
|||
return self.env['pos.receipt'].search_read(**params['search_params']) |
|
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 628 KiB |
After Width: | Height: | Size: 190 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 210 KiB |
After Width: | Height: | Size: 209 KiB |
After Width: | Height: | Size: 109 KiB |
After Width: | Height: | Size: 495 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 624 B |
After Width: | Height: | Size: 136 KiB |
After Width: | Height: | Size: 214 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 310 B |
After Width: | Height: | Size: 929 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 542 B |
After Width: | Height: | Size: 576 B |
After Width: | Height: | Size: 733 B |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 738 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 911 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 600 B |
After Width: | Height: | Size: 673 B |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 462 B |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 926 B |
After Width: | Height: | Size: 9.0 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 7.0 KiB |
After Width: | Height: | Size: 878 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 653 B |
After Width: | Height: | Size: 800 B |
After Width: | Height: | Size: 905 B |
After Width: | Height: | Size: 189 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 839 B |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 427 B |
After Width: | Height: | Size: 627 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 988 B |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 875 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 912 KiB |
After Width: | Height: | Size: 1.3 MiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 85 KiB |
After Width: | Height: | Size: 82 KiB |
After Width: | Height: | Size: 57 KiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 77 KiB |
After Width: | Height: | Size: 167 KiB |
After Width: | Height: | Size: 71 KiB |
After Width: | Height: | Size: 78 KiB |
After Width: | Height: | Size: 880 KiB |
After Width: | Height: | Size: 90 KiB |
After Width: | Height: | Size: 12 KiB |
@ -0,0 +1,44 @@ |
|||
/** @odoo-module */ |
|||
import { OrderReceipt } from "@point_of_sale/app/screens/receipt_screen/receipt/order_receipt"; |
|||
import { patch } from "@web/core/utils/patch"; |
|||
import { useState, Component, xml } from "@odoo/owl"; |
|||
import { useService } from "@web/core/utils/hooks"; |
|||
|
|||
patch(OrderReceipt.prototype, { |
|||
setup(){ |
|||
super.setup(); |
|||
this.state = useState({ |
|||
template: true, |
|||
}) |
|||
this.pos = useState(useService("pos")); |
|||
const templateProps = { |
|||
data: this.props.data, |
|||
order: this.pos.get_order(), |
|||
receipt: this.pos.get_order().export_for_printing(), |
|||
orderlines: this.pos.get_order().get_orderlines(), |
|||
paymentlines: this.pos.get_order().export_for_printing().paymentlines |
|||
}; |
|||
}, |
|||
get templateProps() { |
|||
return { |
|||
data: this.props.data, |
|||
order: this.pos.get_order(), |
|||
receipt: this.pos.get_order().export_for_printing(), |
|||
orderlines: this.pos.get_order().get_orderlines(), |
|||
paymentlines: this.pos.get_order().export_for_printing().paymentlines |
|||
}; |
|||
}, |
|||
get templateComponent() { |
|||
var mainRef = this; |
|||
return class extends Component { |
|||
setup() {} |
|||
static template = xml`${mainRef.pos.config.design_receipt}` |
|||
}; |
|||
}, |
|||
get isTrue() { |
|||
if (this.env.services.pos.config.is_custom_receipt == false) { |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
}); |
@ -0,0 +1,168 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<!--Inherit point_of_sale.OrderReceipt for getting our custom receipt design--> |
|||
<templates id="template" xml:space="preserve"> |
|||
<t t-inherit="point_of_sale.OrderReceipt" t-inherit-mode="extension"> |
|||
<xpath expr="//div[hasclass('pos-receipt')]" position="replace"> |
|||
<div class="pos-receipt"> |
|||
<t t-if="isTrue"> |
|||
<ReceiptHeader data="props.data.headerData"/> |
|||
<OrderWidget lines="props.data.orderlines" t-slot-scope="scope"> |
|||
<t t-set="line" t-value="scope.line"/> |
|||
<Orderline line="omit(scope.line, 'customerNote')" |
|||
class="{ 'pe-none': true }"> |
|||
<li t-if="line.customerNote" |
|||
class="customer-note w-100 p-2 my-1 rounded text-break"> |
|||
<i class="fa fa-sticky-note me-1" role="img" |
|||
aria-label="Customer Note" title="Customer Note"/> |
|||
<t t-esc="line.customerNote"/> |
|||
</li> |
|||
<ul t-if="line.pack_lot_lines"> |
|||
<li t-foreach="line.pack_lot_lines" t-as="lot" |
|||
t-key="lot.cid"> |
|||
<t t-if="lot.order_line.product.tracking == 'lot'"> |
|||
Lot Number <t t-esc="lot.lot_name"/> |
|||
</t> |
|||
<t t-else=""> |
|||
SN <t t-esc="lot.lot_name"/> |
|||
</t> |
|||
</li> |
|||
</ul> |
|||
</Orderline> |
|||
</OrderWidget> |
|||
|
|||
<!-- Total --> |
|||
<div class="pos-receipt-right-align">--------</div> |
|||
<br/> |
|||
<div class="pos-receipt-amount"> |
|||
TOTAL |
|||
<span t-esc="props.formatCurrency(props.data.amount_total)" |
|||
class="pos-receipt-right-align"/> |
|||
</div> |
|||
<t t-if="props.data.rounding_applied"> |
|||
<div class="pos-receipt-amount"> |
|||
Rounding |
|||
<span t-esc='props.formatCurrency(props.data.rounding_applied)' |
|||
class="pos-receipt-right-align"/> |
|||
</div> |
|||
<div class="pos-receipt-amount">To Pay |
|||
<span t-esc='props.formatCurrency(props.data.amount_total + props.data.rounding_applied)' |
|||
class="pos-receipt-right-align"/> |
|||
</div> |
|||
</t> |
|||
<br/> |
|||
<br/> |
|||
|
|||
<!-- Payment Lines --> |
|||
|
|||
<div class="paymentlines" t-foreach="props.data.paymentlines" |
|||
t-as="line" t-key="line_index"> |
|||
<t t-esc="line.name"/> |
|||
<span t-esc="props.formatCurrency(line.amount, false)" |
|||
class="pos-receipt-right-align"/> |
|||
</div> |
|||
<div class="pos-receipt-amount receipt-change mt-2"> |
|||
CHANGE |
|||
<span t-esc="props.formatCurrency(props.data.change)" |
|||
class="pos-receipt-right-align"/> |
|||
</div> |
|||
|
|||
<!-- Extra Payment Info --> |
|||
|
|||
<t t-if="props.data.total_discount"> |
|||
<div> |
|||
Discounts |
|||
<span t-esc="props.formatCurrency(props.data.total_discount)" |
|||
class="pos-receipt-right-align"/> |
|||
</div> |
|||
</t> |
|||
<div t-if="props.data.tax_details.length > 0" |
|||
class="pos-receipt-taxes"> |
|||
<span/> |
|||
<span>TAX%</span> |
|||
<span>Tax</span> |
|||
<span>Base</span> |
|||
<span>Total</span> |
|||
<t t-foreach="props.data.tax_details" t-as="tax" |
|||
t-key="tax.tax.id"> |
|||
<span t-esc="tax.tax.letter || ''"/> |
|||
<span><t t-esc="tax.tax.amount"/> |
|||
%</span> |
|||
<span t-esc="props.formatCurrency(tax.amount, false)"/> |
|||
<span t-esc="props.formatCurrency(tax.base, false)"/> |
|||
<span t-esc="props.formatCurrency(tax.amount + tax.base, false)"/> |
|||
</t> |
|||
<t t-if="props.data.tax_details.length > 1"> |
|||
<span/> |
|||
<span/> |
|||
<span t-esc="props.formatCurrency(props.data.amount_tax, false)"/> |
|||
<span t-esc="props.formatCurrency(props.data.total_without_tax, false)"/> |
|||
<span t-esc="props.formatCurrency(props.data.amount_total, false)"/> |
|||
</t> |
|||
</div> |
|||
|
|||
<div class="before-footer"/> |
|||
|
|||
<div t-if="props.data.pos_qr_code"> |
|||
<br/> |
|||
<br/> |
|||
<div class="pos-receipt-order-data mb-2"> |
|||
Scan me to request an invoice for your purchase. |
|||
</div> |
|||
<img id="posqrcode" t-att-src="props.data.pos_qr_code" |
|||
class="pos-receipt-logo"/> |
|||
</div> |
|||
<div t-if="props.data.ticket_code"> |
|||
<br/> |
|||
<br/> |
|||
<div class="pos-receipt-order-data"> |
|||
You can go to <t t-out="props.data.base_url"/>/pos/ticket |
|||
and use the code below to request an invoice online |
|||
</div> |
|||
<div class="pos-receipt-order-data"> |
|||
Unique Code: <t t-out="props.data.ticket_code"/> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- Footer --> |
|||
<div t-if="props.data.footer" class="pos-receipt-center-align" |
|||
style="white-space:pre-line"> |
|||
<br/> |
|||
<t t-esc="props.data.footer"/> |
|||
<br/> |
|||
<br/> |
|||
</div> |
|||
|
|||
<div class="after-footer"> |
|||
<t t-foreach="props.data.paymentlines" t-as="line" |
|||
t-key="line_index"> |
|||
<t t-if="line.ticket"> |
|||
<br/> |
|||
<div class="pos-payment-terminal-receipt"> |
|||
<pre t-esc="line.ticket"/> |
|||
</div> |
|||
</t> |
|||
</t> |
|||
</div> |
|||
|
|||
<br/> |
|||
<t t-if="props.shippingDate"> |
|||
<div class="pos-receipt-order-data"> |
|||
Expected delivery: |
|||
<div><t t-esc="props.shippingDate" /></div> |
|||
</div> |
|||
</t> |
|||
|
|||
<br/> |
|||
<div class="pos-receipt-order-data"> |
|||
<p>Odoo Point of Sale</p> |
|||
<div t-esc="props.data.name"/> |
|||
<div t-esc="props.data.date"/> |
|||
</div> |
|||
</t> |
|||
<t t-else=""> |
|||
<t t-component="templateComponent" t-props="templateProps"/> |
|||
</t> |
|||
</div> |
|||
</xpath> |
|||
</t> |
|||
</templates> |
@ -0,0 +1,22 @@ |
|||
<?xml version='1.0' encoding='utf-8'?> |
|||
<odoo> |
|||
<!-- Inherits `pos.config` form view to add the new fields for the configuration for custom receipt design --> |
|||
<record id="pos_config_view_form" model="ir.ui.view"> |
|||
<field name="name">pos.config.view.form.inherit.custom.receipts.for.pos</field> |
|||
<field name="model">pos.config</field> |
|||
<field name="inherit_id" ref="point_of_sale.pos_config_view_form"/> |
|||
<field name="arch" type="xml"> |
|||
<xpath expr="//setting[@id='other_devices']" position="after"> |
|||
<setting title="Customize the POS receipts" string="Custom Receipt" help="Use custom receipt designs"> |
|||
<field name="is_custom_receipt"/> |
|||
<div class="content-group mt16"> |
|||
<field name="receipt_design_id" invisible="not is_custom_receipt" required="True"/> |
|||
</div> |
|||
<div class="content-group mt16"> |
|||
<field name="design_receipt" invisible="1"/> |
|||
</div> |
|||
</setting> |
|||
</xpath> |
|||
</field> |
|||
</record> |
|||
</odoo> |