Files
Odoo-Modules/fusion_poynt/static/src/interactions/terminal_payment.js
gsinghpal 0e1aebe60b feat: add Pending status for delivery/technician tasks
- New 'pending' status allows tasks to be created without a schedule,
  acting as a queue for unscheduled work that gets assigned later
- Pending group appears in the Delivery Map sidebar with amber color
- Other modules can create tasks in pending state for scheduling
- scheduled_date no longer required (null for pending tasks)
- New Pending Tasks menu item under Field Service
- Pending filter added to search view

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-24 04:21:05 -05:00

137 lines
4.3 KiB
JavaScript

/** @odoo-module **/
import { _t } from '@web/core/l10n/translation';
import { rpc } from '@web/core/network/rpc';
import { Component, useState } from '@odoo/owl';
export class TerminalPaymentWidget extends Component {
static template = 'fusion_poynt.TerminalPaymentWidget';
static props = {
providerId: { type: Number },
amount: { type: Number },
currency: { type: String },
reference: { type: String },
orderId: { type: String, optional: true },
onComplete: { type: Function, optional: true },
onError: { type: Function, optional: true },
};
setup() {
this.state = useState({
terminals: [],
selectedTerminalId: null,
loading: false,
polling: false,
status: '',
message: '',
});
this._loadTerminals();
}
async _loadTerminals() {
this.state.loading = true;
try {
const result = await rpc('/payment/poynt/terminals', {
provider_id: this.props.providerId,
});
this.state.terminals = result || [];
if (this.state.terminals.length > 0) {
this.state.selectedTerminalId = this.state.terminals[0].id;
}
} catch {
this.state.message = _t('Failed to load terminal devices.');
} finally {
this.state.loading = false;
}
}
onTerminalChange(ev) {
this.state.selectedTerminalId = parseInt(ev.target.value);
}
async onSendToTerminal() {
if (!this.state.selectedTerminalId) {
this.state.message = _t('Please select a terminal.');
return;
}
this.state.loading = true;
this.state.message = '';
try {
const result = await rpc('/payment/poynt/send_to_terminal', {
reference: this.props.reference,
terminal_id: this.state.selectedTerminalId,
poynt_order_id: this.props.orderId || '',
});
if (result.error) {
this.state.message = result.error;
this.state.loading = false;
if (this.props.onError) {
this.props.onError(result.error);
}
return;
}
this.state.polling = true;
this.state.status = _t('Waiting for payment on terminal...');
this._pollStatus(0);
} catch (error) {
this.state.message = error.message || _t('Failed to send payment to terminal.');
this.state.loading = false;
if (this.props.onError) {
this.props.onError(this.state.message);
}
}
}
async _pollStatus(attempt) {
const maxAttempts = 60;
const pollInterval = 3000;
if (attempt >= maxAttempts) {
this.state.polling = false;
this.state.loading = false;
this.state.message = _t('Payment timed out. Please check the terminal.');
if (this.props.onError) {
this.props.onError(this.state.message);
}
return;
}
try {
const result = await rpc('/payment/poynt/terminal_status', {
reference: this.props.reference,
terminal_id: this.state.selectedTerminalId,
});
if (result.status === 'CAPTURED' || result.status === 'AUTHORIZED') {
this.state.polling = false;
this.state.loading = false;
this.state.status = _t('Payment completed!');
if (this.props.onComplete) {
this.props.onComplete(result);
}
return;
}
if (result.status === 'DECLINED' || result.status === 'FAILED') {
this.state.polling = false;
this.state.loading = false;
this.state.message = _t('Payment was declined.');
if (this.props.onError) {
this.props.onError(this.state.message);
}
return;
}
this.state.status = _t('Status: ') + (result.status || _t('Pending'));
} catch {
this.state.status = _t('Checking...');
}
setTimeout(() => this._pollStatus(attempt + 1), pollInterval);
}
}