add pos_cashdro_refund,pos_cashdro_allow_manual

This commit is contained in:
Luis 2026-04-24 13:34:06 +02:00
parent 9b25650118
commit b7e8f8967c
14 changed files with 409 additions and 0 deletions

View file

@ -0,0 +1,3 @@
# Copyright 2026 Criptomart
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from . import models

View file

@ -0,0 +1,23 @@
# Copyright 2026 Criptomart
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
{
"name": "POS CashDro Allow Manual Amount",
"summary": "Permite introducir manualmente el importe en pagos CashDro",
"version": "16.0.1.0.0",
"category": "Point of Sale",
"license": "AGPL-3",
"author": "Criptomart",
"depends": [
"pos_payment_method_cashdro",
],
"data": [
"views/pos_payment_method_views.xml",
],
"assets": {
"point_of_sale.assets": [
"pos_cashdro_allow_manual/static/src/js/PaymentScreen.esm.js",
"pos_cashdro_allow_manual/static/src/xml/PaymentScreenPaymentLines.xml",
],
},
"installable": True,
}

View file

@ -0,0 +1,4 @@
# Copyright 2026 Criptomart
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from . import pos_payment_method
from . import pos_session

View file

@ -0,0 +1,18 @@
# Copyright 2026 Criptomart
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models
class PosPaymentMethod(models.Model):
_inherit = "pos.payment.method"
cashdro_allow_manual_amount = fields.Boolean(
string="Permitir importe manual",
help=(
"Cuando está activado, aparece un botón 'Manual' en la pantalla de "
"pago del TPV que permite confirmar el importe de la línea sin pasar "
"por la máquina CashDro. Útil ante fallos de comunicación, "
"devoluciones u otras situaciones de emergencia."
),
default=True,
)

View file

@ -0,0 +1,12 @@
# Copyright 2026 Criptomart
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import models
class PosSession(models.Model):
_inherit = "pos.session"
def _loader_params_pos_payment_method(self):
result = super()._loader_params_pos_payment_method()
result["search_params"]["fields"].append("cashdro_allow_manual_amount")
return result

View file

@ -0,0 +1,45 @@
/** @odoo-module **/
// Copyright 2026 Criptomart
// License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
import {Component} from "point_of_sale.Registries";
import PaymentScreen from "point_of_sale.PaymentScreen";
import {useListener} from "@web/core/utils/hooks";
const CashdroAllowManualPaymentScreen = (OriginalPaymentScreen) =>
class extends OriginalPaymentScreen {
setup() {
super.setup();
useListener("cashdro-send-manual", this._cashdroSendManual);
}
/**
* Mark the Cashdro payment line as done using the amount that is already
* set on the line (entered manually via the numpad), without contacting
* the CashDro machine.
*
* Sets `cashdro_manual_done = true` on the line so the delete button
* remains visible even in `done` state, letting the cashier undo the
* operation in case of a mistake.
*
* Refuses to proceed when the amount is 0 to avoid locking the POS with
* an undeletable zero-amount payment line.
*/
async _cashdroSendManual({detail: line}) {
if (!line.get_amount()) {
this.showPopup("ErrorPopup", {
title: this.env._t("Importe no válido"),
body: this.env._t(
"Introduzca el importe en el teclado numérico antes de confirmar manualmente el pago."
),
});
return;
}
// Flag this line as manually confirmed so the template keeps
// showing its delete button even after the status is 'done'.
line.cashdro_manual_done = true;
line.set_payment_status("done");
}
};
Component.extend(PaymentScreen, CashdroAllowManualPaymentScreen);

View file

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!-- Copyright 2026 Criptomart
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
Extends the PaymentScreenPaymentLines template to add a "Manual" button
next to the Send/Retry action buttons on Cashdro payment lines.
The button is shown when:
- the payment method is of type "cashdro"
- cashdro_allow_manual_amount is True on that payment method
- the line is in "pending" or "retry" state (the two states where
the numpad is already active and the cashier can edit the amount)
Clicking it triggers the "cashdro-send-manual" event which is handled
by CashdroAllowManualPaymentScreen in PaymentScreen.esm.js.
-->
<templates id="template" xml:space="preserve">
<t
t-name="pos_cashdro_allow_manual.PaymentScreenPaymentLines"
t-inherit="point_of_sale.PaymentScreenPaymentLines"
t-inherit-mode="extension"
owl="1"
>
<!--
//div[hasclass('send_payment_request')] matches two nodes:
1. the "Send" button shown in the "pending" state
2. the "Retry" button shown in the "retry" state
position="after" inserts our node after each match,
so the Manual button appears in both states.
-->
<xpath expr="//div[hasclass('send_payment_request')]" position="before">
<t
t-if="line.payment_method.use_payment_terminal === 'cashdro'
and line.payment_method.cashdro_allow_manual_amount"
>
<div
class="button cashdro-manual-button"
style="flex: 0 0 auto; padding: 0 12px; font-size: 0.8em; opacity: 0.75;"
title="Confirmar importe manualmente sin usar la máquina CashDro"
t-on-click="() => this.trigger('cashdro-send-manual', line)"
>
Manual
</div>
</t>
</xpath>
<!--
Extend the t-if on the wrapper <t> that controls the delete button
visibility so that manually-confirmed Cashdro lines keep showing the
delete button even in 'done' state. This lets the cashier undo
an accidental Manual press without blocking the POS session.
The targeted element is the <t t-if="..."> that wraps the
delete-button <div> inside the selected payment line block.
-->
<xpath
expr="//t[@t-if='line.selected']/div/t[div[hasclass('delete-button')]]"
position="attributes"
>
<attribute name="t-if">!line.payment_status or !['done', 'reversed', 'waitingCard', 'waitingCapture'].includes(line.payment_status) or line.cashdro_manual_done</attribute>
</xpath>
</t>
</templates>

View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!-- Copyright 2026 Criptomart
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="pos_payment_method_cashdro_allow_manual_form" model="ir.ui.view">
<field name="name">pos.payment.method.cashdro.allow.manual.form</field>
<field name="model">pos.payment.method</field>
<field name="inherit_id" ref="pos_payment_method_cashdro.pos_payment_method_view_form"/>
<field name="arch" type="xml">
<field name="cashdro_password" position="after">
<field
name="cashdro_allow_manual_amount"
attrs="{'invisible': [('use_payment_terminal', '!=', 'cashdro')]}"
/>
</field>
</field>
</record>
</odoo>