Skip to content

Commit

Permalink
[IMP] fiscal_epos_print: Print courtesy receipt
Browse files Browse the repository at this point in the history
  • Loading branch information
SirAionTech committed Nov 14, 2024
1 parent 42f3cd7 commit 18035b2
Show file tree
Hide file tree
Showing 6 changed files with 305 additions and 6 deletions.
4 changes: 4 additions & 0 deletions fiscal_epos_print/models/point_of_sale.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ class PosConfig(models.Model):
fiscal_printer_serial = fields.Char(string='Fiscal Printer Serial')

fiscal_cashdrawer = fields.Boolean(string='Fiscal Printer Open CashDrawer')
epos_print_courtesy_receipt = fields.Boolean(
string="Print courtesy receipt",
help="Print a courtesy receipt when the order has to be invoiced",
)

@api.constrains('printer_ip', 'iface_reprint_done_order')
def _check_fiscal_epos_reprint(self):
Expand Down
252 changes: 251 additions & 1 deletion fiscal_epos_print/static/src/js/epson_epos_print.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,33 @@ odoo.define("fiscal_epos_print.epson_epos_print", function (require) {
var _t = core._t;
var round_pr = utils.round_precision;

/**
* Return true if the fiscal printer will print a fiscal receipt for `order`.
*/
function eposWillPrintReceipt(order) {
return order.pos.config.printer_ip && !order.is_to_invoice();
};
/**
* Return true if the fiscal printer will print a courtesy receipt for `order`.
*/
function eposWillPrintCourtesyReceipt(order) {
return order.pos.config.printer_ip && order.is_to_invoice() && order.pos.config.epos_print_courtesy_receipt;
};
/**
* Send `receipt` to the fiscal `printer`,
* this might print a receipt (fiscal or not) for `receipt`.
*/
function eposPrint(printer, receipt) {
var order = printer.order;
var result;
if (eposWillPrintReceipt(order)) {
result = printer.printFiscalReceipt(receipt);
} else if (eposWillPrintCourtesyReceipt(order)) {
result = printer.printNonFiscalReceipt(receipt);
}
return result
}

function addPadding(str, padding=4) {
var pad = new Array(padding).fill(0).join('') + str;
return pad.substr(pad.length - padding, padding);
Expand Down Expand Up @@ -436,6 +463,226 @@ odoo.define("fiscal_epos_print.epson_epos_print", function (require) {
console.log(xml);
},

addNonFiscalNode: function(xml, data, {font="1", operator="1"}) {
var node = xml.createElement("printNormal");
node.setAttribute("data", data);
node.setAttribute("font", font);
node.setAttribute("operator", operator);
xml.documentElement.appendChild(node);
},

formatAmountCurrency: function(amount, currency) {
if (currency.position === "after") {
return amount + " " + (currency.symbol || "");
} else {
return (currency.symbol || "") + " " + amount;
}
},

addNonFiscalEmptyLine: function(xml) {
var node = xml.createElement("printNormal");
node.setAttribute("data", "");
node.setAttribute("font", "1");
node.setAttribute("operator", "1");
xml.documentElement.appendChild(node);
},

addXMLNonFiscalHeader: function(xml, receipt) {
var beginNonFiscal = xml.createElement("beginNonFiscal");
beginNonFiscal.setAttribute("operator", receipt.operator || "1");
xml.documentElement.appendChild(beginNonFiscal);

this.addNonFiscalNode(
xml,
_t(`Courtesy receipt`),
{
font: "3",
operator: receipt.operator,
},
);

var invoice = receipt.epos_invoice;
this.addNonFiscalNode(
xml,
_t(`Copy of invoice ${invoice.name} of ${invoice.date}`),
{
operator: receipt.operator,
},
);
},

addXMLNonFiscalClient: function(xml, receipt) {
var client = this.order.get_client();

var clientName = client.name;
this.addNonFiscalNode(
xml,
_t(`Customer: ${clientName}`),
{
operator: receipt.operator,
},
);

var clientAddress = client.address;
if (clientAddress) {
this.addNonFiscalNode(
xml,
_t(`Address: ${clientAddress}`),
{
operator: receipt.operator,
},
);
}

var clientVAT = client.vat;
if (clientVAT) {
this.addNonFiscalNode(
xml,
_t(`VAT: ${clientVAT}`),
{
operator: receipt.operator,
},
);
}
},

addXMLNonFiscalOrderLine: function(xml, line, receipt) {
this.addNonFiscalNode(
xml,
line.product_name,
{
operator: receipt.operator,
},
);
var currency = receipt.currency;
var unit_amount = this.formatAmountCurrency(line.full_price, currency);
var total_amount = this.formatAmountCurrency(line.price_display, currency);
this.addNonFiscalNode(
xml,
_t(`${line.quantity} x ${unit_amount} = ${total_amount}`),
{
operator: receipt.operator,
},
);
var tax_amount = this.formatAmountCurrency(line.tax, currency);
this.addNonFiscalNode(
xml,
_t(`Tax code ${line.tax_department.code}: ${tax_amount}`),
{
operator: receipt.operator,
},
);
},

addXMLNonFiscalTaxDetail: function(xml, tax_detail, receipt) {
this.addNonFiscalNode(
xml,
_t(`Tax code ${tax_detail.tax.fpdeptax}: ${tax_detail.name}`),
{
operator: receipt.operator,
},
);
this.addNonFiscalNode(
xml,
this.formatAmountCurrency(tax_detail.amount, receipt.currency),
{
operator: receipt.operator,
},
);
},

addXMLNonFiscalTotal: function(xml, receipt) {
var invoice = this.order.epos_invoice;
this.addNonFiscalNode(
xml,
_t(`Total`),
{
operator: receipt.operator,
},
);
var currency = receipt.currency;
this.addNonFiscalNode(
xml,
_t(`Base: ${this.formatAmountCurrency(invoice.amount_untaxed, currency)}`),
{
operator: receipt.operator,
},
);
this.addNonFiscalNode(
xml,
_t(`Tax: ${this.formatAmountCurrency(invoice.amount_tax, currency)}`),
{
operator: receipt.operator,
},
);
this.addNonFiscalNode(
xml,
_t(`Total: ${this.formatAmountCurrency(invoice.amount_total, currency)}`),
{
operator: receipt.operator,
},
);
},

addXMLNonFiscalFooter: function(xml, receipt) {
this.addNonFiscalNode(
xml,
_t("Courtesy copy not valid for tax purposes. " +
"The original invoice has been sent to the SdI " +
"and can be consulted on the Revenue Agency website, " +
"in the Reserved Area."),
{
operator: receipt.operator,
},
);

var endNonFiscal = xml.createElement("endNonFiscal");
endNonFiscal.setAttribute("operator", receipt.operator || "1");
xml.documentElement.appendChild(endNonFiscal);
},

prepareXMLNonFiscalReceipt: function(receipt) {
var xml = document.implementation.createDocument(null, "printerNonFiscal");

this.addXMLNonFiscalHeader(xml, receipt);
this.addNonFiscalEmptyLine(xml);

this.addXMLNonFiscalClient(xml, receipt);
this.addNonFiscalEmptyLine(xml);

for (let line of receipt.orderlines) {
this.addXMLNonFiscalOrderLine(xml, line, receipt);
this.addNonFiscalEmptyLine(xml);
}
this.addNonFiscalEmptyLine(xml);

this.addNonFiscalNode(
xml,
_t("Taxes summary"),
{
operator: receipt.operator,
},
);
for (let tax_detail of receipt.tax_details) {
this.addXMLNonFiscalTaxDetail(xml, tax_detail, receipt);
this.addNonFiscalEmptyLine(xml);
}
this.addNonFiscalEmptyLine(xml);

this.addXMLNonFiscalTotal(xml, receipt);
this.addNonFiscalEmptyLine(xml);

this.addXMLNonFiscalFooter(xml, receipt);
return xml;
},

printNonFiscalReceipt: function(receipt) {
var xml = this.prepareXMLNonFiscalReceipt(receipt);
var xmlString = new XMLSerializer().serializeToString(xml);
this.fiscalPrinter.send(this.url, xmlString);
console.log(xmlString);
},

printFiscalReport: function() {
var xml = '<printerFiscalReport>';
xml += '<printZReport operator="" />';
Expand Down Expand Up @@ -474,7 +721,10 @@ odoo.define("fiscal_epos_print.epson_epos_print", function (require) {
});

return {
eposDriver: eposDriver
eposDriver: eposDriver,
eposWillPrintReceipt: eposWillPrintReceipt,
eposWillPrintCourtesyReceipt: eposWillPrintCourtesyReceipt,
eposPrint: eposPrint,
}

});
35 changes: 35 additions & 0 deletions fiscal_epos_print/static/src/js/models.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ odoo.define('fiscal_epos_print.models', function (require) {
var _t = core._t;
var round_pr = utils.round_precision;
var OrderSuper = models.Order;
var epson_epos_print = require('fiscal_epos_print.epson_epos_print');

models.load_fields("account.journal",
["fiscalprinter_payment_type", "fiscalprinter_payment_index"]);
Expand Down Expand Up @@ -92,6 +93,7 @@ odoo.define('fiscal_epos_print.models', function (require) {
receipt.fiscal_z_rep_number = this.fiscal_z_rep_number;
receipt.fiscal_printer_serial = this.fiscal_printer_serial;
receipt.fiscal_printer_debug_info = this.fiscal_printer_debug_info;
receipt.epos_invoice = this.epos_invoice;

return receipt
},
Expand Down Expand Up @@ -204,6 +206,39 @@ odoo.define('fiscal_epos_print.models', function (require) {
tax_model.fields.push('fpdeptax');
return _super_posmodel.initialize.call(this, session, attributes);
},
push_and_invoice_order: function(order) {
var self = this;
var invoiced = _super_posmodel.push_and_invoice_order.apply(this, arguments);
invoiced.done(function(){
// Get invoice from PoS `order`
self.chrome._rpc({
model: "pos.order",
method: "search_read",
args: [[["pos_reference", "=", order.name]], ["invoice_id",]],
}).then(function (server_orders) {
if (server_orders.length) {
var invoice_id = server_orders[0].invoice_id[0];
// Read invoice fields
self.chrome._rpc({
model: "account.invoice",
method: "read",
args: [invoice_id],
}).then(function (server_invoices) {
if (server_invoices.length) {
// Update `order` and print courtesy receipt
order.epos_invoice = server_invoices[0];
var printer_options = order.getPrinterOptions();
printer_options.order = order;
var receipt = order.export_for_printing();
var fp90 = new epson_epos_print.eposDriver(printer_options, order.pos.gui.current_screen);
return epson_epos_print.eposPrint(fp90, receipt);
}
});
}
});
});
return invoiced;
},
});

});
4 changes: 2 additions & 2 deletions fiscal_epos_print/static/src/js/pos_order_mgmt.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ odoo.define("fiscal_epos_print.pos_order_mgmt", function (require) {
// copiato da screens.PaymentScreenWidget
sendToFP90Printer: function(receipt, printer_options) {
var fp90 = new eposDriver(printer_options, this);
fp90.printFiscalReceipt(receipt);
return epson_epos_print.eposPrint(fp90, receipt);
},
action_print: function (order_data, order) {
if (this.pos.config.printer_ip) {
if (epson_epos_print.eposWillPrintReceipt(currentOrder)) {
if (order_data.fiscal_receipt_number) {
this.pos.gui.show_popup('error', {
'title': _t('Order already printed'),
Expand Down
6 changes: 3 additions & 3 deletions fiscal_epos_print/static/src/js/screens.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ odoo.define("fiscal_epos_print.screens", function (require) {

sendToFP90Printer: function(receipt, printer_options) {
var fp90 = new eposDriver(printer_options, this);
fp90.printFiscalReceipt(receipt);
return epson_epos_print.eposPrint(fp90, receipt);
},

render_receipt: function() {
Expand Down Expand Up @@ -59,15 +59,15 @@ odoo.define("fiscal_epos_print.screens", function (require) {
},
sendToFP90Printer: function(receipt, printer_options) {
var fp90 = new eposDriver(printer_options, this);
fp90.printFiscalReceipt(receipt);
return epson_epos_print.eposPrint(fp90, receipt);
},
finalize_validation: function() {
// we need to get currentOrder before calling the _super()
// otherwise we will likely get a empty order when we want to skip
// the receipt preview
var currentOrder = this.pos.get('selectedOrder');
this._super.apply(this, arguments);
if (this.pos.config.printer_ip && !currentOrder.is_to_invoice()) {
if (epson_epos_print.eposWillPrintReceipt(currentOrder)) {
this.chrome.loading_show();
this.chrome.loading_message(_t('Connecting to the fiscal printer'));
var printer_options = currentOrder.getPrinterOptions();
Expand Down
10 changes: 10 additions & 0 deletions fiscal_epos_print/views/point_of_sale.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@
<div class="o_setting_right_pane">
<label for="fiscal_cashdrawer"/>
</div>
<br/>
<div class="o_setting_left_pane">
<field name="epos_print_courtesy_receipt"/>
</div>
<div class="o_setting_right_pane">
<label for="epos_print_courtesy_receipt"/>
<div class="text-muted">
Print a courtesy receipt when the order has to be invoiced
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box" id="fiscal_printer_serial">
<div class="o_setting_right_pane">
Expand Down

0 comments on commit 18035b2

Please sign in to comment.