Tower: unpublish laundry_management — remove source from 19.0 branch
This commit is contained in:
@@ -1,30 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- Hide standard "Register Payment" buttons on laundry invoices.
|
||||
Cashiers must pay via the laundry order wizard, not the invoice form. -->
|
||||
<record id="view_move_form_laundry_inherit" model="ir.ui.view">
|
||||
<field name="name">account.move.form.laundry</field>
|
||||
<field name="model">account.move</field>
|
||||
<field name="inherit_id" ref="account.view_move_form"/>
|
||||
<field name="arch" type="xml">
|
||||
|
||||
<!-- Inject hidden helper field so invisible expressions can reference it -->
|
||||
<xpath expr="//header" position="inside">
|
||||
<field name="is_laundry_invoice" invisible="1"/>
|
||||
</xpath>
|
||||
|
||||
<!-- Primary Pay button (no outstanding) -->
|
||||
<xpath expr="//button[@id='account_invoice_payment_btn']" position="attributes">
|
||||
<attribute name="invisible">is_laundry_invoice or state != 'posted' or payment_state not in ('not_paid', 'partial', 'in_payment') or move_type not in ('out_invoice', 'out_refund', 'in_invoice', 'in_refund', 'out_receipt', 'in_receipt') or invoice_has_outstanding</attribute>
|
||||
</xpath>
|
||||
|
||||
<!-- Secondary Pay button (with outstanding) -->
|
||||
<xpath expr="//button[@id='account_invoice_payment_secondary_btn']" position="attributes">
|
||||
<attribute name="invisible">is_laundry_invoice or state != 'posted' or payment_state not in ('not_paid', 'partial', 'in_payment') or move_type not in ('out_invoice', 'out_refund', 'in_invoice', 'in_refund', 'out_receipt', 'in_receipt') or not invoice_has_outstanding</attribute>
|
||||
</xpath>
|
||||
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,51 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<!-- Views of laundry label -->
|
||||
<template id="laundry_order_label">
|
||||
<t t-call="web.html_container">
|
||||
<t t-foreach="docs" t-as="obj">
|
||||
<t t-call="web.external_layout">
|
||||
<div class="page">
|
||||
<div class="col-xs-4" style="padding:0;">
|
||||
<table style="border: 2px solid black;border-spacing:0;margin-bottom:0;height:122px;"
|
||||
class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th style="text-align: left; vertical-align: middle; padding-left: 15px; font-weight: bold;"
|
||||
colspan="2">
|
||||
<span t-esc="obj.name"/>
|
||||
</th>
|
||||
<th style="text-align: right; vertical-align: middle; padding-right: 15px; font-weight: bold;"
|
||||
colspan="2">
|
||||
<span t-esc="obj.order_date"/>
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="border: 2px solid black;text-align: center; vertical-align: middle;"
|
||||
colspan="2">
|
||||
<span>CUSTOMER</span>
|
||||
</td>
|
||||
<td style="border: 2px solid black;text-align: center; vertical-align: middle;"
|
||||
colspan="2">
|
||||
<span t-esc="obj.partner_id.name"/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
<!-- Report menu of Printing label-->
|
||||
<record id="laundry_label_report" model="ir.actions.report">
|
||||
<field name="name">Laundry Order Label</field>
|
||||
<field name="model">laundry.order</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="report_name">laundry_management.laundry_order_label</field>
|
||||
<field name="report_file">laundry_management.laundry_order_label</field>
|
||||
<field name="binding_model_id" ref="model_laundry_order"/>
|
||||
<field name="binding_type">report</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -1,252 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════════
|
||||
COMMISSION — Form View (PART 3: 3-state workflow)
|
||||
═══════════════════════════════════════════════════════════════ -->
|
||||
<record id="view_laundry_commission_form" model="ir.ui.view">
|
||||
<field name="name">laundry.commission.form</field>
|
||||
<field name="model">laundry.commission</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Commission">
|
||||
<header>
|
||||
<button name="action_confirm"
|
||||
string="✓ Confirm Commission"
|
||||
type="object"
|
||||
class="btn-primary"
|
||||
invisible="state != 'pending'"
|
||||
groups="laundry_management.group_laundry_manager"/>
|
||||
<button name="action_mark_paid"
|
||||
string="✓ Mark as Paid"
|
||||
type="object"
|
||||
class="btn-success"
|
||||
invisible="state == 'paid'"/>
|
||||
<button name="action_reset_pending"
|
||||
string="↩ Reset to Pending"
|
||||
type="object"
|
||||
invisible="state == 'paid' or state == 'pending'"
|
||||
groups="laundry_management.group_laundry_manager"/>
|
||||
<field name="state"
|
||||
widget="statusbar"
|
||||
statusbar_visible="pending,confirmed,paid"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<div class="oe_title">
|
||||
<h1><field name="name" readonly="1"/></h1>
|
||||
</div>
|
||||
<group>
|
||||
<group string="Staff & Role / الموظف والدور">
|
||||
<field name="order_id"
|
||||
options="{'no_create_edit': True}"/>
|
||||
<field name="employee_id"
|
||||
options="{'no_create_edit': True}"/>
|
||||
<field name="role"
|
||||
widget="badge"
|
||||
decoration-info="role == 'reception'"
|
||||
decoration-warning="role == 'processing'"
|
||||
decoration-success="role == 'delivery'"/>
|
||||
<field name="date"/>
|
||||
</group>
|
||||
<group string="Commission Calculation / حساب العمولة">
|
||||
<field name="commission_type"/>
|
||||
<field name="rate" string="Rate / Amount"/>
|
||||
<field name="base_amount" readonly="1"/>
|
||||
<field name="commission_amount"
|
||||
readonly="1"
|
||||
class="fw-bold fs-5"/>
|
||||
</group>
|
||||
</group>
|
||||
<group>
|
||||
<field name="notes" placeholder="Optional notes…"/>
|
||||
</group>
|
||||
</sheet>
|
||||
<chatter/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════════
|
||||
COMMISSION — List View
|
||||
═══════════════════════════════════════════════════════════════ -->
|
||||
<record id="view_laundry_commission_list" model="ir.ui.view">
|
||||
<field name="name">laundry.commission.list</field>
|
||||
<field name="model">laundry.commission</field>
|
||||
<field name="arch" type="xml">
|
||||
<list string="Commissions"
|
||||
decoration-muted="state == 'paid'"
|
||||
decoration-info="state == 'confirmed'"
|
||||
decoration-warning="state == 'pending'">
|
||||
<field name="name"/>
|
||||
<field name="order_id"/>
|
||||
<field name="employee_id"/>
|
||||
<field name="role"
|
||||
widget="badge"
|
||||
decoration-info="role == 'reception'"
|
||||
decoration-warning="role == 'processing'"
|
||||
decoration-success="role == 'delivery'"/>
|
||||
<field name="date"/>
|
||||
<field name="commission_type" optional="show"/>
|
||||
<field name="rate" optional="show"/>
|
||||
<field name="base_amount" optional="show"/>
|
||||
<field name="commission_amount" sum="Total Commission"/>
|
||||
<field name="state"
|
||||
widget="badge"
|
||||
decoration-warning="state == 'pending'"
|
||||
decoration-info="state == 'confirmed'"
|
||||
decoration-success="state == 'paid'"/>
|
||||
<!-- Quick actions -->
|
||||
<button name="action_confirm"
|
||||
string="Confirm"
|
||||
type="object"
|
||||
icon="fa-check"
|
||||
invisible="state != 'pending'"
|
||||
title="Confirm commission"
|
||||
groups="laundry_management.group_laundry_manager"/>
|
||||
<button name="action_mark_paid"
|
||||
string="Pay"
|
||||
type="object"
|
||||
icon="fa-check-circle"
|
||||
invisible="state == 'paid'"
|
||||
title="Mark as paid"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════════
|
||||
COMMISSION — Graph View (PART 7)
|
||||
═══════════════════════════════════════════════════════════════ -->
|
||||
<record id="view_laundry_commission_graph" model="ir.ui.view">
|
||||
<field name="name">laundry.commission.graph</field>
|
||||
<field name="model">laundry.commission</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Commission Analysis" type="bar">
|
||||
<field name="employee_id" type="row"/>
|
||||
<field name="commission_amount" type="measure"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════════
|
||||
COMMISSION — Pivot View (PART 7)
|
||||
═══════════════════════════════════════════════════════════════ -->
|
||||
<record id="view_laundry_commission_pivot" model="ir.ui.view">
|
||||
<field name="name">laundry.commission.pivot</field>
|
||||
<field name="model">laundry.commission</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Commission Analysis">
|
||||
<field name="employee_id" type="row"/>
|
||||
<field name="role" type="col"/>
|
||||
<field name="commission_amount" type="measure"/>
|
||||
<field name="base_amount" type="measure"/>
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════════
|
||||
COMMISSION — Search View
|
||||
═══════════════════════════════════════════════════════════════ -->
|
||||
<record id="view_laundry_commission_search" model="ir.ui.view">
|
||||
<field name="name">laundry.commission.search</field>
|
||||
<field name="model">laundry.commission</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Commissions">
|
||||
<field name="name" string="Reference"/>
|
||||
<field name="order_id" string="Order"/>
|
||||
<field name="employee_id" string="Staff Member"/>
|
||||
<!-- State filters -->
|
||||
<filter string="Pending"
|
||||
name="pending"
|
||||
domain="[('state','=','pending')]"/>
|
||||
<filter string="Confirmed"
|
||||
name="confirmed"
|
||||
domain="[('state','=','confirmed')]"/>
|
||||
<filter string="Paid"
|
||||
name="paid"
|
||||
domain="[('state','=','paid')]"/>
|
||||
<!-- Unpaid (pending + confirmed) -->
|
||||
<filter string="Unpaid / Unsettled"
|
||||
name="unpaid"
|
||||
domain="[('state','!=','paid')]"/>
|
||||
<separator/>
|
||||
<!-- Date filters -->
|
||||
<filter string="This Month"
|
||||
name="this_month"
|
||||
domain="[('date','>=',context_today().strftime('%Y-%m-01'))]"/>
|
||||
<filter string="Today"
|
||||
name="today"
|
||||
domain="[('date','=',context_today().strftime('%Y-%m-%d'))]"/>
|
||||
<separator/>
|
||||
<!-- Role filters -->
|
||||
<filter string="Reception"
|
||||
name="reception"
|
||||
domain="[('role','=','reception')]"/>
|
||||
<filter string="Processing"
|
||||
name="processing"
|
||||
domain="[('role','=','processing')]"/>
|
||||
<filter string="Delivery"
|
||||
name="delivery"
|
||||
domain="[('role','=','delivery')]"/>
|
||||
<!-- Group-by -->
|
||||
<separator/>
|
||||
<filter string="By Staff"
|
||||
name="by_employee"
|
||||
context="{'group_by':'employee_id'}"/>
|
||||
<filter string="By Role"
|
||||
name="by_role"
|
||||
context="{'group_by':'role'}"/>
|
||||
<filter string="By Status"
|
||||
name="by_state"
|
||||
context="{'group_by':'state'}"/>
|
||||
<filter string="By Order"
|
||||
name="by_order"
|
||||
context="{'group_by':'order_id'}"/>
|
||||
<filter string="By Month"
|
||||
name="by_month"
|
||||
context="{'group_by':'date:month'}"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════════
|
||||
ACTIONS
|
||||
═══════════════════════════════════════════════════════════════ -->
|
||||
<record id="action_laundry_commission" model="ir.actions.act_window">
|
||||
<field name="name">Staff Commissions / العمولات</field>
|
||||
<field name="res_model">laundry.commission</field>
|
||||
<field name="view_mode">list,graph,pivot,form</field>
|
||||
<field name="search_view_id" ref="view_laundry_commission_search"/>
|
||||
<field name="context">{'search_default_unpaid': 1}</field>
|
||||
<field name="view_ids" eval="[
|
||||
(5, 0, 0),
|
||||
(0, 0, {'view_mode': 'list', 'view_id': ref('view_laundry_commission_list')}),
|
||||
(0, 0, {'view_mode': 'graph', 'view_id': ref('view_laundry_commission_graph')}),
|
||||
(0, 0, {'view_mode': 'pivot', 'view_id': ref('view_laundry_commission_pivot')}),
|
||||
(0, 0, {'view_mode': 'form', 'view_id': ref('view_laundry_commission_form')}),
|
||||
]"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
No commissions yet.
|
||||
</p>
|
||||
<p>
|
||||
Enable commission tracking in
|
||||
<strong>Laundry → Configuration → Settings</strong>
|
||||
and set commission rates for each stage.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_laundry_commission_all" model="ir.actions.act_window">
|
||||
<field name="name">All Commissions</field>
|
||||
<field name="res_model">laundry.commission</field>
|
||||
<field name="view_mode">list,graph,pivot,form</field>
|
||||
<field name="search_view_id" ref="view_laundry_commission_search"/>
|
||||
<field name="view_ids" eval="[
|
||||
(5, 0, 0),
|
||||
(0, 0, {'view_mode': 'list', 'view_id': ref('view_laundry_commission_list')}),
|
||||
(0, 0, {'view_mode': 'graph', 'view_id': ref('view_laundry_commission_graph')}),
|
||||
(0, 0, {'view_mode': 'pivot', 'view_id': ref('view_laundry_commission_pivot')}),
|
||||
(0, 0, {'view_mode': 'form', 'view_id': ref('view_laundry_commission_form')}),
|
||||
]"/>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,277 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════════
|
||||
LAUNDRY DASHBOARD — KPI Form View
|
||||
Opened via server action so data is always fresh.
|
||||
═══════════════════════════════════════════════════════════════ -->
|
||||
<record id="view_laundry_dashboard_form" model="ir.ui.view">
|
||||
<field name="name">laundry.dashboard.form</field>
|
||||
<field name="model">laundry.dashboard</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Laundry Dashboard" create="false" edit="false" delete="false">
|
||||
<sheet>
|
||||
|
||||
<!-- ── Header toolbar ─────────────────────────────── -->
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<h2 class="mb-0">Laundry Dashboard</h2>
|
||||
<div class="d-flex gap-2">
|
||||
<button name="action_refresh"
|
||||
string="Refresh"
|
||||
type="object"
|
||||
class="btn btn-sm btn-secondary"/>
|
||||
<button name="action_new_order"
|
||||
string="+ New Order"
|
||||
type="object"
|
||||
class="btn btn-sm btn-primary"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── Session banner ─────────────────────────────── -->
|
||||
<div class="alert alert-success mb-3"
|
||||
role="alert"
|
||||
invisible="not session_is_open">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<strong>Session Open: </strong>
|
||||
<field name="session_name" readonly="1" class="d-inline fw-bold"/>
|
||||
 | 
