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>
This commit is contained in:
gsinghpal
2026-02-24 04:21:05 -05:00
parent 84c009416e
commit 0e1aebe60b
26 changed files with 2735 additions and 9 deletions

View File

@@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Inline payment form template for Poynt -->
<template id="inline_form">
<t t-set="inline_form_values"
t-value="provider_sudo._poynt_get_inline_form_values(
amount,
currency,
partner_id,
mode == 'validation',
payment_method_sudo=pm_sudo,
)"
/>
<div name="o_poynt_payment_container"
class="o_poynt_payment_form"
t-att-data-poynt-inline-form-values="inline_form_values">
<!-- Card number input -->
<div class="mb-3">
<label class="form-label" for="poynt_card_number">Card Number</label>
<input type="text" class="form-control"
id="poynt_card_number"
name="card_number"
placeholder="4111 1111 1111 1111"
maxlength="19"
autocomplete="cc-number"
required="required"/>
</div>
<!-- Expiry and CVV row -->
<div class="row mb-3">
<div class="col-6">
<label class="form-label" for="poynt_expiry">Expiry Date</label>
<input type="text" class="form-control"
id="poynt_expiry"
name="expiry"
placeholder="MM/YY"
maxlength="5"
autocomplete="cc-exp"
required="required"/>
</div>
<div class="col-6">
<label class="form-label" for="poynt_cvv">CVV</label>
<input type="password" class="form-control"
id="poynt_cvv"
name="cvv"
placeholder="123"
maxlength="4"
autocomplete="cc-csc"
required="required"/>
</div>
</div>
<!-- Cardholder name -->
<div class="mb-3">
<label class="form-label" for="poynt_cardholder">Cardholder Name</label>
<input type="text" class="form-control"
id="poynt_cardholder"
name="cardholder_name"
placeholder="John Doe"
autocomplete="cc-name"/>
</div>
<!-- Terminal payment option -->
<div class="mb-3 o_poynt_terminal_section" style="display:none;">
<hr/>
<div class="form-check">
<input type="checkbox" class="form-check-input"
id="poynt_use_terminal" name="use_terminal"/>
<label class="form-check-label" for="poynt_use_terminal">
Pay at Terminal
</label>
</div>
<div id="poynt_terminal_select_wrapper" style="display:none;" class="mt-2">
<label class="form-label" for="poynt_terminal_select">Select Terminal</label>
<select class="form-select" id="poynt_terminal_select" name="terminal_id">
</select>
</div>
</div>
</div>
</template>
</odoo>

View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="payment_provider_form" model="ir.ui.view">
<field name="name">Poynt Provider Form</field>
<field name="model">payment.provider</field>
<field name="inherit_id" ref="payment.payment_provider_form"/>
<field name="arch" type="xml">
<group name="provider_credentials" position="inside">
<group invisible="code != 'poynt'" name="poynt_credentials">
<field name="poynt_application_id"
required="code == 'poynt' and state != 'disabled'"
placeholder="urn:aid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"/>
<field name="poynt_private_key"
required="code == 'poynt' and state != 'disabled'"
widget="text"
placeholder="-----BEGIN RSA PRIVATE KEY-----&#10;...&#10;-----END RSA PRIVATE KEY-----"/>
<field name="poynt_business_id"
required="code == 'poynt' and state != 'disabled'"
placeholder="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"/>
<field name="poynt_store_id"
placeholder="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"/>
<label for="poynt_webhook_secret"/>
<div class="o_row" col="2">
<field name="poynt_webhook_secret" password="True"/>
</div>
</group>
</group>
<group name="provider_credentials" position="after">
<group string="Poynt Actions"
invisible="code != 'poynt'" name="poynt_actions"
col="4">
<button string="Test Connection"
type="object"
name="action_poynt_test_connection"
class="btn-primary"
invisible="not poynt_application_id or not poynt_private_key or not poynt_business_id"
colspan="2"/>
<button string="Fetch Terminals"
type="object"
name="action_poynt_fetch_terminals"
class="btn-secondary"
invisible="not poynt_business_id"
colspan="2"/>
</group>
</group>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,110 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Poynt Terminal Tree View -->
<record id="poynt_terminal_view_list" model="ir.ui.view">
<field name="name">poynt.terminal.list</field>
<field name="model">poynt.terminal</field>
<field name="arch" type="xml">
<list string="Poynt Terminals">
<field name="name"/>
<field name="device_id"/>
<field name="serial_number"/>
<field name="provider_id"/>
<field name="store_id_poynt"/>
<field name="status" widget="badge"
decoration-success="status == 'online'"
decoration-danger="status == 'offline'"
decoration-warning="status == 'unknown'"/>
<field name="last_seen"/>
</list>
</field>
</record>
<!-- Poynt Terminal Form View -->
<record id="poynt_terminal_view_form" model="ir.ui.view">
<field name="name">poynt.terminal.form</field>
<field name="model">poynt.terminal</field>
<field name="arch" type="xml">
<form string="Poynt Terminal">
<header>
<button string="Refresh Status"
type="object"
name="action_refresh_status"
class="btn-primary"/>
</header>
<sheet>
<div class="oe_title">
<h1>
<field name="name" placeholder="Terminal Name"/>
</h1>
</div>
<group>
<group string="Device Information">
<field name="device_id"/>
<field name="serial_number"/>
<field name="status" widget="badge"
decoration-success="status == 'online'"
decoration-danger="status == 'offline'"
decoration-warning="status == 'unknown'"/>
<field name="last_seen"/>
</group>
<group string="Configuration">
<field name="provider_id"/>
<field name="store_id_poynt"/>
<field name="active"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<!-- Poynt Terminal Search View -->
<record id="poynt_terminal_view_search" model="ir.ui.view">
<field name="name">poynt.terminal.search</field>
<field name="model">poynt.terminal</field>
<field name="arch" type="xml">
<search string="Poynt Terminals">
<field name="name"/>
<field name="device_id"/>
<field name="serial_number"/>
<field name="provider_id"/>
<filter string="Online" name="online"
domain="[('status', '=', 'online')]"/>
<filter string="Offline" name="offline"
domain="[('status', '=', 'offline')]"/>
<separator/>
<filter string="Status" name="group_status"
context="{'group_by': 'status'}"/>
<filter string="Provider" name="group_provider"
context="{'group_by': 'provider_id'}"/>
</search>
</field>
</record>
<!-- Poynt Terminal Action -->
<record id="action_poynt_terminal" model="ir.actions.act_window">
<field name="name">Poynt Terminals</field>
<field name="res_model">poynt.terminal</field>
<field name="view_mode">list,form</field>
<field name="search_view_id" ref="poynt_terminal_view_search"/>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
No Poynt terminals configured yet.
</p>
<p>
Click "Fetch Terminals" on your Poynt payment provider to sync
terminal devices from the Poynt Cloud, or add one manually.
</p>
</field>
</record>
<!-- Menu entry under Payment Providers -->
<menuitem id="menu_poynt_terminal"
name="Poynt Terminals"
parent="account_payment.payment_provider_menu"
action="action_poynt_terminal"
sequence="30"/>
</odoo>