|
||||
Opening Float:
|
||||
<field name="session_opening_cash" readonly="1"
|
||||
widget="monetary"
|
||||
options="{'currency_field': 'currency_id'}"
|
||||
class="d-inline"/>
|
||||
 | 
|
||||
Session Sales:
|
||||
<field name="session_sales" readonly="1"
|
||||
widget="monetary"
|
||||
options="{'currency_field': 'currency_id'}"
|
||||
class="d-inline fw-bold text-success"/>
|
||||
</div>
|
||||
<button name="action_open_session"
|
||||
string="View Session"
|
||||
type="object"
|
||||
class="btn btn-sm btn-success"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="alert alert-warning mb-3"
|
||||
role="alert"
|
||||
invisible="session_is_open">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<span>
|
||||
<strong>No Active Session</strong> —
|
||||
Open a session before creating orders.
|
||||
</span>
|
||||
<button name="action_new_session"
|
||||
string="Open Session"
|
||||
type="object"
|
||||
class="btn btn-sm btn-warning"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── Today KPI row ──────────────────────────────── -->
|
||||
<div class="row g-3 mb-4">
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center border-primary h-100">
|
||||
<div class="card-body">
|
||||
<div class="display-6 fw-bold text-primary">
|
||||
<field name="today_orders" readonly="1"/>
|
||||
</div>
|
||||
<div class="text-muted small mt-1">Today's Orders</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center border-success h-100">
|
||||
<div class="card-body">
|
||||
<div class="display-6 fw-bold text-success">
|
||||
<field name="today_revenue" readonly="1"
|
||||
widget="monetary"
|
||||
options="{'currency_field': 'currency_id'}"/>
|
||||
</div>
|
||||
<div class="text-muted small mt-1">Today's Revenue</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center border-info h-100">
|
||||
<div class="card-body">
|
||||
<div class="display-6 fw-bold text-info">
|
||||
<field name="today_collected" readonly="1"
|
||||
widget="monetary"
|
||||
options="{'currency_field': 'currency_id'}"/>
|
||||
</div>
|
||||
<div class="text-muted small mt-1">Collected Today</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center border-danger h-100">
|
||||
<div class="card-body">
|
||||
<div class="display-6 fw-bold text-danger">
|
||||
<field name="today_outstanding" readonly="1"
|
||||
widget="monetary"
|
||||
options="{'currency_field': 'currency_id'}"/>
|
||||
</div>
|
||||
<div class="text-muted small mt-1">Outstanding Today</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── Operations Pipeline ────────────────────────── -->
|
||||
<h5 class="mb-3 border-bottom pb-2">Operations Pipeline</h5>
|
||||
<div class="row g-3 mb-4">
|
||||
<div class="col-md-3">
|
||||
<div class="card h-100 bg-success bg-opacity-10 border-success">
|
||||
<div class="card-body text-center">
|
||||
<div class="fs-2 fw-bold text-success">
|
||||
<field name="ready_count" readonly="1"/>
|
||||
</div>
|
||||
<div class="small text-success fw-semibold">Ready for Pickup</div>
|
||||
<button name="action_view_ready_orders"
|
||||
string="View"
|
||||
type="object"
|
||||
class="btn btn-sm btn-outline-success mt-2"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card h-100 bg-warning bg-opacity-10 border-warning">
|
||||
<div class="card-body text-center">
|
||||
<div class="fs-2 fw-bold text-warning">
|
||||
<field name="in_progress_count" readonly="1"/>
|
||||
</div>
|
||||
<div class="small text-warning fw-semibold">In Processing</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card h-100 bg-secondary bg-opacity-10">
|
||||
<div class="card-body text-center">
|
||||
<div class="fs-2 fw-bold text-secondary">
|
||||
<field name="draft_count" readonly="1"/>
|
||||
</div>
|
||||
<div class="small text-muted">Draft / Quotes</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card h-100">
|
||||
<div class="card-body text-center">
|
||||
<div class="fs-2 fw-bold">
|
||||
<field name="pending_count" readonly="1"/>
|
||||
</div>
|
||||
<div class="small text-muted">Total Pending</div>
|
||||
<button name="action_view_pending_orders"
|
||||
string="View All"
|
||||
type="object"
|
||||
class="btn btn-sm btn-outline-secondary mt-2"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── Session breakdown (if open) ────────────────── -->
|
||||
<div invisible="not session_is_open">
|
||||
<h5 class="mb-3 border-bottom pb-2">Current Session Breakdown</h5>
|
||||
<div class="row g-3 mb-4">
|
||||
<div class="col-md-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<div class="small text-muted">Total Session Sales</div>
|
||||
<div class="fs-4 fw-bold">
|
||||
<field name="session_sales" readonly="1"
|
||||
widget="monetary"
|
||||
options="{'currency_field': 'currency_id'}"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<div class="small text-muted">Cash Collected</div>
|
||||
<div class="fs-4 fw-bold text-success">
|
||||
<field name="session_cash" readonly="1"
|
||||
widget="monetary"
|
||||
options="{'currency_field': 'currency_id'}"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<div class="small text-muted">Bank / Card</div>
|
||||
<div class="fs-4 fw-bold text-info">
|
||||
<field name="session_bank" readonly="1"
|
||||
widget="monetary"
|
||||
options="{'currency_field': 'currency_id'}"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── Month summary ──────────────────────────────── -->
|
||||
<h5 class="mb-3 border-bottom pb-2">This Month</h5>
|
||||
<div class="row g-3 mb-2">
|
||||
<div class="col-md-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<div class="small text-muted">Orders This Month</div>
|
||||
<div class="fs-4 fw-bold">
|
||||
<field name="month_orders" readonly="1"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<div class="small text-muted">Revenue This Month</div>
|
||||
<div class="fs-4 fw-bold">
|
||||
<field name="month_revenue" readonly="1"
|
||||
widget="monetary"
|
||||
options="{'currency_field': 'currency_id'}"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<div class="small text-muted">Collected This Month</div>
|
||||
<div class="fs-4 fw-bold text-success">
|
||||
<field name="month_paid" readonly="1"
|
||||
widget="monetary"
|
||||
options="{'currency_field': 'currency_id'}"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- hidden fields needed for widget resolution -->
|
||||
<field name="currency_id" invisible="1"/>
|
||||
<field name="session_is_open" invisible="1"/>
|
||||
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════════
|
||||
SERVER ACTION — creates fresh dashboard record and opens it
|
||||
═══════════════════════════════════════════════════════════════ -->
|
||||
<record id="action_laundry_dashboard_server" model="ir.actions.server">
|
||||
<field name="name">Open Laundry Dashboard</field>
|
||||
<field name="model_id" ref="model_laundry_dashboard"/>
|
||||
<field name="binding_model_id" ref="model_laundry_dashboard"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">action = model.action_open_dashboard()</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,163 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- ROOT ─────────────────────────────────────────────────────── -->
|
||||
<menuitem id="menu_laundry_root"
|
||||
name="Laundry"
|
||||
sequence="60"
|
||||
web_icon="laundry_management,static/description/icon.png"/>
|
||||
|
||||
<!-- DASHBOARD ─────────────────────────────────────────────── -->
|
||||
<!-- Standard Odoo behavior: kanban grouped by state.
|
||||
Real KPI dashboards live inside the Sales / Accounting
|
||||
"Reporting" menus as graph/pivot views (see
|
||||
views/laundry_reporting_views.xml). -->
|
||||
<menuitem id="menu_laundry_dashboard"
|
||||
name="Dashboard"
|
||||
parent="menu_laundry_root"
|
||||
action="action_laundry_dashboard"
|
||||
sequence="5"
|
||||
groups="laundry_management.group_laundry_operator"/>
|
||||
|
||||
<!-- ORDERS ────────────────────────────────────────────────── -->
|
||||
<menuitem id="menu_laundry_orders"
|
||||
name="Orders"
|
||||
parent="menu_laundry_root"
|
||||
sequence="10"
|
||||
groups="laundry_management.group_laundry_operator"/>
|
||||
|
||||
<menuitem id="menu_laundry_all_orders"
|
||||
name="All Orders"
|
||||
parent="menu_laundry_orders"
|
||||
action="action_laundry_order"
|
||||
sequence="10"
|
||||
groups="laundry_management.group_laundry_operator"/>
|
||||
|
||||
<menuitem id="menu_laundry_ready"
|
||||
name="Ready for Pickup"
|
||||
parent="menu_laundry_orders"
|
||||
action="action_laundry_ready_orders"
|
||||
sequence="30"
|
||||
groups="laundry_management.group_laundry_operator"/>
|
||||
|
||||
<menuitem id="menu_laundry_items"
|
||||
name="Items (Tracking)"
|
||||
parent="menu_laundry_orders"
|
||||
action="action_laundry_items"
|
||||
sequence="40"
|
||||
groups="laundry_management.group_laundry_operator"/>
|
||||
|
||||
<!-- UNPAID ─────────────────────────────────────────────── -->
|
||||
<menuitem id="menu_laundry_unpaid"
|
||||
name="Unpaid"
|
||||
parent="menu_laundry_root"
|
||||
sequence="20"
|
||||
groups="laundry_management.group_laundry_cashier"/>
|
||||
|
||||
<menuitem id="menu_laundry_unpaid_orders"
|
||||
name="Unpaid Orders"
|
||||
parent="menu_laundry_unpaid"
|
||||
action="action_laundry_unpaid_orders"
|
||||
sequence="10"
|
||||
groups="laundry_management.group_laundry_cashier"/>
|
||||
|
||||
<menuitem id="menu_laundry_unpaid_customers"
|
||||
name="Unpaid Customers"
|
||||
parent="menu_laundry_unpaid"
|
||||
action="action_laundry_unpaid_customers"
|
||||
sequence="20"
|
||||
groups="laundry_management.group_laundry_cashier"/>
|
||||
|
||||
<!-- 3. CUSTOMERS ─────────────────────────────────────────────── -->
|
||||
<menuitem id="menu_laundry_customers"
|
||||
name="Customers"
|
||||
parent="menu_laundry_root"
|
||||
action="base.action_partner_form"
|
||||
sequence="30"
|
||||
groups="laundry_management.group_laundry_cashier"/>
|
||||
|
||||
<!-- 4. PRODUCTS ──────────────────────────────────────────────── -->
|
||||
<menuitem id="menu_laundry_products"
|
||||
name="Services"
|
||||
parent="menu_laundry_root"
|
||||
sequence="40"
|
||||
groups="laundry_management.group_laundry_manager"/>
|
||||
|
||||
<menuitem id="menu_laundry_product_services"
|
||||
name="Service Catalog"
|
||||
parent="menu_laundry_products"
|
||||
action="action_laundry_product_catalog"
|
||||
sequence="10"
|
||||
groups="laundry_management.group_laundry_manager"/>
|
||||
|
||||
<menuitem id="menu_laundry_product_categories"
|
||||
name="Service Categories"
|
||||
parent="menu_laundry_products"
|
||||
action="product.product_category_action_form"
|
||||
sequence="20"
|
||||
groups="laundry_management.group_laundry_manager"/>
|
||||
|
||||
<!-- 5. REPORTS ───────────────────────────────────────────────── -->
|
||||
<menuitem id="menu_laundry_reports"
|
||||
name="Reports"
|
||||
parent="menu_laundry_root"
|
||||
sequence="50"
|
||||
groups="laundry_management.group_laundry_manager"/>
|
||||
|
||||
<menuitem id="menu_laundry_report_orders"
|
||||
name="Orders Analysis"
|
||||
parent="menu_laundry_reports"
|
||||
action="action_laundry_order"
|
||||
sequence="10"
|
||||
groups="laundry_management.group_laundry_manager"/>
|
||||
|
||||
<menuitem id="menu_laundry_report_commissions"
|
||||
name="Commissions"
|
||||
parent="menu_laundry_reports"
|
||||
action="action_laundry_commission_all"
|
||||
sequence="20"
|
||||
groups="laundry_management.group_laundry_manager"/>
|
||||
|
||||
<!-- 6. CONFIGURATION ─────────────────────────────────────────── -->
|
||||
<menuitem id="menu_laundry_config"
|
||||
name="Configuration"
|
||||
parent="menu_laundry_root"
|
||||
sequence="90"
|
||||
groups="laundry_management.group_laundry_manager"/>
|
||||
|
||||
<menuitem id="menu_laundry_settings"
|
||||
name="Settings"
|
||||
parent="menu_laundry_config"
|
||||
action="action_laundry_settings"
|
||||
sequence="5"
|
||||
groups="laundry_management.group_laundry_manager"/>
|
||||
|
||||
<menuitem id="menu_laundry_payment_methods"
|
||||
name="Payment Methods"
|
||||
parent="menu_laundry_config"
|
||||
action="action_laundry_payment_method"
|
||||
sequence="10"
|
||||
groups="laundry_management.group_laundry_manager"/>
|
||||
|
||||
<menuitem id="menu_laundry_commissions_config"
|
||||
name="Commissions"
|
||||
parent="menu_laundry_config"
|
||||
action="action_laundry_commission"
|
||||
sequence="20"
|
||||
groups="laundry_management.group_laundry_manager"/>
|
||||
|
||||
<menuitem id="menu_laundry_order_types"
|
||||
name="Order Types"
|
||||
parent="menu_laundry_config"
|
||||
action="action_laundry_order_type"
|
||||
sequence="30"
|
||||
groups="laundry_management.group_laundry_manager"/>
|
||||
|
||||
<menuitem id="menu_laundry_order_attributes"
|
||||
name="Order Attributes"
|
||||
parent="menu_laundry_config"
|
||||
action="action_laundry_order_attribute"
|
||||
sequence="40"
|
||||
groups="laundry_management.group_laundry_manager"/>
|
||||
|
||||
</odoo>
|
||||
@@ -1,68 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="view_laundry_order_attribute_list" model="ir.ui.view">
|
||||
<field name="name">laundry.order.attribute.list</field>
|
||||
<field name="model">laundry.order.attribute</field>
|
||||
<field name="arch" type="xml">
|
||||
<list string="Order Attributes" editable="bottom">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="name"/>
|
||||
<field name="code"/>
|
||||
<field name="is_priority_related"/>
|
||||
<field name="is_delivery_related"/>
|
||||
<field name="pos_available"/>
|
||||
<field name="active" widget="boolean_toggle"/>
|
||||
<field name="company_id" groups="base.group_multi_company" optional="hide"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_laundry_order_attribute_form" model="ir.ui.view">
|
||||
<field name="name">laundry.order.attribute.form</field>
|
||||
<field name="model">laundry.order.attribute</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Order Attribute">
|
||||
<sheet>
|
||||
<widget name="web_ribbon" title="Archived" bg_color="bg-danger"
|
||||
invisible="active"/>
|
||||
<field name="active" invisible="1"/>
|
||||
<field name="icon_image" widget="image" class="oe_avatar"/>
|
||||
<div class="oe_title">
|
||||
<label for="name"/>
|
||||
<h1><field name="name" placeholder="e.g. Urgent"/></h1>
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="code"/>
|
||||
<field name="sequence"/>
|
||||
<field name="color" widget="color"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="is_priority_related"/>
|
||||
<field name="is_delivery_related"/>
|
||||
<field name="pos_available"/>
|
||||
<field name="extra_price"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
</group>
|
||||
<group>
|
||||
<field name="description" nolabel="1"/>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_laundry_order_attribute" model="ir.actions.act_window">
|
||||
<field name="name">Order Attributes</field>
|
||||
<field name="res_model">laundry.order.attribute</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">Configure laundry order attributes</p>
|
||||
<p>Attributes are optional per-order tags (Urgent, Fold, Hanger, Delicate...).
|
||||
Use the semantic flags to drive behavior without hardcoding names.</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,108 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="view_laundry_order_type_list" model="ir.ui.view">
|
||||
<field name="name">laundry.order.type.list</field>
|
||||
<field name="model">laundry.order.type</field>
|
||||
<field name="arch" type="xml">
|
||||
<list string="Order Types">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="name"/>
|
||||
<field name="code"/>
|
||||
<field name="priority"/>
|
||||
<field name="is_delivery"/>
|
||||
<field name="requires_address"/>
|
||||
<field name="requires_scheduled_time"/>
|
||||
<field name="pos_available"/>
|
||||
<field name="active" widget="boolean_toggle"/>
|
||||
<field name="company_id" groups="base.group_multi_company" optional="hide"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_laundry_order_type_form" model="ir.ui.view">
|
||||
<field name="name">laundry.order.type.form</field>
|
||||
<field name="model">laundry.order.type</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Order Type">
|
||||
<sheet>
|
||||
<widget name="web_ribbon" title="Archived" bg_color="bg-danger"
|
||||
invisible="active"/>
|
||||
<field name="active" invisible="1"/>
|
||||
<field name="icon_image" widget="image" class="oe_avatar"/>
|
||||
<div class="oe_title">
|
||||
<label for="name"/>
|
||||
<h1><field name="name" placeholder="e.g. Express"/></h1>
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="code"/>
|
||||
<field name="sequence"/>
|
||||
<field name="priority"/>
|
||||
<field name="color" widget="color"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="is_delivery"/>
|
||||
<field name="requires_address"/>
|
||||
<field name="requires_scheduled_time"/>
|
||||
<field name="pos_available"/>
|
||||
<field name="extra_price"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Default Attributes" name="attributes">
|
||||
<field name="attribute_ids" widget="many2many_tags"
|
||||
options="{'color_field': 'color'}"/>
|
||||
</page>
|
||||
<page string="Description" name="description">
|
||||
<field name="description" nolabel="1"
|
||||
placeholder="Shown as a tooltip on the POS card."/>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_laundry_order_type_kanban" model="ir.ui.view">
|
||||
<field name="name">laundry.order.type.kanban</field>
|
||||
<field name="model">laundry.order.type</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban>
|
||||
<field name="name"/>
|
||||
<field name="priority"/>
|
||||
<field name="is_delivery"/>
|
||||
<field name="color"/>
|
||||
<templates>
|
||||
<t t-name="card">
|
||||
<div class="d-flex flex-column gap-1 p-2">
|
||||
<div class="fw-bold fs-5"><field name="name"/></div>
|
||||
<div class="text-muted small">
|
||||
<field name="code"/>
|
||||
</div>
|
||||
<div class="d-flex gap-2 mt-1">
|
||||
<span t-if="record.priority.raw_value === 'urgent'"
|
||||
class="badge bg-danger">Urgent</span>
|
||||
<span t-if="record.is_delivery.raw_value"
|
||||
class="badge bg-info">Delivery</span>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_laundry_order_type" model="ir.actions.act_window">
|
||||
<field name="name">Order Types</field>
|
||||
<field name="res_model">laundry.order.type</field>
|
||||
<field name="view_mode">list,kanban,form</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">Configure laundry order types</p>
|
||||
<p>Examples: Standard, Express, Home Delivery, VIP.
|
||||
Types drive priority, delivery, and workflow hints.</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,686 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- ================================================================
|
||||
POS ORDER — Smart Button to Laundry Order
|
||||
================================================================ -->
|
||||
<record id="view_pos_order_form_laundry_button" model="ir.ui.view">
|
||||
<field name="name">pos.order.form.laundry.button</field>
|
||||
<field name="model">pos.order</field>
|
||||
<field name="inherit_id" ref="point_of_sale.view_pos_pos_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[@name='button_box']" position="inside">
|
||||
<button name="action_open_laundry_order"
|
||||
type="object"
|
||||
class="oe_stat_button"
|
||||
icon="fa-tshirt"
|
||||
invisible="not laundry_order_id">
|
||||
<field name="laundry_order_id" widget="statinfo" string="Laundry"/>
|
||||
</button>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ================================================================
|
||||
LAUNDRY ORDER — Form View
|
||||
================================================================ -->
|
||||
<record id="view_laundry_order_form" model="ir.ui.view">
|
||||
<field name="name">laundry.order.form</field>
|
||||
<field name="model">laundry.order</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Laundry Order" create="0">
|
||||
<header>
|
||||
<button name="action_process"
|
||||
string="Start Processing"
|
||||
type="object"
|
||||
class="btn-primary"
|
||||
invisible="state != 'intake'"/>
|
||||
<button name="action_ready"
|
||||
string="Mark Ready"
|
||||
type="object"
|
||||
class="btn-primary"
|
||||
invisible="state != 'processing'"/>
|
||||
<button name="action_deliver"
|
||||
string="Deliver"
|
||||
type="object"
|
||||
class="btn-success"
|
||||
invisible="state != 'ready'"/>
|
||||
<button name="action_cancel"
|
||||
string="Cancel Order"
|
||||
type="object"
|
||||
class="btn-danger"
|
||||
confirm="Cancel this laundry order? This is permanent."
|
||||
invisible="source_type == 'pos' or state in ('delivered', 'cancelled')"/>
|
||||
<button name="action_open_unlock_wizard"
|
||||
string="Unlock for Editing"
|
||||
type="object"
|
||||
class="btn-warning"
|
||||
icon="fa-unlock-alt"
|
||||
invisible="not locked"
|
||||
groups="laundry_management.group_laundry_manager_override"/>
|
||||
<button name="%(action_report_laundry_work_order)d"
|
||||
string="Print Work Order"
|
||||
type="action"
|
||||
class="btn-secondary"/>
|
||||
<field name="state"
|
||||
widget="statusbar"
|
||||
statusbar_visible="intake,processing,ready,delivered"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<!-- Lock ribbon — visible at a glance whether the order
|
||||
is currently editable. Source + manager-unlock
|
||||
metadata are below in the Order Info group. -->
|
||||
<widget name="web_ribbon" title="Locked"
|
||||
bg_color="text-bg-warning"
|
||||
invisible="not locked"/>
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button name="action_open_pos_order"
|
||||
type="object"
|
||||
class="oe_stat_button"
|
||||
icon="fa-shopping-cart"
|
||||
invisible="not pos_order_id">
|
||||
<span class="o_stat_text">POS Order</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="oe_title">
|
||||
<h1><field name="name" readonly="1"/></h1>
|
||||
</div>
|
||||
<group>
|
||||
<group string="Customer">
|
||||
<field name="partner_id" readonly="locked"/>
|
||||
<field name="partner_phone" readonly="1"/>
|
||||
<field name="pos_reference" readonly="1"
|
||||
invisible="not pos_reference"/>
|
||||
</group>
|
||||
<group string="Order Info">
|
||||
<field name="source_type" readonly="1"/>
|
||||
<field name="is_from_pos" invisible="1"/>
|
||||
<field name="locked" invisible="1"/>
|
||||
<field name="tracking_enabled"
|
||||
readonly="locked"
|
||||
help="Phase-4 prep: per-item tracking will be wired in a follow-up."/>
|
||||
<field name="amount_total" readonly="1"/>
|
||||
<field name="amount_paid" readonly="1"/>
|
||||
<field name="amount_due" readonly="1"/>
|
||||
<field name="item_count" readonly="1"/>
|
||||
<field name="company_id" groups="base.group_multi_company" readonly="1"/>
|
||||
<field name="currency_id" invisible="1"/>
|
||||
<field name="pos_order_id" invisible="1"/>
|
||||
</group>
|
||||
</group>
|
||||
<!-- Manager unlock window — info-only block, visible when
|
||||
a manager has granted a temporary edit window. -->
|
||||
<div class="alert alert-info mt-2"
|
||||
role="alert"
|
||||
invisible="not manager_unlocked_until">
|
||||
<strong>Manager unlock active</strong> until
|
||||
<field name="manager_unlocked_until" readonly="1"
|
||||
class="d-inline-block mx-1"/>
|
||||
by
|
||||
<field name="manager_unlocked_by" readonly="1"
|
||||
class="d-inline-block mx-1"
|
||||
options="{'no_open': True}"/>.
|
||||
Reason: <em><field name="manager_unlock_reason" readonly="1"
|
||||
class="d-inline-block"/></em>
|
||||
</div>
|
||||
<group>
|
||||
<group string="Type & Attributes">
|
||||
<!-- Lock-driven readonly. POS-sourced orders
|
||||
stay readonly until a manager unlock window
|
||||
is active. Manual orders editable until
|
||||
final state. -->
|
||||
<field name="order_type_id" readonly="locked"/>
|
||||
<field name="attribute_ids" widget="many2many_tags"
|
||||
options="{'color_field': 'color'}"
|
||||
readonly="locked"/>
|
||||
<field name="priority_level" widget="badge"
|
||||
decoration-danger="priority_level == 'urgent'"
|
||||
decoration-muted="priority_level == 'normal'"
|
||||
readonly="locked"/>
|
||||
</group>
|
||||
<group string="Delivery">
|
||||
<field name="is_delivery" readonly="locked"/>
|
||||
<field name="delivery_address"
|
||||
invisible="not is_delivery"
|
||||
required="is_delivery and not locked"
|
||||
readonly="locked"/>
|
||||
<field name="delivery_scheduled_at"
|
||||
invisible="not is_delivery"
|
||||
readonly="locked"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Items" name="lines">
|
||||
<!-- Line list is editable only when the order
|
||||
is unlocked (manual + non-final, OR an
|
||||
active manager unlock window). The model
|
||||
layer enforces the same rule independently. -->
|
||||
<field name="line_ids" readonly="locked">
|
||||
<list editable="bottom">
|
||||
<field name="tracking_code" readonly="1"/>
|
||||
<field name="product_id"
|
||||
readonly="parent.locked"/>
|
||||
<field name="description"
|
||||
readonly="parent.locked"/>
|
||||
<field name="qty"
|
||||
readonly="parent.locked"/>
|
||||
<field name="price_unit"
|
||||
readonly="parent.locked"/>
|
||||
<field name="subtotal" readonly="1"/>
|
||||
<field name="customer_note"/>
|
||||
<field name="state" widget="badge"
|
||||
decoration-info="state == 'received'"
|
||||
decoration-warning="state == 'processing'"
|
||||
decoration-primary="state == 'ready'"
|
||||
decoration-success="state == 'delivered'"/>
|
||||
<button name="action_line_process" type="object"
|
||||
string="Process" icon="fa-cog"
|
||||
invisible="state != 'received'"/>
|
||||
<button name="action_line_ready" type="object"
|
||||
string="Ready" icon="fa-check"
|
||||
invisible="state != 'processing'"/>
|
||||
<button name="action_line_deliver" type="object"
|
||||
string="Deliver" icon="fa-truck"
|
||||
invisible="state != 'ready'"/>
|
||||
</list>
|
||||
</field>
|
||||
</page>
|
||||
<page string="Notes" name="notes">
|
||||
<field name="notes" placeholder="Internal notes..."/>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
<chatter/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ================================================================
|
||||
LAUNDRY ORDER — Main List View (with quick-action buttons)
|
||||
================================================================ -->
|
||||
<record id="view_laundry_order_list" model="ir.ui.view">
|
||||
<field name="name">laundry.order.list</field>
|
||||
<field name="model">laundry.order</field>
|
||||
<field name="arch" type="xml">
|
||||
<list string="Laundry Orders" create="0" multi_edit="1"
|
||||
decoration-danger="priority_level == 'urgent'"
|
||||
default_order="priority_level desc, is_delivery desc, create_date desc">
|
||||
<field name="name" string="Order No." readonly="1"/>
|
||||
<field name="partner_id" string="Customer" readonly="1"/>
|
||||
<field name="order_type_id" string="Type" optional="show" readonly="1"/>
|
||||
<field name="attribute_ids" widget="many2many_tags"
|
||||
options="{'color_field': 'color'}"
|
||||
optional="show" readonly="1"/>
|
||||
<field name="priority_level" widget="badge" optional="show"
|
||||
decoration-danger="priority_level == 'urgent'"
|
||||
readonly="1"/>
|
||||
<field name="is_delivery" widget="boolean_toggle"
|
||||
optional="show" readonly="1"/>
|
||||
<field name="delivery_scheduled_at" optional="hide" readonly="1"/>
|
||||
<field name="pos_reference" string="POS Ref" optional="hide" readonly="1"/>
|
||||
<field name="item_count" string="Items" readonly="1"/>
|
||||
<field name="amount_total" string="Total" sum="Total" readonly="1"/>
|
||||
<field name="amount_due" string="Due" optional="show" readonly="1"
|
||||
decoration-danger="amount_due > 0"/>
|
||||
<field name="state" widget="badge" readonly="1"
|
||||
decoration-info="state == 'intake'"
|
||||
decoration-warning="state == 'processing'"
|
||||
decoration-primary="state == 'ready'"
|
||||
decoration-success="state == 'delivered'"
|
||||
decoration-muted="state == 'cancelled'"/>
|
||||
<field name="source_type" optional="hide" readonly="1"/>
|
||||
<field name="locked" widget="boolean_toggle" readonly="1"
|
||||
optional="hide"/>
|
||||
<field name="create_date" string="Date" optional="show" readonly="1"/>
|
||||
<button name="action_process" string="Process"
|
||||
type="object" icon="fa-cog"
|
||||
invisible="state != 'intake'"/>
|
||||
<button name="action_ready" string="Ready"
|
||||
type="object" icon="fa-check"
|
||||
invisible="state != 'processing'"/>
|
||||
<button name="action_deliver" string="Deliver"
|
||||
type="object" icon="fa-truck"
|
||||
invisible="state != 'ready'"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ================================================================
|
||||
LAUNDRY ORDER — Ready for Pickup List (simplified)
|
||||
================================================================ -->
|
||||
<record id="view_laundry_order_ready_list" model="ir.ui.view">
|
||||
<field name="name">laundry.order.ready.list</field>
|
||||
<field name="model">laundry.order</field>
|
||||
<field name="arch" type="xml">
|
||||
<list string="Ready for Pickup" create="0">
|
||||
<field name="name" string="Order No."/>
|
||||
<field name="partner_id" string="Customer"/>
|
||||
<field name="partner_phone" string="Phone"/>
|
||||
<field name="item_count" string="Items"/>
|
||||
<field name="amount_total" string="Total"/>
|
||||
<field name="amount_due" string="Due"
|
||||
decoration-danger="amount_due > 0"/>
|
||||
<button name="action_deliver" string="Deliver Now"
|
||||
type="object" icon="fa-truck"
|
||||
class="btn-success"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ================================================================
|
||||
LAUNDRY ORDER — Operational Control Board (Smart Kanban)
|
||||
================================================================ -->
|
||||
<record id="view_laundry_order_kanban" model="ir.ui.view">
|
||||
<field name="name">laundry.order.kanban</field>
|
||||
<field name="model">laundry.order</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban class="o_kanban_mobile laundry-board" create="0"
|
||||
group_create="0" group_delete="0" group_edit="0"
|
||||
default_group_by="state"
|
||||
default_order="priority_level desc, is_delivery desc, create_date asc">
|
||||
<field name="name"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="state"/>
|
||||
<field name="amount_total"/>
|
||||
<field name="amount_due"/>
|
||||
<field name="item_count"/>
|
||||
<field name="currency_id"/>
|
||||
<field name="order_type_id"/>
|
||||
<field name="priority_level"/>
|
||||
<field name="is_delivery"/>
|
||||
<field name="create_date"/>
|
||||
<field name="amount_deferred"/>
|
||||
<progressbar field="state"
|
||||
colors='{"intake": "info", "processing": "warning", "ready": "success", "delivered": "muted"}'/>
|
||||
<templates>
|
||||
<t t-name="card">
|
||||
<div class="laundry-board__card"
|
||||
t-att-data-priority="record.priority_level.raw_value"
|
||||
t-att-data-state="record.state.raw_value"
|
||||
t-att-data-delivery="record.is_delivery.raw_value ? '1' : '0'">
|
||||
<div class="laundry-board__strip"/>
|
||||
<div class="laundry-board__head">
|
||||
<div class="laundry-board__title-row">
|
||||
<strong class="laundry-board__name">
|
||||
<field name="name"/>
|
||||
</strong>
|
||||
<span class="laundry-board__total">
|
||||
<field name="amount_total" widget="monetary"/>
|
||||
</span>
|
||||
</div>
|
||||
<div class="laundry-board__customer">
|
||||
<i class="fa fa-user-o me-1"/>
|
||||
<field name="partner_id"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="laundry-board__badges">
|
||||
<span t-if="record.priority_level.raw_value === 'urgent'"
|
||||
class="laundry-pill laundry-pill--urgent">
|
||||
<i class="fa fa-bolt me-1"/>Urgent
|
||||
</span>
|
||||
<span t-if="record.is_delivery.raw_value"
|
||||
class="laundry-pill laundry-pill--delivery">
|
||||
<i class="fa fa-truck me-1"/>Delivery
|
||||
</span>
|
||||
<span t-if="record.order_type_id.raw_value"
|
||||
class="laundry-pill laundry-pill--type">
|
||||
<i class="fa fa-tag me-1"/>
|
||||
<field name="order_type_id"/>
|
||||
</span>
|
||||
<span t-if="record.amount_deferred.raw_value > 0"
|
||||
class="laundry-pill laundry-pill--deferred"
|
||||
title="Paid later via Customer Account">
|
||||
<i class="fa fa-hourglass-half me-1"/>Deferred
|
||||
</span>
|
||||
</div>
|
||||
<div class="laundry-board__meta">
|
||||
<span class="laundry-board__items">
|
||||
<i class="fa fa-shopping-bag me-1"/>
|
||||
<field name="item_count"/> items
|
||||
</span>
|
||||
<span t-if="record.amount_due.raw_value > 0"
|
||||
class="laundry-board__due">
|
||||
Due: <field name="amount_due" widget="monetary"/>
|
||||
</span>
|
||||
<span class="laundry-board__time">
|
||||
<i class="fa fa-clock-o me-1"/>
|
||||
<field name="create_date" widget="date"/>
|
||||
</span>
|
||||
</div>
|
||||
<div class="laundry-board__actions">
|
||||
<button t-if="record.state.raw_value == 'intake'"
|
||||
name="action_process" type="object"
|
||||
class="btn btn-sm btn-primary w-100">
|
||||
<i class="fa fa-play me-1"/>Start Processing
|
||||
</button>
|
||||
<button t-if="record.state.raw_value == 'processing'"
|
||||
name="action_ready" type="object"
|
||||
class="btn btn-sm btn-primary w-100">
|
||||
<i class="fa fa-check me-1"/>Mark Ready
|
||||
</button>
|
||||
<button t-if="record.state.raw_value == 'ready'"
|
||||
name="action_deliver" type="object"
|
||||
class="btn btn-sm btn-success w-100">
|
||||
<i class="fa fa-truck me-1"/>Deliver
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ================================================================
|
||||
LAUNDRY ORDER — Search View
|
||||
================================================================ -->
|
||||
<record id="view_laundry_order_search" model="ir.ui.view">
|
||||
<field name="name">laundry.order.search</field>
|
||||
<field name="model">laundry.order</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Laundry Orders">
|
||||
<field name="name" string="Order No."/>
|
||||
<field name="partner_id" string="Customer"/>
|
||||
<field name="pos_reference" string="POS Reference"/>
|
||||
<separator/>
|
||||
<filter string="Intake" name="intake" domain="[('state','=','intake')]"/>
|
||||
<filter string="Processing" name="processing" domain="[('state','=','processing')]"/>
|
||||
<filter string="Ready" name="ready" domain="[('state','=','ready')]"/>
|
||||
<filter string="Delivered" name="delivered" domain="[('state','=','delivered')]"/>
|
||||
<separator/>
|
||||
<filter string="Active" name="active" domain="[('state','!=','delivered')]"/>
|
||||
<filter string="Unpaid" name="unpaid" domain="[('amount_due','>',0)]"/>
|
||||
<filter string="Urgent" name="urgent" domain="[('priority_level','=','urgent')]"/>
|
||||
<filter string="Delivery" name="delivery" domain="[('is_delivery','=',True)]"/>
|
||||
<separator/>
|
||||
<filter string="By Status" name="by_state" context="{'group_by':'state'}"/>
|
||||
<filter string="By Customer" name="by_customer" context="{'group_by':'partner_id'}"/>
|
||||
<filter string="By Order Type" name="by_order_type" context="{'group_by':'order_type_id'}"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ================================================================
|
||||
ACTIONS
|
||||
================================================================ -->
|
||||
<record id="action_laundry_order" model="ir.actions.act_window">
|
||||
<field name="name">Laundry Orders</field>
|
||||
<field name="res_model">laundry.order</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="context">{'search_default_active': 1}</field>
|
||||
<field name="view_ids" eval="[
|
||||
(5, 0, 0),
|
||||
(0, 0, {'view_mode': 'list', 'view_id': ref('view_laundry_order_list')}),
|
||||
(0, 0, {'view_mode': 'form', 'view_id': ref('view_laundry_order_form')}),
|
||||
]"/>
|
||||
<field name="search_view_id" ref="view_laundry_order_search"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
No laundry orders yet.
|
||||
</p>
|
||||
<p>Orders are created automatically from POS.</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_laundry_ready_orders" model="ir.actions.act_window">
|
||||
<field name="name">Ready for Pickup</field>
|
||||
<field name="res_model">laundry.order</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="domain">[('state','=','ready')]</field>
|
||||
<field name="view_ids" eval="[
|
||||
(5, 0, 0),
|
||||
(0, 0, {'view_mode': 'list', 'view_id': ref('view_laundry_order_ready_list')}),
|
||||
(0, 0, {'view_mode': 'form', 'view_id': ref('view_laundry_order_form')}),
|
||||
]"/>
|
||||
<field name="search_view_id" ref="view_laundry_order_search"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
No orders ready for pickup.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Dashboard: kanban grouped by state -->
|
||||
<record id="action_laundry_dashboard" model="ir.actions.act_window">
|
||||
<field name="name">Operations Dashboard</field>
|
||||
<field name="res_model">laundry.order</field>
|
||||
<field name="view_mode">kanban,list,form</field>
|
||||
<field name="context">{'search_default_active': 1}</field>
|
||||
<field name="view_ids" eval="[
|
||||
(5, 0, 0),
|
||||
(0, 0, {'view_mode': 'kanban', 'view_id': ref('view_laundry_order_kanban')}),
|
||||
(0, 0, {'view_mode': 'list', 'view_id': ref('view_laundry_order_list')}),
|
||||
(0, 0, {'view_mode': 'form', 'view_id': ref('view_laundry_order_form')}),
|
||||
]"/>
|
||||
<field name="search_view_id" ref="view_laundry_order_search"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
No active orders.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Unpaid orders -->
|
||||
<record id="action_laundry_unpaid_orders" model="ir.actions.act_window">
|
||||
<field name="name">Unpaid Orders</field>
|
||||
<field name="res_model">laundry.order</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="domain">[('amount_due', '>', 0)]</field>
|
||||
<field name="view_ids" eval="[
|
||||
(5, 0, 0),
|
||||
(0, 0, {'view_mode': 'list', 'view_id': ref('view_laundry_order_list')}),
|
||||
(0, 0, {'view_mode': 'form', 'view_id': ref('view_laundry_order_form')}),
|
||||
]"/>
|
||||
<field name="search_view_id" ref="view_laundry_order_search"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">All orders are fully paid!</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Unpaid customers -->
|
||||
<record id="action_laundry_unpaid_customers" model="ir.actions.act_window">
|
||||
<field name="name">Unpaid Customers</field>
|
||||
<field name="res_model">laundry.order</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="domain">[('amount_due', '>', 0)]</field>
|
||||
<field name="context">{'search_default_by_customer': 1}</field>
|
||||
<field name="view_ids" eval="[
|
||||
(5, 0, 0),
|
||||
(0, 0, {'view_mode': 'list', 'view_id': ref('view_laundry_order_list')}),
|
||||
(0, 0, {'view_mode': 'form', 'view_id': ref('view_laundry_order_form')}),
|
||||
]"/>
|
||||
<field name="search_view_id" ref="view_laundry_order_search"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">No customers with unpaid orders!</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ================================================================
|
||||
LAUNDRY ITEM (line-level) — Tracking views
|
||||
================================================================ -->
|
||||
<record id="view_laundry_order_line_search" model="ir.ui.view">
|
||||
<field name="name">laundry.order.line.search</field>
|
||||
<field name="model">laundry.order.line</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Items">
|
||||
<field name="tracking_code"/>
|
||||
<field name="order_id"/>
|
||||
<field name="order_partner_id" string="Customer"/>
|
||||
<field name="product_id"/>
|
||||
<separator/>
|
||||
<filter string="Received" name="received" domain="[('state','=','received')]"/>
|
||||
<filter string="Processing" name="processing" domain="[('state','=','processing')]"/>
|
||||
<filter string="Ready" name="ready" domain="[('state','=','ready')]"/>
|
||||
<filter string="Delivered" name="delivered" domain="[('state','=','delivered')]"/>
|
||||
<separator/>
|
||||
<filter string="Active" name="active" domain="[('state','!=','delivered')]"/>
|
||||
<separator/>
|
||||
<filter string="By Status" name="by_state" context="{'group_by':'state'}"/>
|
||||
<filter string="By Customer" name="by_customer" context="{'group_by':'order_partner_id'}"/>
|
||||
<filter string="By Order" name="by_order" context="{'group_by':'order_id'}"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_laundry_order_line_list" model="ir.ui.view">
|
||||
<field name="name">laundry.order.line.list</field>
|
||||
<field name="model">laundry.order.line</field>
|
||||
<field name="arch" type="xml">
|
||||
<list string="Laundry Items" create="0" edit="0">
|
||||
<field name="tracking_code" readonly="1"/>
|
||||
<field name="order_id" readonly="1"/>
|
||||
<field name="order_partner_id" string="Customer" readonly="1"/>
|
||||
<field name="product_id" readonly="1"/>
|
||||
<field name="qty" readonly="1"/>
|
||||
<field name="state" widget="badge" readonly="1"
|
||||
decoration-info="state == 'received'"
|
||||
decoration-warning="state == 'processing'"
|
||||
decoration-primary="state == 'ready'"
|
||||
decoration-success="state == 'delivered'"/>
|
||||
<button name="action_line_process" string="Process"
|
||||
type="object" icon="fa-cog"
|
||||
invisible="state != 'received'"/>
|
||||
<button name="action_line_ready" string="Ready"
|
||||
type="object" icon="fa-check"
|
||||
invisible="state != 'processing'"/>
|
||||
<button name="action_line_deliver" string="Deliver"
|
||||
type="object" icon="fa-truck"
|
||||
invisible="state != 'ready'"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_laundry_order_line_kanban" model="ir.ui.view">
|
||||
<field name="name">laundry.order.line.kanban</field>
|
||||
<field name="model">laundry.order.line</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban class="laundry-board" default_group_by="state"
|
||||
create="0" group_create="0" group_delete="0" group_edit="0">
|
||||
<field name="tracking_code"/>
|
||||
<field name="product_id"/>
|
||||
<field name="order_id"/>
|
||||
<field name="order_partner_id"/>
|
||||
<field name="qty"/>
|
||||
<field name="state"/>
|
||||
<progressbar field="state"
|
||||
colors='{"received": "info", "processing": "warning", "ready": "success", "delivered": "muted"}'/>
|
||||
<templates>
|
||||
<t t-name="card">
|
||||
<div class="laundry-board__card" t-att-data-state="record.state.raw_value">
|
||||
<div class="laundry-board__strip"/>
|
||||
<div class="laundry-board__head">
|
||||
<div class="laundry-board__title-row">
|
||||
<strong class="laundry-board__name">
|
||||
<field name="tracking_code"/>
|
||||
</strong>
|
||||
<span class="laundry-board__total">
|
||||
x<field name="qty"/>
|
||||
</span>
|
||||
</div>
|
||||
<div class="laundry-board__customer">
|
||||
<i class="fa fa-tag me-1" title="Product"/>
|
||||
<field name="product_id"/>
|
||||
</div>
|
||||
<div class="laundry-board__customer">
|
||||
<i class="fa fa-user-o me-1" title="Customer"/>
|
||||
<field name="order_partner_id"/>
|
||||
 · 
|
||||
<field name="order_id"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="laundry-board__actions">
|
||||
<button t-if="record.state.raw_value == 'received'"
|
||||
name="action_line_process" type="object"
|
||||
class="btn btn-sm btn-primary w-100">
|
||||
<i class="fa fa-play me-1"/>Start Processing
|
||||
</button>
|
||||
<button t-if="record.state.raw_value == 'processing'"
|
||||
name="action_line_ready" type="object"
|
||||
class="btn btn-sm btn-primary w-100">
|
||||
<i class="fa fa-check me-1"/>Mark Ready
|
||||
</button>
|
||||
<button t-if="record.state.raw_value == 'ready'"
|
||||
name="action_line_deliver" type="object"
|
||||
class="btn btn-sm btn-success w-100">
|
||||
<i class="fa fa-truck me-1"/>Deliver
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_laundry_items" model="ir.actions.act_window">
|
||||
<field name="name">Laundry Items</field>
|
||||
<field name="res_model">laundry.order.line</field>
|
||||
<field name="view_mode">kanban,list</field>
|
||||
<field name="context">{'search_default_active': 1}</field>
|
||||
<field name="search_view_id" ref="view_laundry_order_line_search"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">No items yet.</p>
|
||||
<p>Items appear here once an order is created from POS.</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ================================================================
|
||||
SERVICE CATALOG
|
||||
================================================================ -->
|
||||
<record id="action_laundry_product_catalog" model="ir.actions.act_window">
|
||||
<field name="name">Service Catalog</field>
|
||||
<field name="res_model">product.template</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="domain">[('is_laundry_service','=',True)]</field>
|
||||
<field name="context">{
|
||||
'default_is_laundry_service': True,
|
||||
'default_type': 'service',
|
||||
'default_sale_ok': True,
|
||||
}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Create your first laundry service product.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ================================================================
|
||||
SERVER ACTIONS — Bulk Operations
|
||||
================================================================ -->
|
||||
<record id="action_bulk_process" model="ir.actions.server">
|
||||
<field name="name">Start Processing</field>
|
||||
<field name="model_id" ref="model_laundry_order"/>
|
||||
<field name="binding_model_id" ref="model_laundry_order"/>
|
||||
<field name="binding_view_types">list</field>
|
||||
<field name="state">code</field>
|
||||
<field name="code">
|
||||
if records:
|
||||
records.filtered(lambda o: o.state == 'intake').action_process()
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_bulk_ready" model="ir.actions.server">
|
||||
<field name="name">Mark Ready</field>
|
||||
<field name="model_id" ref="model_laundry_order"/>
|
||||
<field name="binding_model_id" ref="model_laundry_order"/>
|
||||
<field name="binding_view_types">list</field>
|
||||
<field name="state">code</field>
|
||||
<field name="code">
|
||||
if records:
|
||||
records.filtered(lambda o: o.state == 'processing').action_ready()
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_bulk_deliver" model="ir.actions.server">
|
||||
<field name="name">Deliver</field>
|
||||
<field name="model_id" ref="model_laundry_order"/>
|
||||
<field name="binding_model_id" ref="model_laundry_order"/>
|
||||
<field name="binding_view_types">list</field>
|
||||
<field name="state">code</field>
|
||||
<field name="code">
|
||||
if records:
|
||||
records.filtered(lambda o: o.state == 'ready').action_deliver()
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,101 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════════
|
||||
LAUNDRY PAYMENT METHOD — Form View
|
||||
═══════════════════════════════════════════════════════════════ -->
|
||||
<record id="view_laundry_payment_method_form" model="ir.ui.view">
|
||||
<field name="name">laundry.payment.method.form</field>
|
||||
<field name="model">laundry.payment.method</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Payment Method">
|
||||
<sheet>
|
||||
<div class="oe_title">
|
||||
<h1><field name="name" placeholder="e.g. Cash, Visa, Bank Transfer"/></h1>
|
||||
</div>
|
||||
<group>
|
||||
<group string="Method Settings">
|
||||
<field name="payment_type"/>
|
||||
<field name="journal_id"
|
||||
options="{'no_create': True}"
|
||||
invisible="payment_type == 'credit'"
|
||||
required="payment_type in ('cash','bank')"/>
|
||||
<field name="is_default"/>
|
||||
<field name="active"/>
|
||||
</group>
|
||||
<group string="Display">
|
||||
<field name="sequence"/>
|
||||
<field name="company_id"
|
||||
groups="base.group_multi_company"
|
||||
options="{'no_create': True}"/>
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════════
|
||||
LAUNDRY PAYMENT METHOD — List View
|
||||
═══════════════════════════════════════════════════════════════ -->
|
||||
<record id="view_laundry_payment_method_list" model="ir.ui.view">
|
||||
<field name="name">laundry.payment.method.list</field>
|
||||
<field name="model">laundry.payment.method</field>
|
||||
<field name="arch" type="xml">
|
||||
<list string="Payment Methods" editable="top">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="name"/>
|
||||
<field name="payment_type"
|
||||
widget="badge"
|
||||
decoration-success="payment_type == 'cash'"
|
||||
decoration-info="payment_type == 'bank'"
|
||||
decoration-warning="payment_type == 'credit'"/>
|
||||
<field name="journal_id"/>
|
||||
<field name="is_default"/>
|
||||
<field name="active"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════════
|
||||
LAUNDRY PAYMENT METHOD — Search View
|
||||
═══════════════════════════════════════════════════════════════ -->
|
||||
<record id="view_laundry_payment_method_search" model="ir.ui.view">
|
||||
<field name="name">laundry.payment.method.search</field>
|
||||
<field name="model">laundry.payment.method</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Payment Methods">
|
||||
<field name="name" string="Name"/>
|
||||
<filter string="Active" name="active"
|
||||
domain="[('active','=',True)]"/>
|
||||
<filter string="Cash" name="cash"
|
||||
domain="[('payment_type','=','cash')]"/>
|
||||
<filter string="Bank / Card" name="bank"
|
||||
domain="[('payment_type','=','bank')]"/>
|
||||
<filter string="Credit / Deferred" name="credit"
|
||||
domain="[('payment_type','=','credit')]"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════════
|
||||
ACTION
|
||||
═══════════════════════════════════════════════════════════════ -->
|
||||
<record id="action_laundry_payment_method" model="ir.actions.act_window">
|
||||
<field name="name">Payment Methods</field>
|
||||
<field name="res_model">laundry.payment.method</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="search_view_id" ref="view_laundry_payment_method_search"/>
|
||||
<field name="context">{'search_default_active': 1}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
No payment methods configured yet.
|
||||
</p>
|
||||
<p>
|
||||
Create payment methods (Cash, Card, Bank Transfer, Credit)
|
||||
linked to accounting journals for session reconciliation.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,144 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════════
|
||||
LAUNDRY PAYMENT WIZARD — POS-like payment screen (PART 2)
|
||||
Model: laundry.payment.wizard
|
||||
═══════════════════════════════════════════════════════════════ -->
|
||||
<record id="view_laundry_payment_wizard_form" model="ir.ui.view">
|
||||
<field name="name">laundry.payment.wizard.form</field>
|
||||
<field name="model">laundry.payment.wizard</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Register Payment / تسجيل الدفع">
|
||||
<sheet>
|
||||
|
||||
<!-- ── Order / Customer Header ── -->
|
||||
<div class="row mb-3 p-3"
|
||||
style="background:linear-gradient(135deg,#1a73e8,#0d5cb6);
|
||||
border-radius:8px;color:white;">
|
||||
<div class="col-6">
|
||||
<div style="font-size:0.8em;opacity:0.8;">Order / الطلب</div>
|
||||
<div class="fw-bold fs-5">
|
||||
<field name="order_name" readonly="1" class="text-white"/>
|
||||
</div>
|
||||
<div style="font-size:0.85em;opacity:0.9;" class="mt-1">
|
||||
<field name="partner_id" readonly="1" class="text-white"/>
|
||||
</div>
|
||||
<div style="font-size:0.8em;opacity:0.8;" class="mt-1">
|
||||
<field name="mobile" readonly="1" class="text-white"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 text-end">
|
||||
<div style="font-size:0.8em;opacity:0.8;">Processing Status</div>
|
||||
<div class="fw-bold">
|
||||
<field name="laundry_state" readonly="1" class="text-white"/>
|
||||
</div>
|
||||
<div style="font-size:0.8em;opacity:0.8;" class="mt-2">Order Total</div>
|
||||
<div class="fw-bold fs-4">
|
||||
<field name="order_total" readonly="1"
|
||||
widget="monetary"
|
||||
options="{'currency_field': 'currency_id'}"
|
||||
class="text-white"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── Balance Due Banner ── -->
|
||||
<div class="alert mb-3"
|
||||
t-attf-class="alert #{amount_due > 0 ? 'alert-danger' : 'alert-success'}"
|
||||
role="alert">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<span class="fw-bold">
|
||||
<span invisible="amount_due == 0">
|
||||
💰 Balance Due / المبلغ المتبقي:
|
||||
</span>
|
||||
<span invisible="amount_due != 0">
|
||||
✅ Order is fully paid!
|
||||
</span>
|
||||
</span>
|
||||
<span class="fs-4 fw-bold">
|
||||
<field name="amount_due" readonly="1"
|
||||
widget="monetary"
|
||||
options="{'currency_field': 'currency_id'}"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── Payment Entry ── -->
|
||||
<group string="Payment Details / تفاصيل الدفع">
|
||||
<group>
|
||||
<field name="journal_id"
|
||||
string="Journal / الدفتر"
|
||||
options="{'no_create': True, 'no_create_edit': True}"
|
||||
required="1"/>
|
||||
<field name="payment_method_line_id"
|
||||
string="Payment Method / طريقة الدفع"
|
||||
options="{'no_create': True, 'no_create_edit': True}"
|
||||
required="1"/>
|
||||
<field name="amount"
|
||||
string="Amount Received / المبلغ المستلم"
|
||||
required="1"
|
||||
widget="monetary"
|
||||
options="{'currency_field': 'currency_id'}"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="payment_date"
|
||||
string="Payment Date / تاريخ الدفع"
|
||||
required="1"/>
|
||||
<field name="memo"
|
||||
string="Reference / المرجع"
|
||||
placeholder="e.g. Cash payment for order…"/>
|
||||
</group>
|
||||
</group>
|
||||
|
||||
<!-- ── Change Display (cash overpayment) ── -->
|
||||
<div class="alert alert-warning mt-2"
|
||||
invisible="not is_overpayment"
|
||||
role="alert">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<span class="fw-bold">💵 Change to Return / الباقي:</span>
|
||||
<span class="fs-5 fw-bold">
|
||||
<field name="change_amount" readonly="1"
|
||||
widget="monetary"
|
||||
options="{'currency_field': 'currency_id'}"/>
|
||||
</span>
|
||||
</div>
|
||||
<div class="small text-muted mt-1">
|
||||
Payment recorded for balance due. Return change to customer.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Hidden fields -->
|
||||
<field name="currency_id" invisible="1"/>
|
||||
<field name="company_id" invisible="1"/>
|
||||
<field name="is_overpayment" invisible="1"/>
|
||||
|
||||
</sheet>
|
||||
<footer>
|
||||
<button name="action_confirm_payment"
|
||||
string="✓ Confirm Payment / تأكيد الدفع"
|
||||
type="object"
|
||||
class="btn-primary btn-lg"/>
|
||||
<button name="action_view_invoice"
|
||||
string="View Invoice"
|
||||
type="object"
|
||||
class="btn-secondary"
|
||||
groups="laundry_management.group_laundry_manager"/>
|
||||
<button string="Cancel"
|
||||
class="btn-secondary"
|
||||
special="cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Action to open the payment wizard (also used by button on order) -->
|
||||
<record id="action_laundry_payment_wizard" model="ir.actions.act_window">
|
||||
<field name="name">Register Payment</field>
|
||||
<field name="res_model">laundry.payment.wizard</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
<field name="context">{'default_order_id': active_id}</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,46 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════════
|
||||
PRINT WIZARD — Form View
|
||||
═══════════════════════════════════════════════════════════════ -->
|
||||
<record id="view_laundry_print_wizard_form" model="ir.ui.view">
|
||||
<field name="name">laundry.print.wizard.form</field>
|
||||
<field name="model">laundry.print.wizard</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Print / طباعة">
|
||||
<sheet>
|
||||
<div class="alert alert-info mb-3" role="alert">
|
||||
<strong>
|
||||
<field name="order_name" readonly="1" nolabel="1"/>
|
||||
</strong>
|
||||
 — 
|
||||
<field name="customer_name" readonly="1" nolabel="1"/>
|
||||
 |  Total:
|
||||
<field name="total_amount" readonly="1" nolabel="1"/>
|
||||
</div>
|
||||
|
||||
<group string="Print Template / قالب الطباعة">
|
||||
<field name="template" widget="radio"/>
|
||||
</group>
|
||||
|
||||
<group string="Options">
|
||||
<field name="include_prices"/>
|
||||
<field name="include_notes"/>
|
||||
</group>
|
||||
</sheet>
|
||||
<footer>
|
||||
<button name="action_print"
|
||||
string="Print"
|
||||
type="object"
|
||||
class="btn-primary"
|
||||
icon="fa-print"/>
|
||||
<button string="Cancel"
|
||||
class="btn-secondary"
|
||||
special="cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,197 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<!-- ════════════════════════════════════════════════════════════════
|
||||
Laundry Reporting — extends standard Odoo dashboards.
|
||||
────────────────────────────────────────────────────────────────
|
||||
Strategy:
|
||||
• Pure standard view types (graph + pivot) — no OWL, no
|
||||
client action, no SCSS. Identical to the way
|
||||
sale.order/account.move ship their analysis views.
|
||||
• New menu items hang off the EXISTING reporting menus that
|
||||
core already exposes:
|
||||
sale.menu_sale_report (Sales → Reporting)
|
||||
account.menu_finance_reports (Accounting → Reporting)
|
||||
Plus a convenience entry under the Laundry app root.
|
||||
• No view inheritance against core dashboards — adding our
|
||||
own graph/pivot under their reporting menus is the safe,
|
||||
standard pattern; overriding `account.dashboard.kanban`
|
||||
would be invasive and version-fragile.
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
|
||||
<!-- ── laundry.order — Operations & Financial graph/pivot ──────── -->
|
||||
<record id="view_laundry_order_graph" model="ir.ui.view">
|
||||
<field name="name">laundry.order.graph</field>
|
||||
<field name="model">laundry.order</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Laundry Orders Analysis" type="bar"
|
||||
stacked="0" sample="1">
|
||||
<field name="create_date" interval="day" type="row"/>
|
||||
<field name="state" type="col"/>
|
||||
<field name="amount_total" type="measure"/>
|
||||
<field name="amount_due" type="measure"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_laundry_order_pivot" model="ir.ui.view">
|
||||
<field name="name">laundry.order.pivot</field>
|
||||
<field name="model">laundry.order</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Laundry Orders Analysis" sample="1">
|
||||
<field name="create_date" interval="month" type="row"/>
|
||||
<field name="state" type="col"/>
|
||||
<field name="amount_total" type="measure"/>
|
||||
<field name="amount_paid_cash" type="measure"/>
|
||||
<field name="amount_due" type="measure"/>
|
||||
<field name="item_count" type="measure"/>
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Action: Sales-side analysis (orders + revenue + AOV via measures) -->
|
||||
<record id="action_laundry_orders_reporting" model="ir.actions.act_window">
|
||||
<field name="name">Laundry Orders</field>
|
||||
<field name="res_model">laundry.order</field>
|
||||
<field name="view_mode">graph,pivot,list,form</field>
|
||||
<field name="view_ids" eval="[
|
||||
(5, 0, 0),
|
||||
(0, 0, {'view_mode': 'graph', 'view_id': ref('view_laundry_order_graph')}),
|
||||
(0, 0, {'view_mode': 'pivot', 'view_id': ref('view_laundry_order_pivot')}),
|
||||
(0, 0, {'view_mode': 'list', 'view_id': ref('view_laundry_order_list')}),
|
||||
(0, 0, {'view_mode': 'form', 'view_id': ref('view_laundry_order_form')}),
|
||||
]"/>
|
||||
<field name="search_view_id" ref="view_laundry_order_search"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
No laundry orders for this period.
|
||||
</p>
|
||||
<p>
|
||||
Switch to the Pivot view for a customer / month / state
|
||||
breakdown, or use the date filters to narrow the range.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ── laundry.order — Operations-only KPI (Processing/Ready/Delayed) -->
|
||||
<!-- Same model, different default filter — surfaces the operational
|
||||
in-flight pipeline so the cashier / operator can spot bottlenecks. -->
|
||||
<record id="action_laundry_operations_kpi" model="ir.actions.act_window">
|
||||
<field name="name">Laundry Operations (Live)</field>
|
||||
<field name="res_model">laundry.order</field>
|
||||
<field name="view_mode">graph,pivot,list</field>
|
||||
<field name="domain">[('state', 'in', ['intake', 'processing', 'ready'])]</field>
|
||||
<field name="context">{'search_default_groupby_state': 1}</field>
|
||||
<field name="view_ids" eval="[
|
||||
(5, 0, 0),
|
||||
(0, 0, {'view_mode': 'graph', 'view_id': ref('view_laundry_order_graph')}),
|
||||
(0, 0, {'view_mode': 'pivot', 'view_id': ref('view_laundry_order_pivot')}),
|
||||
(0, 0, {'view_mode': 'list', 'view_id': ref('view_laundry_order_list')}),
|
||||
]"/>
|
||||
<field name="search_view_id" ref="view_laundry_order_search"/>
|
||||
</record>
|
||||
|
||||
<!-- ── account.move — Laundry-flagged invoices analysis ────────── -->
|
||||
<!-- Uses the existing `is_laundry_invoice` computed flag on
|
||||
account.move (from models/account_move.py). No new accounting
|
||||
logic — pure read filter. -->
|
||||
<record id="view_laundry_invoice_graph" model="ir.ui.view">
|
||||
<field name="name">account.move.graph.laundry</field>
|
||||
<field name="model">account.move</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Laundry Invoices" type="bar" stacked="0" sample="1">
|
||||
<field name="invoice_date" interval="month" type="row"/>
|
||||
<field name="state" type="col"/>
|
||||
<field name="amount_total_signed" type="measure"/>
|
||||
<field name="amount_residual_signed" type="measure"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_laundry_invoice_pivot" model="ir.ui.view">
|
||||
<field name="name">account.move.pivot.laundry</field>
|
||||
<field name="model">account.move</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Laundry Invoices" sample="1">
|
||||
<field name="partner_id" type="row"/>
|
||||
<field name="invoice_date" interval="month" type="col"/>
|
||||
<field name="amount_total_signed" type="measure"/>
|
||||
<field name="amount_residual_signed" type="measure"/>
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_laundry_invoices_reporting" model="ir.actions.act_window">
|
||||
<field name="name">Laundry Invoices</field>
|
||||
<field name="res_model">account.move</field>
|
||||
<field name="view_mode">graph,pivot,list,form</field>
|
||||
<field name="domain">[
|
||||
('is_laundry_invoice', '=', True),
|
||||
('move_type', 'in', ('out_invoice', 'out_refund')),
|
||||
]</field>
|
||||
<field name="view_ids" eval="[
|
||||
(5, 0, 0),
|
||||
(0, 0, {'view_mode': 'graph', 'view_id': ref('view_laundry_invoice_graph')}),
|
||||
(0, 0, {'view_mode': 'pivot', 'view_id': ref('view_laundry_invoice_pivot')}),
|
||||
]"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
No laundry invoices for this period.
|
||||
</p>
|
||||
<p>
|
||||
Switch to the Pivot view for a customer / month
|
||||
breakdown of revenue, settled, and outstanding.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ════════════════════════════════════════════════════════════════
|
||||
MENU INTEGRATION — extend existing core reporting menus.
|
||||
No menu override; pure additive child entries.
|
||||
════════════════════════════════════════════════════════════════ -->
|
||||
|
||||
<!-- Sales → Reporting → Laundry Orders -->
|
||||
<menuitem id="menu_sale_report_laundry_orders"
|
||||
name="Laundry Orders"
|
||||
parent="sale.menu_sale_report"
|
||||
action="action_laundry_orders_reporting"
|
||||
sequence="100"
|
||||
groups="laundry_management.group_laundry_operator"/>
|
||||
|
||||
<!-- Accounting → Reporting → Laundry Invoices -->
|
||||
<menuitem id="menu_finance_report_laundry_invoices"
|
||||
name="Laundry Invoices"
|
||||
parent="account.menu_finance_reports"
|
||||
action="action_laundry_invoices_reporting"
|
||||
sequence="100"
|
||||
groups="laundry_management.group_laundry_manager"/>
|
||||
|
||||
<!-- Convenience entry under the Laundry app: same actions surfaced
|
||||
here so operators don't have to hop into Sales/Accounting. -->
|
||||
<menuitem id="menu_laundry_reports_root"
|
||||
name="Reports"
|
||||
parent="menu_laundry_root"
|
||||
sequence="80"
|
||||
groups="laundry_management.group_laundry_operator"/>
|
||||
|
||||
<menuitem id="menu_laundry_reports_orders"
|
||||
name="Orders Analysis"
|
||||
parent="menu_laundry_reports_root"
|
||||
action="action_laundry_orders_reporting"
|
||||
sequence="10"
|
||||
groups="laundry_management.group_laundry_operator"/>
|
||||
|
||||
<menuitem id="menu_laundry_reports_operations"
|
||||
name="Operations (Live)"
|
||||
parent="menu_laundry_reports_root"
|
||||
action="action_laundry_operations_kpi"
|
||||
sequence="20"
|
||||
groups="laundry_management.group_laundry_operator"/>
|
||||
|
||||
<menuitem id="menu_laundry_reports_invoices"
|
||||
name="Invoices Analysis"
|
||||
parent="menu_laundry_reports_root"
|
||||
action="action_laundry_invoices_reporting"
|
||||
sequence="30"
|
||||
groups="laundry_management.group_laundry_manager"/>
|
||||
|
||||
</odoo>
|
||||
@@ -1,309 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════════
|
||||
SESSION — Form View
|
||||
═══════════════════════════════════════════════════════════════ -->
|
||||
<record id="view_laundry_session_form" model="ir.ui.view">
|
||||
<field name="name">laundry.session.form</field>
|
||||
<field name="model">laundry.session</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Laundry Session">
|
||||
<header>
|
||||
<button name="action_open_session"
|
||||
string="Open Session"
|
||||
type="object"
|
||||
class="btn-primary"
|
||||
invisible="state != 'new'"/>
|
||||
<button name="action_close_session"
|
||||
string="Close Session"
|
||||
type="object"
|
||||
class="btn-warning"
|
||||
invisible="state != 'opened'"/>
|
||||
<button name="action_print_session_report"
|
||||
string="Print Report"
|
||||
type="object"
|
||||
icon="fa-print"
|
||||
invisible="state == 'new'"/>
|
||||
<field name="state" widget="statusbar"
|
||||
statusbar_visible="new,opened,closed"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<!-- Smart buttons -->
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button name="action_view_orders"
|
||||
type="object"
|
||||
class="oe_stat_button"
|
||||
icon="fa-list-alt"
|
||||
invisible="order_count == 0">
|
||||
<field name="order_count"
|
||||
widget="statinfo"
|
||||
string="Orders"/>
|
||||
</button>
|
||||
<button class="oe_stat_button"
|
||||
type="object"
|
||||
name="action_view_orders"
|
||||
icon="fa-money">
|
||||
<field name="total_sales"
|
||||
widget="statinfo"
|
||||
string="Sales"/>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="oe_title">
|
||||
<h1><field name="name" readonly="1"/></h1>
|
||||
</div>
|
||||
|
||||
<group>
|
||||
<group string="Session Info">
|
||||
<field name="user_id"
|
||||
options="{'no_create_edit': True}"/>
|
||||
<field name="opening_datetime" readonly="1"/>
|
||||
<field name="closing_datetime" readonly="1"
|
||||
invisible="state != 'closed'"/>
|
||||
<field name="company_id"
|
||||
groups="base.group_multi_company"/>
|
||||
</group>
|
||||
<group string="Opening Cash">
|
||||
<field name="opening_cash"
|
||||
readonly="state != 'new'"/>
|
||||
<field name="difference_account_id"
|
||||
options="{'no_create': True, 'no_create_edit': True}"
|
||||
readonly="state == 'closed'"/>
|
||||
</group>
|
||||
</group>
|
||||
|
||||
<notebook>
|
||||
<!-- FINANCIAL SUMMARY TAB -->
|
||||
<page string="Summary" name="summary">
|
||||
<group>
|
||||
<group string="Sales Breakdown">
|
||||
<field name="total_sales" readonly="1"/>
|
||||
<field name="total_paid" readonly="1"/>
|
||||
<field name="outstanding_amount" readonly="1"/>
|
||||
</group>
|
||||
<group string="Payment Methods">
|
||||
<field name="total_cash" readonly="1"/>
|
||||
<field name="total_bank" readonly="1"/>
|
||||
<field name="total_credit" readonly="1"/>
|
||||
</group>
|
||||
</group>
|
||||
<group string="Cash Control"
|
||||
invisible="state == 'new'">
|
||||
<group>
|
||||
<field name="opening_cash" readonly="1"
|
||||
string="Opening Float"/>
|
||||
<field name="total_cash" readonly="1"
|
||||
string="+ Cash Received"/>
|
||||
<field name="expected_closing_cash" readonly="1"/>
|
||||
</group>
|
||||
<group invisible="state != 'closed'">
|
||||
<field name="actual_closing_cash" readonly="1"/>
|
||||
<field name="cash_difference" readonly="1"
|
||||
widget="monetary"
|
||||
decoration-danger="cash_difference < 0"
|
||||
decoration-success="cash_difference >= 0"/>
|
||||
</group>
|
||||
</group>
|
||||
<group string="Notes" invisible="not notes">
|
||||
<field name="notes" nolabel="1" readonly="1"/>
|
||||
</group>
|
||||
</page>
|
||||
|
||||
<!-- ORDERS TAB — uses sale.order fields -->
|
||||
<page string="Orders" name="orders">
|
||||
<field name="order_ids" readonly="1">
|
||||
<list>
|
||||
<field name="name" string="Order No."/>
|
||||
<field name="partner_id" string="Customer"/>
|
||||
<field name="mobile" optional="show"/>
|
||||
<field name="date_order" string="Date"/>
|
||||
<field name="amount_total" string="Total" sum="Total"/>
|
||||
<field name="amount_due" string="Balance Due" optional="show"/>
|
||||
<field name="laundry_payment_status"
|
||||
string="Payment"
|
||||
widget="badge"
|
||||
decoration-success="laundry_payment_status == 'paid'"
|
||||
decoration-warning="laundry_payment_status == 'partial'"
|
||||
decoration-danger="laundry_payment_status == 'unpaid'"/>
|
||||
<field name="laundry_state"
|
||||
string="Processing"
|
||||
widget="badge"
|
||||
decoration-success="laundry_state == 'delivered'"
|
||||
decoration-warning="laundry_state == 'processing'"
|
||||
decoration-primary="laundry_state == 'ready'"
|
||||
decoration-info="laundry_state == 'intake'"/>
|
||||
<field name="state"
|
||||
widget="badge"
|
||||
decoration-info="state == 'draft'"
|
||||
decoration-success="state == 'sale'"
|
||||
decoration-danger="state == 'cancel'"
|
||||
optional="show"/>
|
||||
</list>
|
||||
</field>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
<chatter/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════════
|
||||
SESSION — List View
|
||||
═══════════════════════════════════════════════════════════════ -->
|
||||
<record id="view_laundry_session_list" model="ir.ui.view">
|
||||
<field name="name">laundry.session.list</field>
|
||||
<field name="model">laundry.session</field>
|
||||
<field name="arch" type="xml">
|
||||
<list string="Laundry Sessions">
|
||||
<field name="name"/>
|
||||
<field name="user_id"/>
|
||||
<field name="opening_datetime"/>
|
||||
<field name="closing_datetime" optional="show"/>
|
||||
<field name="order_count"/>
|
||||
<field name="total_sales" sum="Total Sales"/>
|
||||
<field name="total_cash" sum="Cash" optional="show"/>
|
||||
<field name="total_bank" sum="Bank/Card" optional="show"/>
|
||||
<field name="total_credit" sum="Credit" optional="show"/>
|
||||
<field name="state"
|
||||
widget="badge"
|
||||
decoration-success="state == 'closed'"
|
||||
decoration-warning="state == 'opened'"
|
||||
decoration-info="state == 'new'"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════════
|
||||
SESSION — Search View
|
||||
═══════════════════════════════════════════════════════════════ -->
|
||||
<record id="view_laundry_session_search" model="ir.ui.view">
|
||||
<field name="name">laundry.session.search</field>
|
||||
<field name="model">laundry.session</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Sessions">
|
||||
<field name="name" string="Session"/>
|
||||
<field name="user_id" string="Staff"/>
|
||||
<filter string="Open" name="opened"
|
||||
domain="[('state','=','opened')]"/>
|
||||
<filter string="Closed" name="closed"
|
||||
domain="[('state','=','closed')]"/>
|
||||
<filter string="Today" name="today"
|
||||
domain="[('opening_datetime','>=',context_today().strftime('%Y-%m-%d'))]"/>
|
||||
<separator/>
|
||||
<filter string="By Staff" name="by_user"
|
||||
context="{'group_by':'user_id'}"/>
|
||||
<filter string="By Month" name="by_month"
|
||||
context="{'group_by':'opening_datetime:month'}"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════════
|
||||
SESSION CLOSE WIZARD — View
|
||||
═══════════════════════════════════════════════════════════════ -->
|
||||
<record id="view_laundry_session_close_wizard_form" model="ir.ui.view">
|
||||
<field name="name">laundry.session.close.wizard.form</field>
|
||||
<field name="model">laundry.session.close.wizard</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Close Session">
|
||||
<sheet>
|
||||
<div class="alert alert-warning mb-3" role="alert">
|
||||
<strong>Closing Session: </strong>
|
||||
<field name="session_id" readonly="1" nolabel="1"/>
|
||||
<br/>
|
||||
Count the cash in the drawer and enter the total below.
|
||||
</div>
|
||||
|
||||
<group string="Session Summary">
|
||||
<group>
|
||||
<field name="order_count" string="Orders Processed" readonly="1"/>
|
||||
<field name="total_sales" readonly="1"/>
|
||||
<field name="total_paid" readonly="1"/>
|
||||
<field name="outstanding_amount" readonly="1"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="total_cash" readonly="1"/>
|
||||
<field name="total_bank" readonly="1"/>
|
||||
<field name="total_credit" readonly="1"/>
|
||||
</group>
|
||||
</group>
|
||||
|
||||
<group string="Cash Control">
|
||||
<group>
|
||||
<field name="opening_cash" readonly="1" string="Opening Float"/>
|
||||
<field name="total_cash" readonly="1" string="+ Cash Received"/>
|
||||
<field name="expected_closing_cash" readonly="1"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="actual_closing_cash"/>
|
||||
<field name="cash_difference" readonly="1"
|
||||
decoration-danger="cash_difference < 0"
|
||||
decoration-success="cash_difference >= 0"/>
|
||||
</group>
|
||||
</group>
|
||||
|
||||
<group string="Cash Difference Entry"
|
||||
invisible="cash_difference == 0">
|
||||
<group>
|
||||
<field name="post_difference_entry"/>
|
||||
</group>
|
||||
<group invisible="not post_difference_entry">
|
||||
<field name="difference_account_id"
|
||||
options="{'no_create': True}"/>
|
||||
</group>
|
||||
</group>
|
||||
|
||||
<group string="Notes">
|
||||
<field name="closing_notes" nolabel="1"
|
||||
placeholder="Any remarks about this session…"/>
|
||||
</group>
|
||||
</sheet>
|
||||
<footer>
|
||||
<button name="action_close"
|
||||
string="Close Session"
|
||||
type="object"
|
||||
class="btn-primary"/>
|
||||
<button string="Cancel"
|
||||
class="btn-secondary"
|
||||
special="cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════════
|
||||
ACTIONS
|
||||
═══════════════════════════════════════════════════════════════ -->
|
||||
<record id="action_laundry_session" model="ir.actions.act_window">
|
||||
<field name="name">Sessions</field>
|
||||
<field name="res_model">laundry.session</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="search_view_id" ref="view_laundry_session_search"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
No sessions yet — open your first daily session!
|
||||
</p>
|
||||
<p>
|
||||
Sessions track daily orders and cash flow,
|
||||
similar to a Point of Sale day shift.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_laundry_session_open" model="ir.actions.act_window">
|
||||
<field name="name">Current Session</field>
|
||||
<field name="res_model">laundry.session</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="domain">[('state','=','opened')]</field>
|
||||
<field name="search_view_id" ref="view_laundry_session_search"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
No session is currently open.
|
||||
</p>
|
||||
<p>Go to All Sessions to open a new session for today.</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,150 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════════
|
||||
LAUNDRY SETTINGS — Odoo 19 style settings panel (PART 9)
|
||||
═══════════════════════════════════════════════════════════════ -->
|
||||
<record id="view_laundry_res_config_settings" model="ir.ui.view">
|
||||
<field name="name">res.config.settings.laundry</field>
|
||||
<field name="model">res.config.settings</field>
|
||||
<field name="inherit_id" ref="base.res_config_settings_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//form" position="inside">
|
||||
<app data-string="Laundry"
|
||||
string="Laundry"
|
||||
name="laundry_management"
|
||||
logo="/laundry_management/static/description/icon.png"
|
||||
groups="laundry_management.group_laundry_manager">
|
||||
|
||||
<!-- ── WhatsApp Business ──────────────────────── -->
|
||||
<block title="WhatsApp Business / واتساب الأعمال"
|
||||
name="laundry_whatsapp">
|
||||
|
||||
<setting string="Cloud API Token"
|
||||
help="Meta/Facebook WhatsApp Business Cloud API Bearer token. Leave blank to use the wa.me web link (one-click) mode.">
|
||||
<field name="laundry_wa_token"
|
||||
password="True"
|
||||
placeholder="EAAxxxxxxxx…"/>
|
||||
</setting>
|
||||
|
||||
<setting string="Phone Number ID"
|
||||
help="WhatsApp Business Phone Number ID from Meta Developer Console.">
|
||||
<field name="laundry_wa_phone_id"
|
||||
placeholder="12345678901234"/>
|
||||
</setting>
|
||||
|
||||
<setting string="Store WhatsApp Number"
|
||||
help="Store number in E.164 format without + (e.g. 966501234567). Used as fallback.">
|
||||
<field name="laundry_wa_store_number"
|
||||
placeholder="966501234567"/>
|
||||
</setting>
|
||||
|
||||
<setting string="Auto-send on Ready"
|
||||
help="Automatically open WhatsApp Web when an order is marked Ready for Pickup.">
|
||||
<field name="laundry_wa_auto_send"/>
|
||||
</setting>
|
||||
|
||||
</block>
|
||||
|
||||
<!-- ── Staff Commissions ──────────────────────── -->
|
||||
<block title="Staff Commissions / عمولات الموظفين"
|
||||
name="laundry_commission">
|
||||
|
||||
<setting string="Enable Commission Tracking"
|
||||
help="Automatically create commission records for reception, processing, and delivery staff as orders progress.">
|
||||
<field name="laundry_commission_enabled"/>
|
||||
<div class="content-group"
|
||||
invisible="not laundry_commission_enabled">
|
||||
<div class="row mt8">
|
||||
<label for="laundry_commission_type"
|
||||
class="col-lg-4 col-form-label o_light_label"
|
||||
string="Commission Type"/>
|
||||
<div class="col-lg-8">
|
||||
<field name="laundry_commission_type"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt4">
|
||||
<label for="laundry_commission_reception_rate"
|
||||
class="col-lg-4 col-form-label o_light_label"
|
||||
string="Reception Rate"/>
|
||||
<div class="col-lg-8">
|
||||
<field name="laundry_commission_reception_rate"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt4">
|
||||
<label for="laundry_commission_processing_rate"
|
||||
class="col-lg-4 col-form-label o_light_label"
|
||||
string="Processing Rate"/>
|
||||
<div class="col-lg-8">
|
||||
<field name="laundry_commission_processing_rate"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt4">
|
||||
<label for="laundry_commission_delivery_rate"
|
||||
class="col-lg-4 col-form-label o_light_label"
|
||||
string="Delivery Rate"/>
|
||||
<div class="col-lg-8">
|
||||
<field name="laundry_commission_delivery_rate"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</setting>
|
||||
|
||||
<setting string="Commission Expense Account"
|
||||
help="Expense account for booking commission costs (for future accounting integration).">
|
||||
<field name="laundry_commission_account_id"
|
||||
options="{'no_create': True}"/>
|
||||
</setting>
|
||||
|
||||
</block>
|
||||
|
||||
<!-- ── Session & Cash Control ─────────────── -->
|
||||
<block title="Session & Cash Control / الجلسات وإدارة الصندوق"
|
||||
name="laundry_session">
|
||||
|
||||
<setting string="Require Open Session"
|
||||
help="Prevent confirming orders when no daily session is open.">
|
||||
<field name="laundry_require_session"/>
|
||||
</setting>
|
||||
|
||||
<setting string="Default Cash Journal"
|
||||
help="Default journal used in the payment wizard for cash transactions.">
|
||||
<field name="laundry_cash_journal_id"
|
||||
options="{'no_create': True}"/>
|
||||
</setting>
|
||||
|
||||
<setting string="Cash Difference Account"
|
||||
help="Default account for posting session cash count variances.">
|
||||
<field name="laundry_difference_account_id"
|
||||
options="{'no_create': True}"/>
|
||||
</setting>
|
||||
|
||||
</block>
|
||||
|
||||
<!-- ── Operations ────────────────────────────── -->
|
||||
<block title="Operations / العمليات" name="laundry_operations">
|
||||
|
||||
<setting string="Default Print Format"
|
||||
help="Default paper format for order receipts.">
|
||||
<field name="laundry_default_paper"/>
|
||||
</setting>
|
||||
|
||||
</block>
|
||||
|
||||
</app>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ═══════════════════════════════════════════════════════════════
|
||||
ACTION
|
||||
═══════════════════════════════════════════════════════════════ -->
|
||||
<record id="action_laundry_settings" model="ir.actions.act_window">
|
||||
<field name="name">Laundry Settings</field>
|
||||
<field name="res_model">res.config.settings</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">current</field>
|
||||
<field name="context">{'module': 'laundry_management'}</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,35 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="view_pos_config_laundry_form" model="ir.ui.view">
|
||||
<field name="name">pos.config.form.laundry</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="//sheet" position="inside">
|
||||
<group string="Laundry POS Settings" name="laundry_pos_settings">
|
||||
<group string="Order Type Flow" name="laundry_order_type_flow">
|
||||
<field name="enable_laundry_order_type"/>
|
||||
<field name="require_laundry_order_type"
|
||||
invisible="not enable_laundry_order_type"/>
|
||||
<field name="ask_laundry_order_type_on_first_line"
|
||||
invisible="not enable_laundry_order_type"/>
|
||||
<field name="allow_change_laundry_order_type_before_payment"
|
||||
invisible="not enable_laundry_order_type"/>
|
||||
<field name="default_laundry_order_type_id"
|
||||
invisible="not enable_laundry_order_type"/>
|
||||
<field name="enable_laundry_attributes"
|
||||
invisible="not enable_laundry_order_type"/>
|
||||
<field name="require_delivery_details_if_needed"
|
||||
invisible="not enable_laundry_order_type"/>
|
||||
<field name="require_delivery_time"
|
||||
invisible="not enable_laundry_order_type or not require_delivery_details_if_needed"/>
|
||||
<field name="show_order_type_icons"
|
||||
invisible="not enable_laundry_order_type"/>
|
||||
</group>
|
||||
</group>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,36 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- Add laundry context fields to pos.order form (Extra Info tab). -->
|
||||
<record id="view_pos_order_form_laundry_context" model="ir.ui.view">
|
||||
<field name="name">pos.order.form.laundry.context</field>
|
||||
<field name="model">pos.order</field>
|
||||
<field name="inherit_id" ref="point_of_sale.view_pos_pos_form"/>
|
||||
<field name="arch" type="xml">
|
||||
|
||||
<xpath expr="//page[@name='extra']" position="inside">
|
||||
<group string="Laundry — Type & Attributes"
|
||||
name="laundry_context">
|
||||
<group>
|
||||
<field name="laundry_order_type_id"
|
||||
options="{'no_create': True, 'no_open': True}"/>
|
||||
<field name="laundry_is_delivery"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="laundry_delivery_address"
|
||||
invisible="not laundry_is_delivery"/>
|
||||
<field name="laundry_delivery_scheduled_at"
|
||||
invisible="not laundry_is_delivery"/>
|
||||
</group>
|
||||
<group colspan="2">
|
||||
<field name="laundry_order_attribute_ids"
|
||||
widget="many2many_tags"
|
||||
options="{'no_create': True, 'color_field': 'color'}"/>
|
||||
</group>
|
||||
</group>
|
||||
</xpath>
|
||||
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="view_product_template_form_laundry" model="ir.ui.view">
|
||||
<field name="name">product.template.form.laundry</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="inherit_id" ref="product.product_template_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//page[@name='general_information']//field[@name='type']" position="after">
|
||||
<field name="is_laundry_service"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,32 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<!-- Views of report of laundry orders -->
|
||||
<record id="report_laundry_order_view_pivot" model="ir.ui.view">
|
||||
<field name="name">report.laundry.order.pivot</field>
|
||||
<field name="model">report.laundry.order</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Laundry Order Analysis" display_quantity="true"
|
||||
disable_linking="True">
|
||||
<field name="name" type="row"/>
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
<!-- Defined Action-->
|
||||
<record id="report_laundry_order_action"
|
||||
model="ir.actions.act_window">
|
||||
<field name="name">Laundry Order Analysis</field>
|
||||
<field name="res_model">report.laundry.order</field>
|
||||
<field name="view_mode">pivot</field>
|
||||
<field name="context">{'group_by_no_leaf':1,'group_by':[]}</field>
|
||||
<field name="help">This report allows you to analyse the performance
|
||||
of your Laundry Management.
|
||||
</field>
|
||||
</record>
|
||||
<!-- Defined Menus-->
|
||||
<menuitem id="laundry_report_menu" name="Report"
|
||||
parent="laundry_management_menu" sequence="2"/>
|
||||
<menuitem name="Laundry Order Analysis"
|
||||
action="report_laundry_order_action"
|
||||
id="menu_laundry_order_analysis" parent="laundry_report_menu"
|
||||
sequence="1"/>
|
||||
</odoo>
|
||||
@@ -1,54 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<!-- Washing type model form view -->
|
||||
<record id="washing_type_form_view" model="ir.ui.view">
|
||||
<field name="name">washing.type.view.form</field>
|
||||
<field name="model">washing.type</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<sheet>
|
||||
<group>
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<field name="assigned_person_id"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="amount"/>
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<!-- Washing type model list view -->
|
||||
<record id="washing_type_view_list" model="ir.ui.view">
|
||||
<field name="name">washing.type.view.list</field>
|
||||
<field name="model">washing.type</field>
|
||||
<field name="arch" type="xml">
|
||||
<list>
|
||||
<field name="name"/>
|
||||
<field name="assigned_person_id"/>
|
||||
<field name="amount"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
<!-- Action for washing type-->
|
||||
<record id="washing_type_action" model="ir.actions.act_window">
|
||||
<field name="name">Washing Type</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">washing.type</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
</record>
|
||||
<!-- Defined Menus-->
|
||||
<menuitem id="laundry_config_menu" name="Configuration"
|
||||
parent="laundry_management_menu" sequence="3"/>
|
||||
<menuitem id="laundry_customer" name="Customers"
|
||||
parent="laundry_config_menu"
|
||||
action="base.action_partner_customer_form" sequence="1"/>
|
||||
<menuitem id="laundry_products" name="Products"
|
||||
parent="laundry_config_menu"
|
||||
action="product.product_normal_action_sell" sequence="2"/>
|
||||
<menuitem id="laundry_washing_type" name="Washing Type"
|
||||
parent="laundry_config_menu" action="washing_type_action"
|
||||
sequence="3"/>
|
||||
</odoo>
|
||||
@@ -1,85 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<!-- Washing model form view -->
|
||||
<record id="washing_washing_view_form" model="ir.ui.view">
|
||||
<field name="name">washing.washing.view.form</field>
|
||||
<field name="model">washing.washing</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Washing" create="false">
|
||||
<header>
|
||||
<button name="start_wash" class="oe_highlight"
|
||||
string="Start" type="object"
|
||||
invisible="state not in 'draft'"/>
|
||||
<button name="action_set_to_done" class="oe_highlight"
|
||||
string="Set to Done" type="object"
|
||||
invisible="state not in 'process'"/>
|
||||
<field name="state" widget="statusbar"
|
||||
statusbar_visible="draft,process,done"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<group>
|
||||
<group>
|
||||
<field name="name" readonly="1"/>
|
||||
<field name="user_id"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="washing_date" readonly="1"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Description">
|
||||
<field name="description"/>
|
||||
</page>
|
||||
<page string="Additional Products">
|
||||
<field name="product_line_ids"
|
||||
readonly="state != 'draft'">
|
||||
<list editable="bottom">
|
||||
<field name="product_id"/>
|
||||
<field name="name"/>
|
||||
<field name="quantity"/>
|
||||
<field name="uom_id"/>
|
||||
<field name="price_unit"/>
|
||||
<field name="subtotal"/>
|
||||
<field name="wash_id" invisible="1"/>
|
||||
</list>
|
||||
</field>
|
||||
<group class="oe_subtotal_footer oe_right"
|
||||
colspan="2" name="product_total">
|
||||
<field name="total_amount"
|
||||
widget='monetary'/>
|
||||
</group>
|
||||
<div class="oe_clear"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<!-- Washing model list view -->
|
||||
<record id="washing_washing_view_list" model="ir.ui.view">
|
||||
<field name="name">washing.washing.view.list</field>
|
||||
<field name="model">washing.washing</field>
|
||||
<field name="arch" type="xml">
|
||||
<list create="false" edit="false"
|
||||
decoration-info="state == 'draft'">
|
||||
<field name="name"/>
|
||||
<field name="user_id"/>
|
||||
<field name="washing_date"/>
|
||||
<field name="state"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
<!-- Action for washing-->
|
||||
<record id="washing_washing_action" model="ir.actions.act_window">
|
||||
<field name="name">Washing</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">washing.washing</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="domain">[('user_id','=', uid)]</field>
|
||||
</record>
|
||||
<!-- Defined Menu-->
|
||||
<menuitem id="washing_washing_menu" name="Laundry Works"
|
||||
parent="laundry_management_sub_menu"
|
||||
action="washing_washing_action"
|
||||
sequence="2"/>
|
||||
</odoo>
|
||||
@@ -1,46 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<!-- Washing work model form view-->
|
||||
<record id="washing_work_view_form" model="ir.ui.view">
|
||||
<field name="name">washing.work.view.form</field>
|
||||
<field name="model">washing.work</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<sheet>
|
||||
<group>
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<field name="assigned_person_id"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="amount"/>
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<!-- Washing work model list view-->
|
||||
<record id="washing_work_view_list" model="ir.ui.view">
|
||||
<field name="name">washing.work.view.list</field>
|
||||
<field name="model">washing.work</field>
|
||||
<field name="arch" type="xml">
|
||||
<list>
|
||||
<field name="name"/>
|
||||
<field name="assigned_person_id"/>
|
||||
<field name="amount"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
<!-- Action for washing work-->
|
||||
<record id="washing_work_action" model="ir.actions.act_window">
|
||||
<field name="name">Additional Works</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">washing.work</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
</record>
|
||||
<!-- Menu for Additional work-->
|
||||
<menuitem id="washing_work_menu" name="Additional Works"
|
||||
parent="laundry_config_menu" action="washing_work_action"
|
||||
sequence="4"/>
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user