19.0 vanilla

This commit is contained in:
Ernad Husremovic 2026-03-09 09:32:12 +01:00
parent 79f83631d5
commit 73afc09215
6267 changed files with 1534193 additions and 1130106 deletions

View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_account_journal_pos_user_form" model="ir.ui.view">
<field name="name">account.move.pos.form.inherit</field>
<field name="model">account.move</field>
<field name="inherit_id" ref="account.view_move_form"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='button_box']" position="inside">
<button class="oe_stat_button"
name="action_view_source_pos_orders"
type="object"
icon="fa-pencil-square-o"
invisible="pos_order_count == 0 or move_type not in ('out_invoice', 'out_refund')">
<field string="POS Orders" name="pos_order_count" widget="statinfo"/>
</button>
</xpath>
<xpath expr="//field[@name='tax_cash_basis_origin_move_id']" position="before">
<field name="reversed_pos_order_id" readonly="True" invisible="not reversed_pos_order_id"/>
</xpath>
</field>
</record>
</odoo>

View file

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_account_journal_pos_user_form" model="ir.ui.view">
<field name="name">account.journal.pos.user.form.inherit</field>
<field name="model">account.journal</field>
<field name="inherit_id" ref="account.view_account_journal_form"/>
<field name="arch" type="xml">
<xpath expr="//notebook[last()]" position="inside">
<page string="Point of Sale" name="point_of_sale" invisible="1"/>
</xpath>
</field>
</record>
</odoo>

View file

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="point_of_sale.customer_display_index" name="POS Customer Display">
&lt;!DOCTYPE html&gt;
<html>
<head>
<!-- <title>Odoo Customer Display</title> -->
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta http-equiv="content-type" content="text/html, charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="mobile-web-app-capable" content="yes" />
<link rel="icon" href="/point_of_sale/static/src/img/favicon.ico" type="image/x-icon"/>
<script type="text/javascript">
var odoo =
<t t-out="json.dumps({
'csrf_token': request.csrf_token(None),
'__session_info__': session_info,
'debug': debug,
})" />;
</script>
<t t-call-assets="point_of_sale.customer_display_assets" />
<t t-if="'tests' in debug or test_mode_enabled" t-call-assets="point_of_sale.customer_display_assets_test" />
<title><t t-esc="debug" /></title>
</head>
<body></body>
</html>
</template>
</odoo>

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="digest_digest_view_form" model="ir.ui.view">
<field name="name">digest.digest.view.form.inherit.sale.order</field>
<field name="name">digest.digest.view.form.inherit.point_of_sale</field>
<field name="model">digest.digest</field>
<field name="priority">50</field>
<field name="inherit_id" ref="digest.digest_digest_view_form" />

View file

@ -3,21 +3,27 @@
<record id="action_pos_session_filtered" model="ir.actions.act_window">
<field name="name">Sessions</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">pos.session</field>
<field name="view_mode">tree,form</field>
<field name="view_mode">list,form</field>
<field name="search_view_id" ref="view_pos_session_search" />
<field name="context">{
'search_default_config_id': [active_id],
'default_config_id': active_id}
</field>
<field name="help" type="html">
<p class="o_view_nocontent_empty_folder">
No sessions found
</p>
<p>
Daily sessions hold sales from your Point of Sale.
</p>
</field>
</record>
<record id="action_pos_order_filtered" model="ir.actions.act_window">
<field name="name">Orders</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">pos.order</field>
<field name="view_mode">tree,form</field>
<field name="view_mode">list,form</field>
<field name="search_view_id" ref="view_pos_order_search"/>
<field name="context">{
'search_default_config_id': [active_id],
@ -49,118 +55,117 @@
<field name="name">pos.config.kanban.view</field>
<field name="model">pos.config</field>
<field name="arch" type="xml">
<kanban create="false" class="o_kanban_dashboard o_pos_kanban">
<field name="current_user_id" invisible="1" />
<field name="cash_control" invisible="1"/>
<field name="name"/>
<kanban create="false" can_open="0" class="o_pos_kanban" js_class="pos_config_kanban_view">
<field name="cash_control"/>
<field name="current_session_id"/>
<field name="current_session_state"/>
<field name="last_session_closing_date"/>
<field name="pos_session_username"/>
<field name="access_token"/>
<field name="pos_session_state"/>
<field name="pos_session_duration"/>
<field name="currency_id"/>
<field name="number_of_opened_session"/>
<field name="statistics_for_current_session" />
<templates>
<t t-name="kanban-box">
<div>
<div class="o_kanban_card_header">
<div class="o_kanban_card_header_title mb16">
<div class="o_primary">
<t t-esc="record.name.value"/>
<t t-name="menu">
<div class="container dropdown-pos-config">
<div class="row" style="min-width:200px">
<div class="col-6 o_kanban_manage_view">
<h5 role="menuitem" class="o_kanban_card_manage_title">
<span>View</span>
</h5>
<div role="menuitem">
<a name="%(action_pos_order_filtered)d" type="action">Orders</a>
</div>
<div role="menuitem">
<a name="%(action_pos_session_filtered)d" type="action">Sessions</a>
</div>
<t t-if="!record.current_session_id.raw_value &amp;&amp; record.pos_session_username.value">
<div class="badge text-bg-info o_kanban_inline_block">Opened by <t t-esc="record.pos_session_username.value"/></div>
</t>
<t t-if="record.pos_session_state.raw_value == 'opening_control'">
<div class="badge text-bg-info o_kanban_inline_block">Opening Control</div>
</t>
<t t-if="record.pos_session_state.raw_value == 'closing_control'">
<div class="badge text-bg-info o_kanban_inline_block">Closing Control</div>
</t>
<t t-if="record.pos_session_state.raw_value == 'opened' and record.pos_session_duration.raw_value > 1">
<div t-attf-class="badge bg-#{record.pos_session_duration.raw_value > 3 and 'danger' or 'warning'} o_kanban_inline_block"
title="The session has been opened for an unusually long period. Please consider closing.">
To Close
</div>
</t>
</div>
<div class="o_kanban_manage_button_section">
<a class="o_kanban_manage_toggle_button" href="#"><i class="fa fa-ellipsis-v" role="img" aria-label="Manage" title="Manage"/></a>
<div class="col-6">
<h5 role="menuitem" class="o_kanban_card_manage_title">
<span>Reporting</span>
</h5>
<div role="menuitem">
<a name="%(action_report_pos_order_all_filtered)d" type="action">Orders</a>
</div>
</div>
</div>
<div class="container o_kanban_card_content">
<div class="row">
<div class="col-6 o_kanban_primary_left">
<button t-if="record.current_session_state.raw_value != 'closing_control'" class="btn btn-primary" name="open_ui" type="object">
<t t-if="record.current_session_state.raw_value === 'opened'">Continue selling</t>
<t t-elif="!record.current_session_id.raw_value &amp;&amp; !record.pos_session_username.value">New Session</t>
<t t-elif="record.current_session_state.raw_value === 'opening_control'">Open Session</t>
</button>
<button t-else="" class="btn btn-secondary" name="open_existing_session_cb" type="object">Close</button>
</div>
<div class="col-6 o_kanban_primary_right">
<div t-if="record.last_session_closing_date.value" class="row">
<div class="col-6">
<span>Last Closing Date</span>
</div>
<div class="col-6">
<span><t t-esc="record.last_session_closing_date.value"/></span>
</div>
</div>
<div t-if="record.last_session_closing_date.value" attrs='{"invisible": [("cash_control","=",False)]}' class="row">
<div class="col-6">
<span>Last Closing Cash Balance</span>
</div>
<div class="col-6">
<span><field name="last_session_closing_cash" widget="monetary"/></span>
</div>
</div>
<button t-if="record.number_of_opened_session.value &gt; 1" class="btn btn-link" style="padding-left:0; text-decoration: underline" name="open_opened_session_list" type="object">
There are <t t-esc="record.number_of_opened_session.value"/> open sessions
</button>
</div>
</div>
<div style="text-align:right;">
<field name="current_user_id" widget="many2one_avatar_user"/>
</div>
</div><div class="container o_kanban_card_manage_pane dropdown-menu" role="menu">
<div class="row">
<div class="col-6 o_kanban_card_manage_section o_kanban_manage_view">
<div role="menuitem" class="o_kanban_card_manage_title">
<span>View</span>
</div>
<div role="menuitem">
<a name="%(action_pos_order_filtered)d" type="action">Orders</a>
</div>
<div role="menuitem">
<a name="%(action_pos_session_filtered)d" type="action">Sessions</a>
</div>
</div>
<div class="col-6 o_kanban_card_manage_section o_kanban_manage_new">
<div role="menuitem" class="o_kanban_card_manage_title">
<span>Reporting</span>
</div>
<div role="menuitem">
<a name="%(action_report_pos_order_all_filtered)d" type="action">Orders</a>
</div>
</div>
</div>
<div t-if="widget.editable" class="o_kanban_card_manage_settings row" groups="point_of_sale.group_pos_manager">
<div role="menuitem" class="col-12">
<a name="action_pos_config_modal_edit" type="object">Edit</a>
</div>
<div t-if="widget.editable" class="o_kanban_card_manage_settings row" groups="point_of_sale.group_pos_manager">
<div role="menuitem" class="col-12">
<a name="action_pos_config_modal_edit" type="object">Edit</a>
</div>
</div>
</div>
</t>
<t t-name="card">
<div name="card_title" class="mb-4 ms-2">
<field name="name" class="fw-bold fs-4 d-block"/>
<div t-if="!record.current_session_id.raw_value &amp;&amp; record.pos_session_username.value" class="badge text-bg-info d-inline-block">Opened by <field name="pos_session_username"/></div>
<div t-if="record.pos_session_state.raw_value == 'opening_control'" class="badge text-bg-info d-inline-block">Opening Control</div>
<div t-if="record.pos_session_state.raw_value == 'closing_control'" class="badge text-bg-info d-inline-block">Closing Control</div>
<div t-if="record.pos_session_state.raw_value == 'opened' and record.pos_session_duration.raw_value > 1" t-attf-class="badge bg-#{record.pos_session_duration.raw_value > 3 and 'danger' or 'warning'} d-inline-block"
title="The session has been opened for an unusually long period. Please consider closing.">
To Close
</div>
</div>
<div class="row g-0 pb-4 ms-2 mt-auto">
<div name="card_left" class="col-12 col-md-6 d-flex flex-wrap align-items-center gap-2 mb-2 mb-md-0">
<button t-if="record.current_session_state.raw_value != 'closing_control'" class="btn btn-primary" name="open_ui" type="object">
<t t-if="record.current_session_state.raw_value === 'opened'">Continue Selling</t>
<t t-else="">Open Register</t>
</button>
<button t-else="" class="btn btn-secondary" name="open_existing_session_cb" type="object">Close</button>
</div>
<div class="col-12 col-md-6">
<t t-set="statistics" t-value="record.statistics_for_current_session.raw_value" />
<t t-if="statistics">
<div t-if="statistics.date.is_started" class="row">
<div class="col-5">
<span>Date</span>
</div>
<span t-esc="statistics.date.start_date" class="col-7"/>
</div>
<div class="row">
<div class="col-5">
<span>Opening</span>
</div>
<span name="opening_cash" t-esc="statistics.cash.opening_cash" class="col-7"/>
</div>
<div t-if="statistics.orders.paid.display" class="row">
<div class="col-5">
<span>Sold</span>
</div>
<span name="paid_orders" t-esc="statistics.orders.paid.display" class="col-7"/>
</div>
<div t-if="statistics.orders.draft.display" class="row">
<div class="col-5">
<span>Ongoing</span>
</div>
<span name="draft_orders" t-esc="statistics.orders.draft.display" class="col-7"/>
</div>
</t>
<t t-elif="record.last_session_closing_date.value">
<div class="row">
<div class="col-6">
<span>Closing</span>
</div>
<field name="last_session_closing_date" class="col-6"/>
</div>
<div class="row" invisible="not cash_control">
<div class="col-6">
<span>Balance</span>
</div>
<field name="last_session_closing_cash" widget="monetary" class="col-6"/>
</div>
</t>
<a t-if="record.number_of_rescue_session.value &gt; 0" class="col-12" name="open_opened_rescue_session_form" type="object">
<field name="number_of_rescue_session" /> outstanding rescue session
</a>
</div>
</div>
<field name="current_user_id" widget="many2one_avatar_user" class="mt-auto ms-auto"/>
</t>
</templates>
</kanban>
</field>

View file

@ -15,6 +15,8 @@
<field name="model">pos.session</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">point_of_sale.report_saledetails</field>
<field name="binding_model_id" ref="point_of_sale.model_pos_session"/>
<field name="binding_view_types">form</field>
</record>
</odoo>

View file

@ -4,7 +4,7 @@
<record id="seq_pos_session" model="ir.sequence">
<field name="name">POS Session</field>
<field name="code">pos.session</field>
<field name="prefix">POS/</field>
<field name="prefix">/</field>
<field name="padding">5</field>
<field name="company_id" eval="False" />
</record>

View file

@ -5,7 +5,7 @@
id="menu_point_root"
name="Point of Sale"
groups="group_pos_manager,group_pos_user"
web_icon="point_of_sale,static/description/icon.svg"
web_icon="point_of_sale,static/description/icon.png"
sequence="50"/>
<!-- Orders menu -->
@ -24,8 +24,13 @@
<menuitem id="menu_point_rep"
name="Reporting"
parent="menu_point_root"
sequence="90"
groups="group_pos_manager"/>
sequence="90"/>
<menuitem id="menu_report_daily_details"
name="Session Report"
action="action_report_pos_daily_sales_reports"
parent="menu_point_rep"
sequence="5"/>
<!-- Config menu and sub menus -->
<menuitem id="menu_point_config_product"
@ -37,14 +42,12 @@
<menuitem id="pos_menu_products_configuration"
name="Products"
parent="menu_point_config_product"
sequence="11"/>
sequence="12"/>
<record id="action_pos_configuration" model="ir.actions.act_window">
<field name="name">Settings</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">res.config.settings</field>
<field name="view_mode">form</field>
<field name="target">inline</field>
<field name="context">{'module' : 'point_of_sale', 'bin_size': False}</field>
</record>

View file

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="point_of_sale.assets_common" name="POS Assets Common">
<t t-call-assets="point_of_sale.pos_assets_backend_style" t-js="false"/>
<t t-call-assets="point_of_sale.assets" t-js="false" />
<t t-call-assets="web.assets_common" t-css="false" />
<t t-call-assets="point_of_sale.pos_assets_backend" t-css="false" />
<t t-call-assets="point_of_sale.assets" t-css="false" />
</template>
</odoo>

View file

@ -7,30 +7,25 @@
<head>
<title>Odoo POS</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta http-equiv="content-type" content="text/html, charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"/>
<meta name="apple-mobile-web-app-capable" content="yes"/>
<meta name="mobile-web-app-capable" content="yes"/>
<link rel="shortcut icon" sizes="196x196" href="/point_of_sale/static/src/img/touch-icon-196.png"/>
<link rel="shortcut icon" sizes="128x128" href="/point_of_sale/static/src/img/touch-icon-128.png"/>
<link rel="apple-touch-icon" href="/point_of_sale/static/src/img/touch-icon-iphone.png"/>
<link rel="apple-touch-icon" sizes="76x76" href="/point_of_sale/static/src/img/touch-icon-ipad.png"/>
<link rel="apple-touch-icon" sizes="120x120" href="/point_of_sale/static/src/img/touch-icon-iphone-retina.png"/>
<link rel="apple-touch-icon" sizes="152x152" href="/point_of_sale/static/src/img/touch-icon-ipad-retina.png"/>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, interactive-widget=resizes-content"/>
<link rel="icon" href="/point_of_sale/static/src/img/favicon.ico" type="image/x-icon"/>
<style> body { background: #222; } </style>
<link rel="shortcut icon" href="/point_of_sale/static/src/img/favicon.ico" type="image/x-icon"/>
<script type="text/javascript">
var odoo = <t t-out="json.dumps({
'csrf_token': request.csrf_token(None),
'__session_info__': session_info,
'login_number': login_number,
'from_backend': from_backend,
'pos_session_id': pos_session_id,
'last_data_change': last_data_change,
'pos_config_id': pos_config_id,
'access_token': access_token,
'urls_to_cache': urls_to_cache,
'use_pos_fake_tours': use_pos_fake_tours,
'use_lna': use_lna,
'debug': debug,
})"/>;
// Prevent the menu_service to load anything. In an ideal world, POS assets would only contain
@ -38,11 +33,20 @@
odoo.loadMenusPromise = Promise.resolve();
</script>
<t t-call="point_of_sale.assets_common"/>
<t t-call="web.conditional_assets_tests"/>
<t t-call-assets="point_of_sale.assets_backend_prod_only" />
<t t-call="web.conditional_assets_tests">
<t t-set="ignore_missing_deps" t-value="True"/>
</t>
<t t-if="request.cookies.get('pos_color_scheme') == 'dark'">
<t t-call-assets="point_of_sale.assets_prod_dark"/>
</t>
<t t-else="">
<t t-call-assets="point_of_sale.assets_prod"/>
</t>
<t t-if="use_pos_fake_tours">
<t t-call-assets="point_of_sale.assets_debug" />
</t>
</head>
<body>
<body class="pos">
</body>
</html>
</template>

View file

@ -1,56 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="point_of_sale.qunit_suite_assets">
<t t-if="request.httprequest.cookies.get('color_scheme') == 'dark'">
<t t-call-assets="web.dark_mode_assets_backend" t-js="false"/>
</t>
<t t-else="">
<t t-call-assets="web.assets_backend" t-js="false"/>
</t>
<t t-call-assets="point_of_sale.tests_assets" t-js="false"/>
<t t-call-assets="point_of_sale.tests_assets" t-css="false"/>
<style>
body {
position: relative;
}
body:not(.debug) .modal-backdrop, body:not(.debug) .modal, body:not(.debug) .ui-autocomplete {
opacity: 0 !important;
}
#qunit-testrunner-toolbar label {
font-weight: inherit;
margin-bottom: inherit;
}
#qunit-testrunner-toolbar input[type=text] {
width: inherit;
display: inherit;
}
</style>
</template>
<template id="point_of_sale.qunit_suite">
<t t-call="web.layout">
<t t-set="html_data" t-value="{'style': 'height: 100%;'}"/>
<t t-set="title">Point of Sale Tests</t>
<t t-set="head">
<!-- we need session_info in order to properly instantiate PosGlobalState -->
<script type="text/javascript">
var odoo = <t t-out="json.dumps({
'csrf_token': request.csrf_token(None),
'__session_info__': session_info,
'debug': debug,
'pos_session_id': pos_session_id,
})"/>;
</script>
<t t-call="point_of_sale.assets_common" />
<t t-call="point_of_sale.qunit_suite_assets" />
<t t-call-assets="point_of_sale.qunit_suite_tests" />
</t>
<div id="qunit"/>
<div id="qunit-fixture"/>
</t>
</template>
</odoo>

View file

@ -17,22 +17,21 @@
</record>
<record id="view_pos_bill_tree" model="ir.ui.view">
<field name="name">pos.bill.tree</field>
<field name="name">pos.bill.list</field>
<field name="model">pos.bill</field>
<field name="arch" type="xml">
<tree string="Bills" create="1" delete="1">
<list string="Bills" create="1" delete="1" editable="bottom">
<field name="name" />
<field name="value" />
<field name="pos_config_ids" widget="many2many_tags" />
</tree>
<field name="pos_config_ids" widget="many2many_tags_placeholder_list_view" placeholder="For all point of sale."/>
</list>
</field>
</record>
<record id="action_pos_bill" model="ir.actions.act_window">
<field name="name">Coins/Bills</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">pos.bill</field>
<field name="view_mode">tree,form</field>
<field name="view_mode">list,form</field>
</record>
<menuitem

View file

@ -6,9 +6,8 @@
<field name="arch" type="xml">
<form string="Pos Product Categories">
<sheet>
<field name="image_128" widget="image" class="oe_avatar"/>
<field name="image_512" widget="image" class="oe_avatar"/>
<div class="oe_title">
<label for="name"/>
<h1>
<field name="name" class="o_text_overflow" placeholder="e.g. Soft Drinks" required="True"/>
</h1>
@ -16,22 +15,32 @@
<group>
<group>
<field name="parent_id" class="o_text_overflow"/>
<field name="sequence" groups="base.group_no_one" />
</group>
<group name="sequence">
<field name="color" widget="color_picker" />
</group>
<div name="available_between" class="row col-lg-12" invisible="1">
<span class="text-900 fw-bold">Available between
<span class="col-lg-4 o_light_label">
<a class="o-tooltip"><sup title="Only works for online and self order">?</sup></a>
</span>
<field name="hour_after" class="oe_inline text-center" widget="float_time"/> and <field name="hour_until" class="oe_inline text-center" widget="float_time"/></span>
</div>
</group>
</sheet>
</form>
</field>
</record>
<record id="product_pos_category_tree_view" model="ir.ui.view">
<field name="name">pos.category.tree</field>
<field name="name">pos.category.list</field>
<field name="model">pos.category</field>
<field name="field_parent" eval="False"/>
<field name="arch" type="xml">
<tree string="Product Product Categories">
<list string="Product Product Categories">
<field name="sequence" widget="handle"/>
<field name="display_name" string="PoS Product Category"/>
</tree>
<field name="parent_id" optional="hide"/>
<field name="color" widget="color_picker" optional="hide"/>
</list>
</field>
</record>
@ -40,20 +49,14 @@
<field name="model">pos.category</field>
<field name="arch" type="xml">
<kanban class="o_kanban_mobile">
<field name="name"/>
<field name="id"/>
<templates>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_global_click">
<div class="row">
<div class="col-4">
<img height="100" width="100" t-att-src="kanban_image('pos.category', 'image_128', record.id.raw_value)" alt="Category"/>
</div>
<div class="col-8">
<strong class="o_kanban_record_title"><field name="name"/></strong>
</div>
</div>
</div>
<t t-name="card" class="row g-0">
<aside class="col-4">
<field name="image_128" widget="image" alt="Category" options="{'size': [100, 100], 'img_class': 'h-100'}"/>
</aside>
<main class="col ms-4">
<field name="name" class="fw-bolder fs-5"/>
</main>
</t>
</templates>
</kanban>
@ -62,9 +65,8 @@
<record id="product_pos_category_action" model="ir.actions.act_window">
<field name="name">PoS Product Categories</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">pos.category</field>
<field name="view_mode">tree,kanban,form</field>
<field name="view_mode">list,kanban,form</field>
<field name="view_id" eval="False"/>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">

View file

@ -7,7 +7,7 @@
<field name="arch" type="xml">
<form string="Point of Sale Configuration">
<sheet>
<widget name="web_ribbon" title="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
<widget name="web_ribbon" title="Archived" bg_color="text-bg-danger" invisible="active"/>
<field name="active" invisible="1"/>
<field name="company_has_template" invisible="1"/>
<field name="has_active_session" invisible="1"/>
@ -21,94 +21,104 @@
</div>
<!-- HIDE this div in create_mode (when '+ New Shop' is clicked in the general settings.) -->
<div invisible="context.get('pos_config_create_mode', False)">
<div class="o_notification_alert alert alert-warning" attrs="{'invisible':[('has_active_session','=', False)]}" role="alert">
<div class="o_notification_alert alert alert-warning" invisible="not has_active_session" role="alert">
A session is currently opened for this PoS. Some settings can only be changed after the session is closed.
<button class="btn" style="padding:0" name="open_ui" type="object">Click here to close the session</button>
<button class="btn" style="padding:0" name="close_ui" type="object">Click here to close the session</button>
</div>
<div class="o_notification_alert alert alert-warning" attrs="{'invisible': [('company_has_template','=',True)]}" role="alert">
<div class="o_notification_alert alert alert-warning" invisible="company_has_template" role="alert">
There is no Chart of Accounts configured on the company. Please go to the invoicing settings to install a Chart of Accounts.
</div>
</div>
<!-- SHOW this div in create_mode (when '+ New Shop' is clicked in the general settings.) -->
<div class="row mt16 o_settings_container" invisible="not context.get('pos_config_create_mode', False)">
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane">
<div id="restaurant_on_create" class="row mt16 o_settings_container" invisible="not context.get('pos_config_create_mode', False)">
<setting>
<field name="module_pos_restaurant" />
</div>
<div class="o_setting_right_pane">
<label for="module_pos_restaurant"/>
</div>
</div>
</setting>
</div>
<!-- HIDE this div in create_mode (when '+ New Shop' is clicked in the general settings.) -->
<div class="row mt16 o_settings_container" invisible="context.get('pos_config_create_mode', False)">
<div class="col-12 col-lg-6 o_setting_box"
title="Employees can scan their badge or enter a PIN to log in to a PoS session. These credentials are configurable in the *HR Settings* tab of the employee form.">
<div class="o_setting_left_pane">
<field name="module_pos_hr" attrs="{'readonly': [('has_active_session','=', True)]}" />
</div>
<div class="o_setting_right_pane">
<span class="o_form_label">Multi Employees per Session</span>
<div class="text-muted">
Allow to log and switch between selected Employees
</div>
<div class="content-group mt16" attrs="{'invisible': [('module_pos_hr','=',False)]}">
<div class="text-warning" id="warning_text_employees">
Save this page and come back here to set up the feature.
</div>
<setting
title="Employees can scan their badge or enter a PIN to log in to a PoS session. These credentials are configurable in the *HR Settings* tab of the employee form."
string="Log in with Employees"
help="Allow to log and switch between selected Employees">
<field name="module_pos_hr" readonly="has_active_session" />
<div class="content-group mt16" invisible="not module_pos_hr">
<div class="text-warning" id="warning_text_employees">
Save this page and come back here to set up the feature.
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box" id="other_devices">
<div class="o_setting_left_pane">
<field name="other_devices" />
</div>
<div class="o_setting_right_pane">
<label for="other_devices" string="ePos Printer"/>
<div class="text-muted mb16">
Connect device to your PoS without an IoT Box
</setting>
<setting id="other_devices" string="ePos Printer" help="Connect device to your PoS without an IoT Box">
<field name="other_devices" />
<div class="content-group" invisible="not other_devices">
<div class="row mb-2">
<div class="col-lg-6">
<field name="epson_printer_ip" placeholder="Epson Receipt Printer IP Address" class="w-100 pt-1" />
</div>
<div class="col-lg-6">
<widget name="point_of_sale_test_epos" />
</div>
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="is_posbox" />
</div>
<div class="o_setting_right_pane">
<label for="is_posbox" string="IoT Box"/>
<div class="text-muted mb16">
Connect devices using an IoT Box
</div>
<div class="content-group pos_iot_config" attrs="{'invisible' : [('is_posbox', '=', False)]}">
<div class="row">
<label string="IoT Box IP Address" for="proxy_ip" class="col-lg-4 o_light_label"/>
<field name="proxy_ip"/>
<div class="row" invisible="epson_printer_ip in [False, '']">
<div class="col-lg-6 o_light_label">
<label string="Link Cashdrawer" for="iface_cashdrawer"/>
</div>
<div class="row iot_barcode_scanner">
<label string="Barcode Scanner/Card Reader" for="iface_scan_via_proxy" class="col-lg-4 o_light_label"/>
<field name="iface_scan_via_proxy"/>
</div>
<div class="row">
<label string="Electronic Scale" for="iface_electronic_scale" class="col-lg-4 o_light_label"/>
<field name="iface_electronic_scale"/>
</div>
<div class="row">
<label string="Receipt Printer" for="iface_print_via_proxy" class="col-lg-4 o_light_label"/>
<field name="iface_print_via_proxy"/>
</div>
<div class="row" attrs="{'invisible': [('iface_print_via_proxy', '=', False)]}">
<label string="Cashdrawer" for="iface_cashdrawer" class="col-lg-4 o_light_label"/>
<div class="col-lg-6">
<field name="iface_cashdrawer"/>
</div>
<div class="row">
<label string="Customer Display" for="iface_customer_facing_display_via_proxy" class="col-lg-4 o_light_label"/>
<field name="iface_customer_facing_display_via_proxy"/>
</div>
</div>
</div>
</div>
<div role="alert" class="alert alert-warning" invisible="not iface_print_via_proxy or not other_devices or epson_printer_ip in [False, '']">
The Epson receipt printer will be used instead of the receipt printer connected to the IoT Box.
</div>
</setting>
<setting string="IoT Box" help="Connect devices using an IoT Box">
<field name="is_posbox" />
<div class="content-group pos_iot_config ms-3" invisible="not is_posbox">
<div class="row">
<div class="col-lg-4 o_light_label">
<label string="IoT Box IP Address" for="proxy_ip"/>
</div>
<div class="col-lg-8">
<field name="proxy_ip"/>
</div>
</div>
<div class="row iot_barcode_scanner">
<div class="col-lg-5 o_light_label">
<label string="Scanner" for="iface_scan_via_proxy"/>
</div>
<div class="col-lg-7">
<field name="iface_scan_via_proxy"/>
</div>
</div>
<div class="row">
<div class="col-lg-5 o_light_label">
<label string="Electronic Scale" for="iface_electronic_scale"/>
</div>
<div class="col-lg-7">
<field name="iface_electronic_scale"/>
</div>
</div>
<div class="row">
<div class="col-lg-5 o_light_label">
<label string="Receipt Printer" for="iface_print_via_proxy"/>
</div>
<div class="col-lg-7">
<field name="iface_print_via_proxy"/>
</div>
</div>
<div class="row" invisible="not iface_print_via_proxy">
<div class="col-lg-5 o_light_label ps-4">
<label string="Cashdrawer" for="iface_cashdrawer"/>
</div>
<div class="col-lg-7">
<field name="iface_cashdrawer"/>
</div>
</div>
</div>
</setting>
<div groups="base.group_system">
<p>
More settings: <a href="#" name="%(action_pos_configuration)d" type="action" class="btn-link o_form_uri" role="button">Configurations > Settings</a>
@ -127,13 +137,16 @@
</record>
<record id="view_pos_config_tree" model="ir.ui.view">
<field name="name">pos.config.tree.view</field>
<field name="name">pos.config.list.view</field>
<field name="model">pos.config</field>
<field name="arch" type="xml">
<tree string="Point of Sale Configuration">
<list string="Point of Sale Configuration">
<field name="name" />
<field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/>
</tree>
<field name="last_session_closing_date" string="Closing"/>
<field name="currency_id" column_invisible="True"/>
<field name="last_session_closing_cash" widget="monetary" string="Balance"/>
</list>
</field>
</record>
@ -151,9 +164,24 @@
<record id="action_pos_config_kanban" model="ir.actions.act_window">
<field name="name">Point of Sale</field>
<field name="type">ir.actions.act_window</field>
<field name="path">point-of-sale</field>
<field name="res_model">pos.config</field>
<field name="view_mode">kanban,tree,form</field>
<field name="view_mode">kanban,list,form</field>
<field name="domain"></field>
<field name="search_view_id" ref="view_pos_config_search" />
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a new PoS
</p><p>
Configure at least one Point of Sale.
</p>
</field>
</record>
<record id="action_pos_config_tree" model="ir.actions.act_window">
<field name="name">Point of Sale List</field>
<field name="res_model">pos.config</field>
<field name="view_mode">list,form</field>
<field name="domain"></field>
<field name="search_view_id" ref="view_pos_config_search" />
<field name="help" type="html">
@ -175,4 +203,7 @@
parent="point_of_sale.pos_menu_products_configuration" groups="product.group_product_variant" sequence="2"/>
<menuitem id="menu_pos_dashboard" action="action_pos_config_kanban" parent="menu_point_root" name="Dashboard" sequence="1"/>
<menuitem id="menu_point_of_sale_list" name="Point of Sales" parent="menu_point_config_product"
action="action_pos_config_tree" sequence="10"/>
</odoo>

View file

@ -0,0 +1,25 @@
<odoo>
<record id="view_pos_note_tree" model="ir.ui.view">
<field name="name">Note Models</field>
<field name="model">pos.note</field>
<field name="arch" type="xml">
<list string="Note Models" editable="bottom">
<field name="sequence" widget="handle" />
<field name="name" />
<field name="color" widget="color_picker"/>
</list>
</field>
</record>
<record id="action_pos_note_model" model="ir.actions.act_window">
<field name="name">Note Models</field>
<field name="res_model">pos.note</field>
<field name="view_mode">list</field>
</record>
<menuitem id="menu_pos_note_model"
parent="menu_point_config_product"
action="action_pos_note_model"
sequence="11"/>
</odoo>

View file

@ -26,19 +26,20 @@
</record>
<record id="report_pos_order_view_tree" model="ir.ui.view">
<field name="name">report.pos.order.view.tree</field>
<field name="name">report.pos.order.view.list</field>
<field name="model">report.pos.order</field>
<field name="arch" type="xml">
<tree string="Point of Sale Analysis">
<field name="date" widget="date"/>
<list string="Point of Sale Analysis">
<field name="date"/>
<field name="order_id" optional="hide"/>
<field name="partner_id" optional="hide"/>
<field name="product_id" optional="show"/>
<field name="product_categ_id" optional="show"/>
<field name="config_id" optional="hide"/>
<field name="company_id" optional="show" groups="base.group_multi_company"/>
<field name="price_total" optional="show"/>
<field name="state" optional="show"/>
</tree>
</list>
</field>
</record>
@ -49,19 +50,22 @@
<search string="Point of Sale Analysis">
<field name="date"/>
<separator/>
<filter string="Invoiced" name="invoiced" domain="[('state','=',('invoiced'))]"/>
<filter string="Not Invoiced" name="not_invoiced" domain="[('state','in',['paid', 'done'])]"/>
<filter string="Invoiced" name="invoiced" domain="[('invoiced','=',True)]"/>
<filter string="Not Invoiced" name="not_invoiced" domain="[('invoiced','=',False)]"/>
<filter string="Not Cancelled" name="not_cancelled" domain="[('state','!=','cancel')]"/>
<separator/>
<filter name="filter_date" date="date"/>
<field name="config_id"/>
<field name="partner_id"/>
<field name="product_id"/>
<field name="product_categ_id"/>
<group expand="1" string="Group By">
<group>
<filter string="User" name="User" context="{'group_by':'user_id'}"/>
<filter string="Point of Sale" name="pos" context="{'group_by':'config_id'}"/>
<filter string="Product" name="product" context="{'group_by':'product_id'}"/>
<filter string="Product Category" name="product_category" context="{'group_by':'product_categ_id'}"/>
<filter string="Payment Method" name="payment_method" context="{'group_by':'payment_method_id'}"/>
<filter string="Point of Sale Category" name="pos_categ_id" context="{'group_by':'pos_categ_id'}"/>
<separator/>
<filter string="Order Date" name="order_month" context="{'group_by':'date:month'}"/>
</group>
@ -72,7 +76,7 @@
<record id="filter_orders_per_session" model="ir.filters">
<field name="name">Per session</field>
<field name="model_id">report.pos.order</field>
<field name="user_id" eval="False"/>
<field name="user_ids" eval="False"/>
<field name="context">{'group_by': ['date', 'session_id']}</field>
</record>
@ -81,7 +85,7 @@
<field name="res_model">report.pos.order</field>
<field name="view_mode">graph,pivot</field>
<field name="search_view_id" ref="view_report_pos_order_search"/>
<field name="context">{'group_by_no_leaf':1,'group_by':[]}</field>
<field name="context">{'group_by':[], 'search_default_not_cancelled': 1}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
No data yet!

View file

@ -6,121 +6,144 @@
<field name="arch" type="xml">
<form string="Point of Sale Orders" create="0">
<header>
<button name="%(action_pos_payment)d" string="Payment" class="oe_highlight" type="action" states="draft" />
<button name="%(action_pos_payment)d" string="Payment" class="oe_highlight" type="action" invisible="state != 'draft'" />
<button name="action_pos_order_invoice" string="Invoice" type="object"
attrs="{'invisible': [('state','!=','paid')]}"/>
invisible="state not in ['paid', 'done'] or account_move"/>
<button name="refund" string="Return Products" type="object"
attrs="{'invisible':['|', ('state','=','draft'), ('has_refundable_lines', '=', False)]}"/>
<field name="state" widget="statusbar" statusbar_visible="draft,paid,done" />
invisible="state == 'draft' or not has_refundable_lines"/>
<field name="state" widget="statusbar" invisible="state == 'cancel'" statusbar_visible="draft,paid,done"/>
<field name="state" widget="statusbar" invisible="state != 'cancel'" statusbar_visible="draft,cancel"/>
<field name="has_refundable_lines" invisible="1" />
<field name="refunded_orders_count" invisible="1" />
</header>
<sheet>
<field name="failed_pickings" invisible="1"/>
<field name="is_refunded" invisible="1"/>
<div class="oe_button_box" name="button_box">
<button name="action_stock_picking"
type="object"
class="oe_stat_button"
icon="fa-truck"
attrs="{'invisible':[('picking_count', '=', 0)]}">
<field name="picking_count" widget="statinfo" string="Pickings" attrs="{'invisible': [('failed_pickings', '!=', False)]}"/>
<field name="picking_count" widget="statinfo" string="Pickings" class="text-danger" attrs="{'invisible': [('failed_pickings', '=', False)]}"/>
invisible="picking_count == 0">
<field name="picking_count" widget="statinfo" string="Pickings" invisible="failed_pickings"/>
<field name="picking_count" widget="statinfo" string="Pickings" class="text-danger" invisible="not failed_pickings"/>
</button>
<button name="action_view_invoice"
string="Invoice"
type="object"
class="oe_stat_button"
icon="fa-pencil-square-o"
attrs="{'invisible':[('state','!=','invoiced')]}">
invisible="not account_move">
</button>
<button name="action_view_refund_orders"
type="object"
class="oe_stat_button"
icon="fa-undo"
attrs="{'invisible':[('is_refunded', '=', False)]}">
invisible="refund_orders_count == 0">
<field name="refund_orders_count" widget="statinfo" string="Refunds" />
</button>
<button name="action_view_refunded_orders"
<button name="action_view_refunded_order"
type="object"
class="oe_stat_button"
icon="fa-shopping-cart "
attrs="{'invisible':[('refunded_orders_count', '=', 0)]}">
<field name="refunded_orders_count" widget="statinfo" string="Refunded Orders" />
invisible="not refunded_order_id">
<field name="refunded_order_id" widget="statinfo" string="Refunded Orders" />
</button>
</div>
<group col="4" colspan="4" name="order_fields">
<field name="name"/>
<field name="source" readonly="True" />
<field name="date_order"/>
<field name="session_id" />
<field string="User" name="user_id"/>
<field name="partner_id" context="{'res_partner_search_mode': 'customer'}" attrs="{'readonly': [('state','=','invoiced')]}"/>
<field name="fiscal_position_id" options="{'no_create': True}"/>
<field name="session_id" readonly="state != 'draft'"/>
<field string="User" name="user_id" readonly="account_move or state == 'done'"/>
<field name="order_edit_tracking" invisible="1"/>
<field name="is_edited" readonly="1" invisible="not order_edit_tracking"/>
<field name="partner_id" context="{'res_partner_search_mode': 'customer'}" readonly="account_move"/>
<field name="fiscal_position_id" options="{'no_create': True}" readonly="state != 'draft'"/>
</group>
<notebook colspan="4">
<page string="Products" name="products">
<field name="lines" colspan="4" nolabel="1">
<tree string="Order lines" editable="bottom">
<field name="full_product_name"/>
<field name="lines" colspan="4" nolabel="1" readonly="state != 'draft'" mode="list,kanban">
<kanban class="o_kanban_mobile">
<t t-name="card" class="row g-0">
<aside class="col-2 pe-3">
<field name="product_id" widget="image" options="{'preview_image': 'image_128'}"/>
</aside>
<main class="col">
<div class="d-flex">
<field name="full_product_name" class="fw-bolder"/>
<field name="price_subtotal_incl" widget="monetary" class="ms-auto me-3"/>
</div>
<div class="text-muted">
Quantity: <field name="qty"/> <field name="product_uom_id" groups="uom.group_uom"/>
</div>
<div class="text-muted">
Unit price: <field name="price_unit" widget="monetary"/>
</div>
</main>
</t>
</kanban>
<list string="Order lines" editable="bottom">
<field name="name" column_invisible="True"/>
<field name="full_product_name" optional="hide" readonly="1"/>
<field name="product_id" widget="product_label_section_and_note_field" />
<field name="is_edited" readonly="1" column_invisible="not parent.order_edit_tracking"/>
<field name="pack_lot_ids" widget="many2many_tags" groups="stock.group_production_lot"/>
<field name="qty"/>
<field name="customer_note" optional="hide"/>
<field name="product_uom_id" string="UoM" groups="uom.group_uom"/>
<field name="product_uom_id" groups="uom.group_uom"/>
<field name="price_unit" widget="monetary"/>
<field name="is_total_cost_computed" invisible="1"/>
<field name="total_cost" attrs="{'invisible': [('is_total_cost_computed','=', False)]}" optional="hide" widget="monetary"/>
<field name="margin" attrs="{'invisible': [('is_total_cost_computed','=', False)]}" optional="hide" widget="monetary"/>
<field name="margin_percent" attrs="{'invisible': [('is_total_cost_computed','=', False)]}" optional="hide" widget="percentage"/>
<field name="discount" string="Disc.%"/>
<field name="tax_ids_after_fiscal_position" widget="many2many_tags" string="Taxes"/>
<field name="tax_ids" widget="many2many_tags" invisible="1"/>
<field name="is_total_cost_computed" column_invisible="True"/>
<field name="total_cost" invisible="not is_total_cost_computed" optional="hide" widget="monetary"/>
<field name="margin" invisible="not is_total_cost_computed" optional="hide" widget="monetary"/>
<field name="margin_percent" invisible="not is_total_cost_computed" optional="hide" widget="percentage"/>
<field name="discount" width="50px" string="Disc.%"/>
<field name="tax_ids_after_fiscal_position" widget="many2many_tax_tags" string="Taxes"/>
<field name="tax_ids" widget="many2many_tax_tags" column_invisible="True"/>
<field name="price_subtotal" widget="monetary" force_save="1"/>
<field name="price_subtotal_incl" widget="monetary" force_save="1"/>
<field name="currency_id" invisible="1"/>
<field name="currency_id" column_invisible="True"/>
<field name="refunded_qty" optional="hide" />
</tree>
</list>
<form string="Order lines">
<group col="4">
<field name="full_product_name"/>
<field name="product_id" />
<field name="qty"/>
<field name="discount"/>
<field name="price_unit" widget="monetary"/>
<field name="price_subtotal" invisible="1" widget="monetary" force_save="1"/>
<field name="price_subtotal_incl" invisible="1" widget="monetary" force_save="1"/>
<field name="tax_ids_after_fiscal_position" widget="many2many_tags" string="Taxes"/>
<field name="tax_ids" widget="many2many_tags" invisible="1"/>
<field name="tax_ids_after_fiscal_position" widget="many2many_tax_tags" string="Taxes"/>
<field name="tax_ids" widget="many2many_tax_tags" invisible="1"/>
<field name="pack_lot_ids" widget="many2many_tags" groups="stock.group_production_lot"/>
<field name="notice"/>
<field name="currency_id" invisible="1"/>
<field name="full_product_name" readonly="1" />
</group>
</form>
</field>
<group class="oe_subtotal_footer oe_right" colspan="2" name="order_total">
<group class="oe_subtotal_footer" colspan="2" name="order_total">
<field name="amount_tax"
force_save="1"
widget="monetary"/>
<div class="oe_subtotal_footer_separator oe_inline o_td_label">
<label for="amount_total" />
<button name="button_dummy"
states="draft" string="(update)" class="oe_edit_only oe_link"/>
</div>
<field name="amount_total"
force_save="1"
nolabel="1"
class="oe_subtotal_footer_separator"
class="h3"
widget="monetary"/>
<div class="oe_inline o_td_label">
<label class="o_form_label_readonly" for="amount_paid" string="Total Paid (with rounding)"/>
</div>
<field name="amount_paid"
string="Total Paid (with rounding)"
class="oe_subtotal_footer_separator"
nolabel="1"
widget="monetary"
attrs="{'invisible': [('amount_paid','=', 'amount_total')]}"/>
class="h3"
invisible="amount_paid == 'amount_total'"
readonly="state != 'draft'"/>
<label for="margin"/>
<div class="text-nowrap">
<field name="margin" class="oe_inline" attrs="{'invisible': [('is_total_cost_computed','=', False)]}"/>
<span class="oe_inline" attrs="{'invisible': [('is_total_cost_computed','=', False)]}">
<field name="margin" class="oe_inline" invisible="not is_total_cost_computed"/>
<span class="oe_inline" invisible="not is_total_cost_computed">
(<field name="margin_percent" nolabel="1" class="oe_inline" widget="percentage"/>)
</span>
<span attrs="{'invisible': [('is_total_cost_computed','=', True)]}">TBD</span>
<span class="float-end" invisible="is_total_cost_computed">To be determined</span>
</div>
<field name="is_total_cost_computed" invisible="1"/>
<field name="currency_id" invisible="1"/>
@ -128,36 +151,63 @@
<div class="clearfix"/>
</page>
<page string="Payments" name="payments">
<field name="payment_ids" colspan="4" nolabel="1">
<tree string="Payments">
<field name="currency_id" invisible="1" />
<field name="payment_ids" colspan="4" nolabel="1" readonly="account_move or state == 'done' or nb_print > 0">
<list string="Payments" create="1" editable="bottom" open_form_view="True">
<field name="currency_id" column_invisible="True" />
<field name="payment_date"/>
<field name="payment_method_id"/>
<field name="payment_method_id" domain="[('id', 'in', parent.available_payment_method_ids)]" />
<field name="amount"/>
</tree>
<field name="payment_method_payment_mode" optional="hide"/>
<field name="card_no" invisible="not card_no"/>
<field name="card_brand" string="Card's Brand" invisible="not card_brand or not card_no"/>
<field name="cardholder_name" invisible="not cardholder_name or not card_no"/>
</list>
</field>
<group class="oe_subtotal_footer" colspan="2" name="order_total">
<field name="amount_total" class="h3" widget="monetary"/>
<field name="amount_paid" widget="monetary" class="h3" readonly="1" />
<field name="amount_difference" widget="monetary" force_save="1" />
</group>
</page>
<page name="extra" string="Extra Info">
<group >
<group
string="Accounting"
groups="account.group_account_manager"
attrs="{'invisible':['|', ('session_move_id','=', False), ('state', '=', 'invoiced')]}"
>
invisible="not session_move_id or account_move">
<field name="session_move_id" readonly="1" />
</group>
<group string="Other Information">
<group string="Other Information" name="other_information">
<field name="pos_reference"/>
<field name="tracking_number"/>
<field name="country_code" invisible="1"/>
<field name="company_id" groups="base.group_multi_company"/>
<field name="pricelist_id" groups="product.group_product_pricelist"/>
<field name="pricelist_id" groups="product.group_product_pricelist" readonly="state != 'draft'"/>
<field name="preset_id" readonly="True" />
<field name="preset_time" readonly="True" label="Preset time" invisible="not preset_time" />
<field name="floating_order_name" invisible="not floating_order_name"/>
</group>
<group string="Contact Info">
<group class="w-75">
<label for="email"/>
<div class="o_row">
<field name="email"/>
<button name="action_send_mail" icon="fa-envelope fa-lg" type="object" class="btn-link" title="email" invisible="not email"/>
</div>
<label for="mobile"/>
<div class="o_row">
<field name="mobile"/>
</div>
</group>
</group>
</group>
</page>
<page string="Notes" name="notes">
<field name="note"/>
<page string="Customer Note" name="notes">
<field name="general_customer_note" readonly="1"/>
</page>
</notebook>
</sheet>
<chatter groups="point_of_sale.group_pos_manager"/>
</form>
</field>
</record>
@ -167,47 +217,24 @@
<field name="model">pos.order</field>
<field name="arch" type="xml">
<kanban class="o_kanban_mobile" create="0" sample="1">
<field name="name"/>
<field name="partner_id"/>
<field name="amount_total"/>
<field name="date_order"/>
<field name="state"/>
<field name="pos_reference"/>
<field name="partner_id"/>
<field name="currency_id"/>
<templates>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_card oe_kanban_global_click">
<div class="o_kanban_record_top">
<div class="o_kanban_record_headings">
<strong class="o_kanban_record_title">
<span t-if="record.partner_id.value">
<t t-esc="record.partner_id.value"/>
</span>
<span t-else="">
<t t-esc="record.name.value"/>
</span>
</strong>
</div>
<strong><field name="amount_total" widget="monetary"/></strong>
</div>
<div class="row">
<div class="col-12">
<span><t t-esc="record.pos_reference.value"/></span>
</div>
</div>
<div class="row">
<div class="col-8 text-muted">
<span><t t-esc="record.date_order.value"/></span>
</div>
<div class="col-4">
<span class="float-end text-end">
<field name="state" widget="label_selection" options="{'classes': {'draft': 'default',
'invoiced': 'success', 'cancel': 'danger'}}"/>
</span>
</div>
</div>
<t t-name="card">
<div class="d-flex align-items-baseline mb-1">
<span t-if="record.partner_id.value">
<field name="partner_id" class="fw-bolder me-2"/>
</span>
<span t-else="">
<field name="name" class="fw-bolder me-2"/>
</span>
<field name="amount_total" widget="monetary" class="fw-bolder ms-auto flex-shrink-0"/>
</div>
<field name="pos_reference" />
<footer class="flex-wrap">
<field name="date_order" class="text-muted text-nowrap"/>
<field name="state" widget="label_selection" options="{'classes': {'draft': 'default',
'done': 'success', 'cancel': 'danger'}}" class="ms-auto text-truncate"/>
</footer>
</t>
</templates>
</kanban>
@ -228,9 +255,9 @@
<record id="action_pos_pos_form" model="ir.actions.act_window">
<field name="name">Orders</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">pos.order</field>
<field name="view_mode">tree,form,kanban,pivot</field>
<field name="path">pos-orders</field>
<field name="view_mode">list,form,kanban,pivot</field>
<field name="view_id" eval="False"/>
<field name="domain">[]</field>
<field name="help" type="html">
@ -244,10 +271,9 @@
<record id="action_pos_sale_graph" model="ir.actions.act_window">
<field name="name">Orders</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">pos.order</field>
<field name="view_mode">graph,tree,form,kanban,pivot</field>
<field name="domain">[('state', 'not in', ['draft', 'cancel', 'invoiced'])]</field>
<field name="view_mode">graph,list,form,kanban,pivot</field>
<field name="domain">[('state', 'not in', ['draft', 'cancel']), ('account_move', '=', False)]</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
No data yet!
@ -258,20 +284,27 @@
</record>
<record id="view_pos_order_tree" model="ir.ui.view">
<field name="name">pos.order.tree</field>
<field name="name">pos.order.list</field>
<field name="model">pos.order</field>
<field name="arch" type="xml">
<tree string="POS Orders" create="0" sample="1" decoration-info="state == 'draft'" decoration-muted="state == 'cancel'">
<field name="currency_id" invisible="1"/>
<list string="POS Orders" create="0" sample="1" decoration-info="state == 'draft'" decoration-muted="state == 'cancel'" duplicate="0">
<header>
<button name="action_create_invoices" type="object" string="Create Invoices"/>
</header>
<field name="currency_id" column_invisible="True"/>
<field name="name" decoration-bf="1"/>
<field name="session_id" />
<field name="session_id" readonly="state != 'draft'"/>
<field name="date_order"/>
<field name="config_id" />
<field name="pos_reference"/>
<field name="tracking_number" optional="hide"/>
<field name="partner_id"/>
<field string="Cashier" name="user_id" widget="many2one_avatar_user"/>
<field name="user_id" widget="many2one_avatar_user" readonly="account_move or state == 'done'"/>
<field name="amount_total" sum="Amount total" widget="monetary" decoration-bf="1"/>
<field name="state" widget="badge" decoration-info="state == 'draft'" decoration-success="state not in ('draft','cancel')"/>
</tree>
<field name="invoice_status" widget="badge" decoration-success="invoice_status == 'invoiced'" invisible="invoice_status == 'to_invoice'"/>
<field name="is_edited" readonly="1" optional="hide"/>
</list>
</field>
</record>
<record id="view_pos_order_tree_no_session_id" model="ir.ui.view">
@ -299,10 +332,10 @@
<menuitem id="menu_point_ofsale" parent="menu_point_of_sale" action="action_pos_pos_form" sequence="2" groups="group_pos_manager,group_pos_user"/>
<record id="view_pos_order_line" model="ir.ui.view">
<field name="name">pos.order.line.tree</field>
<field name="name">pos.order.line.list</field>
<field name="model">pos.order.line</field>
<field name="arch" type="xml">
<tree string="POS Order lines">
<list string="POS Order lines">
<field name="product_id" readonly="1"/>
<field name="qty" readonly="1" sum="Total qty"/>
<field name="discount" readonly="1"/>
@ -310,8 +343,8 @@
<field name="price_subtotal" readonly="1" sum="Sum of subtotals" widget="monetary"/>
<field name="price_subtotal_incl" readonly="1" sum="Sum of subtotals" widget="monetary"/>
<field name="create_date" readonly="1"/>
<field name="currency_id" invisible="1"/>
</tree>
<field name="currency_id" column_invisible="True"/>
</list>
</field>
</record>
@ -334,46 +367,42 @@
<record id="action_pos_order_line" model="ir.actions.act_window">
<field name="name">Sale line</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">pos.order.line</field>
<field name="view_mode">tree</field>
<field name="view_mode">list</field>
<field name="view_id" ref="view_pos_order_line"/>
</record>
<record id="action_pos_order_line_form" model="ir.actions.act_window">
<field name="name">Sale line</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">pos.order.line</field>
<field name="view_mode">form,tree</field>
<field name="view_mode">form,list</field>
<field name="view_id" ref="view_pos_order_line_form"/>
</record>
<record id="action_pos_order_line_day" model="ir.actions.act_window">
<field name="name">Sale line</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">pos.order.line</field>
<field name="view_mode">tree</field>
<field name="view_mode">list</field>
<field name="view_id" ref="view_pos_order_line"/>
<field name="domain">[('create_date', '&gt;=', time.strftime('%Y-%m-%d 00:00:00')),('create_date', '&lt;=', time.strftime('%Y-%m-%d 23:59:59'))]</field>
<field name="domain">[('create_date', '&gt;=', 'today'), ('create_date', '&lt;', 'today +1d')]</field>
</record>
<record id="view_pos_order_tree_all_sales_lines" model="ir.ui.view">
<field name="name">pos.order.line.all.sales.tree</field>
<field name="name">pos.order.line.all.sales.list</field>
<field name="model">pos.order.line</field>
<field name="arch" type="xml">
<tree string="POS Orders lines">
<list string="POS Orders lines">
<field name="order_id" />
<field name="create_date" />
<field name="product_id" />
<field name="qty" />
<field name="price_unit" widget="monetary"/>
<field name="currency_id" invisible="1"/>
</tree>
<field name="currency_id" column_invisible="True"/>
</list>
</field>
</record>
<record id="action_pos_all_sales_lines" model="ir.actions.act_window">
<field name="name">All sales lines</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">pos.order.line</field>
<field name="view_id" ref="view_pos_order_tree_all_sales_lines" />
</record>
@ -386,16 +415,21 @@
<field name="name"/>
<field name="pos_reference"/>
<field name="date_order"/>
<field name="tracking_number"/>
<field name="user_id"/>
<field name="partner_id"/>
<field name="session_id"/>
<filter string="Invoiced" name="invoiced" domain="[('state', '=', 'invoiced')]"/>
<field name="config_id"/>
<field name="lines" string="Product" filter_domain="[('lines.product_id', 'ilike', self)]"/>
<filter string="Invoiced" name="invoiced" domain="[('account_move', '!=', False)]"/>
<filter string="Posted" name="posted" domain="[('state', '=', 'done')]"/>
<filter string="Cancelled" name="cancelled" domain="[('state', '=', 'cancel')]"/>
<separator/>
<filter string="Order Date" name="order_date" date="date_order"/>
<group expand="0" string="Group By">
<group>
<filter string="Session" name="session" domain="[]" context="{'group_by': 'session_id'}"/>
<filter string="User" name="user_id" domain="[]" context="{'group_by': 'user_id'}"/>
<filter string="Point of Sale" name="config_id" domain="[]" context="{'group_by': 'config_id'}"/>
<filter string="Customer" name="customer" domain="[]" context="{'group_by': 'partner_id'}"/>
<filter string="Status" name="status" domain="[]" context="{'group_by': 'state'}"/>
<filter string="Order Date" name="order_month" domain="[]" context="{'group_by': 'date_order'}"/>
@ -404,16 +438,42 @@
</field>
</record>
<!-- REMOVE IN MASTER -->
<record id="pos_rounding_form_view_inherited" model="ir.ui.view">
<field name="name">pos.cash.rounding.form.inherited</field>
<field name="model">account.cash.rounding</field>
<field name="inherit_id" ref="account.rounding_form_view"/>
<field name="arch" type="xml">
<xpath expr="//div[hasclass('oe_title')]" position="before">
<div class="o_notification_alert alert alert-warning" role="alert">
<div class="o_notification_alert alert alert-warning" role="alert" invisible="1">
The Point of Sale only supports the "add a rounding line" rounding strategy.
</div>
</xpath>
</field>
</record>
<record model="ir.actions.server" id="pos_order_set_cancel">
<field name="name">Cancel Order</field>
<field name="model_id" ref="point_of_sale.model_pos_order"/>
<field name="group_ids" eval="[(4, ref('point_of_sale.group_pos_user'))]"/>
<field name="binding_model_id" ref="point_of_sale.model_pos_order" />
<field name="state">code</field>
<field name="binding_view_types">list,kanban,form</field>
<field name="code">
if records:
action = records.action_pos_order_cancel()
</field>
</record>
<record id="model_pos_order_send_mail" model="ir.actions.server">
<field name="name">Send Email</field>
<field name="model_id" ref="point_of_sale.model_pos_order"/>
<field name="binding_model_id" ref="point_of_sale.model_pos_order"/>
<field name="binding_view_types">list,kanban</field>
<field name="state">code</field>
<field name="code">
if records:
action = records.with_context(hide_default_template=True).action_send_mail()
</field>
</record>
</odoo>

View file

@ -6,35 +6,36 @@
<field name="arch" type="xml">
<form string="Payment Methods">
<sheet>
<widget name="web_ribbon" title="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
<widget name="web_ribbon" title="Archived" bg_color="text-bg-danger" invisible="active"/>
<field name="active" invisible="1"/>
<field name="type" invisible="1" />
<div class="oe_title">
<label for="name"/>
<h1><field name="name" placeholder="e.g. Cash" class="oe_inline"/></h1>
<field name="type" invisible="1"/>
<field name="default_pos_receivable_account_name" invisible="1" />
<div class="d-flex justify-content-between">
<div class="oe_title">
<label for="name"/>
<h1><field name="name" placeholder="e.g. Cash" class="oe_inline"/></h1>
</div>
<field name="image" class="oe_avatar" widget='image'/>
</div>
<group name="Payment methods">
<field name="hide_use_payment_terminal" invisible="1"/>
<group>
<field name="split_transactions"/>
<field name="journal_id" attrs="{'required': [('split_transactions', '=', False)]}" placeholder="Leave empty to use the receivable account of customer" />
<field name="outstanding_account_id" groups="account.group_account_readonly" attrs="{'invisible': [('type', '!=', 'bank')]}" placeholder="Leave empty to use the default account from the company setting" />
<field name="receivable_account_id" groups="account.group_account_readonly" attrs="{'invisible': [('split_transactions', '=', True)]}" placeholder="Leave empty to use the default account from the company setting" />
<field name="journal_id" required="not split_transactions" placeholder="Leave empty to use the receivable account of customer" />
<field name="outstanding_account_id" groups="account.group_account_readonly" invisible="type != 'bank'" required="type == 'bank'" placeholder="Selection of outstanding account is required" />
<field name="receivable_account_id" groups="account.group_account_readonly" invisible="split_transactions" widget="many2one" options="{'placeholder_field': 'default_pos_receivable_account_name'}"/>
<field name="company_id" readonly="1" groups="base.group_multi_company" />
<field name="config_ids" widget="many2many_tags" placeholder="No Point of Sale" />
</group>
<group attrs="{'invisible': ['|', ('hide_use_payment_terminal', '=', False), ('type', 'in', ['cash', 'pay_later'])]}">
<div colspan="2">
<h2>Tips:</h2>
<p>
Go to <a href="#" name="%(action_pos_configuration)d" type="action" class="btn-link o_form_uri" role="button">Configurations > Settings</a>
<strong> > Payment Terminals</strong>
in order to install a Payment Terminal and make a fully integrated payment method.
</p>
</div>
</group>
<group attrs="{'invisible': [('hide_use_payment_terminal', '=', True)]}">
<field name="use_payment_terminal" />
</group>
<div>
<group>
<field name="hide_use_payment_terminal" invisible="1"/>
<field name="hide_qr_code_method" invisible="1"/>
<field name="payment_method_type" />
<field name="use_payment_terminal" string="Integrate with" invisible="hide_use_payment_terminal"/>
<field name="qr_code_method" invisible="hide_qr_code_method" required="payment_method_type == 'qr_code'"/>
</group>
<widget name="pos_payment_provider_cards" invisible="use_payment_terminal or payment_method_type != 'terminal'" />
</div>
</group>
</sheet>
</form>
@ -42,18 +43,20 @@
</record>
<record id="pos_payment_method_view_tree" model="ir.ui.view">
<field name="name">pos.payment.method.tree</field>
<field name="name">pos.payment.method.list</field>
<field name="model">pos.payment.method</field>
<field name="arch" type="xml">
<tree string="Payment Methods" create="1" delete="1">
<field name="type" invisible="1"/>
<list string="Payment Methods" create="1" delete="1">
<field name="type" column_invisible="True"/>
<field name="sequence" widget="handle"/>
<field name="name" />
<field name="split_transactions" optional="hide" />
<field name="journal_id" attrs="{'required': [('split_transactions', '=', False)]}" />
<field name="outstanding_account_id" groups="account.group_account_readonly" optional="hide" attrs="{'invisible': [('type', '!=', 'bank')]}" />
<field name="receivable_account_id" groups="account.group_account_readonly" optional="hide" attrs="{'invisible': [('split_transactions', '=', True)]}" />
<field name="journal_id" required="not split_transactions" />
<field name="outstanding_account_id" groups="account.group_account_readonly" optional="hide" invisible="type != 'bank'" />
<field name="receivable_account_id" groups="account.group_account_readonly" optional="hide" invisible="split_transactions" />
<field name="company_id" groups="base.group_multi_company" />
</tree>
<field name="config_ids" widget="many2many_tags"/>
</list>
</field>
</record>
@ -64,8 +67,11 @@
<search string="Payment Methods">
<field name="name"/>
<field name="receivable_account_id" groups="account.group_account_readonly" />
<group expand="1" string="Group By">
<group>
<filter name="group_by_receivable_account" string="Account" domain="[]" context="{'group_by':'receivable_account_id'}"/>
<filter name="group_by_pos_config" string="Point of Sale" domain="[]" context="{'group_by':'config_ids'}"/>
<filter name="group_by_method_name" string="Method Name" domain="[]" context="{'group_by':'name'}"/>
<filter name="group_by_journal_id" string="Journal" domain="[]" context="{'group_by':'journal_id'}"/>
</group>
<filter string="Archived" name="active" domain="[('active', '=', False)]"/>
</search>
@ -74,9 +80,8 @@
<record id="action_pos_payment_method_form" model="ir.actions.act_window">
<field name="name">Payment Methods</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">pos.payment.method</field>
<field name="view_mode">tree,kanban,form</field>
<field name="view_mode">list,kanban,form</field>
<field name="view_id" eval="False"/>
<field name="domain">[]</field>
<field name="context">{'search_default_group_by_account': 1}</field>
@ -99,6 +104,6 @@
<field name="name">Payments Methods</field>
<field name="res_model">pos.payment.method</field>
<field name="view_id" ref="pos_payment_method_view_tree"/>
<field name="view_mode">tree,form,kanban</field>
<field name="view_mode">list,form,kanban</field>
</record>
</odoo>

View file

@ -7,15 +7,20 @@
<form string="Payments" create="0" edit="0" delete="0">
<sheet>
<group>
<field name="currency_id" invisible="1" />
<field name="name" />
<field name="amount" />
<field name="pos_order_id" readonly="1"/>
<field name="payment_method_id" readonly="1"/>
<field name="card_type" readonly="1" attrs="{'invisible': [('card_type', '=', False)]}"/>
<field name="cardholder_name" readonly="1" attrs="{'invisible': [('cardholder_name', '=', False)]}"/>
<field name="transaction_id" readonly="1" attrs="{'invisible': [('transaction_id', '=', False)]}"/>
<field name="session_id" />
<field name="session_id" readonly="0"/>
<field name="pos_order_id"/>
<field name="amount" readonly="0" widget="monetary"/>
<field name="currency_id"/>
<field name="payment_method_id"/>
<field name="payment_method_payment_mode" invisible="not payment_method_payment_mode"/>
<field name="card_type" invisible="not card_type or not card_no"/>
<field name="card_brand" string="Card's Brand" invisible="not card_brand or not card_no"/>
<field name="card_no" invisible="not card_no"/>
<field name="cardholder_name" invisible="not cardholder_name or not card_no"/>
<field name="payment_method_issuer_bank" invisible="not payment_method_issuer_bank"/>
<field name="payment_method_authcode" invisible="not payment_method_authcode"/>
<field name="payment_ref_no" invisible="not payment_ref_no"/>
<field name="transaction_id" invisible="not transaction_id"/>
</group>
</sheet>
</form>
@ -23,16 +28,17 @@
</record>
<record id="view_pos_payment_tree" model="ir.ui.view">
<field name="name">pos.payment.tree</field>
<field name="name">pos.payment.list</field>
<field name="model">pos.payment</field>
<field name="arch" type="xml">
<tree string="Payments" create="0" delete="0">
<field name="currency_id" invisible="1" />
<list string="Payments" create="0" delete="0">
<field name="currency_id" column_invisible="True" />
<field name="payment_date"/>
<field name="payment_method_id" />
<field name="pos_order_id" />
<field name="user_id" widget="many2one_avatar_employee"/>
<field name="amount" />
</tree>
</list>
</field>
</record>
@ -44,7 +50,7 @@
<field name="name"/>
<field name="amount"/>
<field name="pos_order_id" />
<group expand="0" string="Group By">
<group>
<filter name="group_by_payment_method" string="Payment Method" domain="[]" context="{'group_by':'payment_method_id'}"/>
<filter name="group_by_session" string="Session" domain="[]" context="{'group_by':'session_id'}"/>
</group>
@ -54,9 +60,8 @@
<record id="action_pos_payment_form" model="ir.actions.act_window">
<field name="name">Payments</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">pos.payment</field>
<field name="view_mode">tree,form</field>
<field name="view_mode">list,form</field>
<field name="view_id" eval="False"/>
<field name="domain">[]</field>
<field name="context">{'search_default_group_by_payment_method': 1}</field>

View file

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_pos_preset_form" model="ir.ui.view">
<field name="name">pos.preset.form</field>
<field name="model">pos.preset</field>
<field name="arch" type="xml">
<form string="Preset">
<sheet>
<div class="oe_button_box" name="button_box">
<button name="action_open_linked_orders"
type="object"
class="oe_stat_button"
icon="fa-shopping-cart"
invisible="count_linked_orders == 0">
<field string="Order(s)" name="count_linked_orders" widget="statinfo"/>
</button>
<button name="action_open_linked_config"
type="object"
class="oe_stat_button"
icon="fa-share-alt"
invisible="count_linked_config == 0">
<field string="PoS Config" name="count_linked_config" widget="statinfo"/>
</button>
</div>
<field name="image_512" widget="image" class="oe_avatar"/>
<div class="oe_title mb-2">
<label for="name"/>
<h1><field name="name" placeholder="e.g. Dine in"/></h1>
</div>
<group class="w-100" name="Presets">
<group>
<field name="pricelist_id" placeholder="Default"/>
<field name="fiscal_position_id" placeholder="Default"/>
<field name="use_timing" />
<label for="resource_calendar_id" string="Schedule based on" class="fw-bold" />
<div>
<field name="resource_calendar_id" readonly="not use_timing" required="use_timing"/>
</div>
<label for="slots_per_interval" string="Preparation capacity" class="fw-bold" />
<div class="o_row">
<field name="slots_per_interval" class="text-center" readonly="not use_timing" />
<label for="slots_per_interval" string="orders per" />
<field name="interval_time" class="text-center" readonly="not use_timing" />
<label for="interval_time" string="minutes" />
</div>
</group>
<group>
<field name="identification"/>
<label for="return" string="Return mode"/>
<div>
<field id="return" name="is_return" class="oe_inline"/>
<span invisible="not is_return or pricelist_id" class="oe_inline ps-2 text-info">Tip: add a return pricelist (i.e. 0€)</span>
</div>
<field name="color" widget="color_picker"/>
</group>
</group>
<notebook>
<page string="Schedule" name="resource" invisible="not use_timing or not resource_calendar_id">
<field name="attendance_ids" widget="section_one2many" />
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<record id="view_pos_preset_tree" model="ir.ui.view">
<field name="name">pos.preset.list</field>
<field name="model">pos.preset</field>
<field name="arch" type="xml">
<list string="Presets">
<field name="name"/>
<field name="use_timing"/>
<field name="identification"/>
<field name="color" widget="color_picker"/>
</list>
</field>
</record>
<record id="action_pos_preset_form" model="ir.actions.act_window">
<field name="name">Presets</field>
<field name="res_model">pos.preset</field>
<field name="view_mode">list,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Add a new preset
</p>
</field>
</record>
<menuitem id="menu_pos_preset" parent="menu_point_config_product" action="action_pos_preset_form" sequence="3" groups="group_pos_preset"/>
</odoo>

View file

@ -0,0 +1,65 @@
<odoo>
<record id="view_pos_printer_form" model="ir.ui.view">
<field name="name">Preparation Printer</field>
<field name="model">pos.printer</field>
<field name="arch" type="xml">
<form string="POS Printer">
<sheet>
<group>
<group>
<field name="company_id" invisible="1" />
<field name="name" />
<field name="printer_type" widget="radio"/>
<field name="epson_printer_ip" invisible="printer_type != 'epson_epos'"/>
<field name="proxy_ip" invisible="printer_type != 'iot'"/>
<field name="product_categories_ids" />
</group>
<group>
<div style="display:flex; justify-content:flex-end; align-items:flex-start; height:100%;">
<widget name="point_of_sale_test_epos" invisible="printer_type != 'epson_epos'"/>
</div>
</group>
</group>
</sheet>
</form>
</field>
</record>
<record id="action_pos_printer_form" model="ir.actions.act_window">
<field name="name">Preparation Printers</field>
<field name="res_model">pos.printer</field>
<field name="view_mode">list,kanban,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Add a new preparation printer
</p><p>
Preparation printers are typically used by restaurants and bars to print the
orders at the kitchen/bar when the waiter updates an order.
</p><p>
Each printer can be configured to print products from a specific category.
The printer will then only print updates for products belonging to one of
its linked categories.
</p>
</field>
</record>
<record id="view_pos_printer" model="ir.ui.view">
<field name="name">Preparation Printers</field>
<field name="model">pos.printer</field>
<field name="arch" type="xml">
<list string="Preparation Printers">
<field name="name" />
<field name="product_categories_ids" widget="many2many_tags"/>
<field name="proxy_ip" optional="hide"/>
<field name="company_id" optional="hide"/>
</list>
</field>
</record>
<menuitem
name="Preparation Printers"
id="point_of_sale.menu_pos_preparation_printer"
parent="point_of_sale.menu_point_of_sale"
action="action_pos_printer_form"
sequence="99" />
</odoo>

View file

@ -0,0 +1,480 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<template id="pos_session_sales_details">
<div class="page">
<div class="bg-secondary p-3" id="header">
<div class="row">
<div class="col-3 d-flex flex-column justify-content-center">
<br/>
<br/>
<div class="text-start" style="font-size:0.85rem;">
<span t-esc="company.name"/>
<address class="mb-0 text-muted" t-field="env.company.partner_id" t-options='{"widget": "contact", "fields": ["address"], "no_marker": True}'/>
</div>
</div>
<div class="col-6 text-center">
<h2 t-if="state == 'closed' or state == 'opened'" id="daily_report_title">Daily Sales Report
<t t-if="state == 'closed'">Z</t>
<t t-else="">X</t>
</h2>
<t t-if="session_name">
Session ID: <span t-out="session_name">987657</span>
</t>
</div>
</div>
</div>
<div class="row">
<div class="col-12 text-end mt-2">
<span class="badge bg-light text-dark border border-dark p-2">
<t t-set="date_format" t-value="env['res.lang']._get_data(code=env.user.lang).date_format"/>
<strong> As of <span t-esc="context_timestamp(datetime.datetime.now()).strftime(date_format)"/>
</strong>
</span>
</div>
</div>
<div class="text-center" style="break-inside: avoid;">
<t t-if="state == 'multiple'">
<h2>Sales Details</h2>
<div class="oe_structure"></div>
<t t-if="config_names">
<strong>Config names</strong>
<t t-foreach="config_names" t-as="name">
<span t-out="name">Sample Config Name</span>,
</t>
</t>
</t>
<t t-if="date_start and date_stop">
<span t-out="date_start" t-options="{'widget': 'datetime'}">2-03-2000 9:00 AM</span> - <span t-out="date_stop" t-options="{'widget': 'datetime'}">Demo 3-03-2000 5:00 PM</span>
</t>
</div>
<br/>
<br/>
<div class="oe_structure"></div>
<!-- Orderlines -->
<div t-if="products" id="sales">
<h6 class="bg-secondary p-1 fw-bold">Sales</h6>
<div class="oe_structure"></div>
<table class="table table-sm table-borderless" >
<tbody>
<tr t-foreach="products" t-as="category" class="border-bottom border-secondary">
<td class="ps-2 fw-bold"><span t-out="category['name']">Technical Stuffs</span></td>
<td class="fw-bold"/>
<td class="fw-bold"/>
<td class="text-end fw-bold" ><span t-out="category['qty']">5</span></td>
<td class="text-end fw-bold">
<t t-if="currency['position']">
<span t-out="category['total']" t-options="{'widget': 'float', 'precision': currency['precision']}">10000.00</span><span t-out='currency["symbol"]'>$</span>
</t>
<t t-else="" >
<span t-out='currency["symbol"]'>$</span><span t-out="category['total']" t-options="{'widget': 'float', 'precision': currency['precision']}">10000.00</span>
</t>
</td>
<tr t-foreach="category['products']" t-as="line" class="border-bottom border-secondary">
<td class="ps-5"><span t-out="line['product_name']">Laptop model x</span><span t-if="line['combo_products_label']" t-out="line['combo_products_label']"/></td>
<td/>
<td class="text-end">
<t t-if="line['barcode']">
<img t-att-src="'/report/barcode/Code128/'+line['barcode']" style="width:230px; height:23px" alt="Barcode"/>
</t>
</td>
<td class="text-end">
<span t-out="line['quantity']">5</span>
<t t-if='line["uom"] != "Units"'>
<span t-out='line["uom"]'>Unit</span>
</t>
</td>
<td class="text-end">
<t t-if="currency['position']">
<span t-out='line["base_amount"]' t-options="{'widget': 'float', 'precision': currency['precision']}">567789</span><span t-out='currency["symbol"]'>$</span>
</t>
<t t-else="" >
<span t-out='currency["symbol"]'>$</span><span t-out='line["base_amount"]' t-options="{'widget': 'float', 'precision': currency['precision']}">567789</span>
</t>
<t t-if='line["discount"] != 0'>
Disc: <span t-out='line["discount"]'>45</span>%
</t>
</td>
</tr>
</tr>
<tr>
<td><strong>Total</strong></td>
<td/>
<td/>
<td class="text-end"><strong><span t-out="products_info['qty']">5</span></strong></td>
<td class="text-end">
<t t-if="currency['position']">
<strong><span t-out='products_info["total"]' t-options="{'widget': 'float', 'precision': currency['precision']}">10000</span><span t-out='currency["symbol"]'>$</span></strong>
</t>
<t t-else="" >
<strong><span t-out='currency["symbol"]'>$</span><span t-out='products_info["total"]' t-options="{'widget': 'float', 'precision': currency['precision']}">1000</span></strong>
</t>
</td>
</tr>
</tbody>
</table>
</div>
<div class="oe_structure"></div>
<div t-if="taxes" id="taxe_sales" style="page-break-inside: avoid;">
<h6 class="bg-secondary p-1 fw-bold w-50 ms-auto">Taxes on sales</h6>
<table class="table table-sm table-borderless w-50 ms-auto" >
<tbody>
<tr t-foreach='taxes' t-as='tax' class="border-bottom border-secondary">
<td class="ps-2 fw-bold"><span t-out="tax['name']">Demo Name</span></td>
<td class="text-end">
<t t-if="currency['position']">
<span t-out="tax['tax_amount']" t-options="{'widget': 'float', 'precision': currency['precision']}">0.00</span><span t-out='currency["symbol"]'>$</span>
</t>
<t t-else="" >
<span t-out='currency["symbol"]'>$</span><span t-out="tax['tax_amount']" t-options="{'widget': 'float', 'precision': currency['precision']}">0.00</span>
</t>
</td>
<td class="text-end">
<t t-if="currency['position']">
<span t-out="tax['base_amount']" t-options="{'widget': 'float', 'precision': currency['precision']}">0.00</span><span t-out='currency["symbol"]'>$</span>
</t>
<t t-else="" >
<span t-out='currency["symbol"]'>$</span><span t-out="tax['base_amount']" t-options="{'widget': 'float', 'precision': currency['precision']}">0.00</span>
</t>
</td>
</tr>
<tr>
<td><strong>Total</strong></td>
<td class="text-end">
<t t-if="currency['position']">
<strong><span t-out='taxes_info["tax_amount"]' t-options="{'widget': 'float', 'precision': currency['precision']}">0.00</span><span t-out='currency["symbol"]'>$</span></strong>
</t>
<t t-else="" >
<strong><span t-out='currency["symbol"]'>$</span><span t-out='taxes_info["tax_amount"]' t-options="{'widget': 'float', 'precision': currency['precision']}">0.00</span></strong>
</t>
</td>
<td class="text-end">
<t t-if="currency['position']">
<strong><span t-out='taxes_info["base_amount"]' t-options="{'widget': 'float', 'precision': currency['precision']}">0.00</span><span t-out='currency["symbol"]'>$</span></strong>
</t>
<t t-else="" >
<strong><span t-out='currency["symbol"]'>$</span><span t-out='taxes_info["base_amount"]' t-options="{'widget': 'float', 'precision': currency['precision']}">0.00</span></strong>
</t>
</td>
</tr>
</tbody>
</table>
<div class="oe_structure"></div>
</div>
<div t-if="refund_products" id="refunds">
<h6 class="bg-secondary p-1 fw-bold">Refunds</h6>
<table class="table table-sm table-borderless" >
<tbody>
<tr t-foreach="refund_products" t-as="category" class="border-bottom border-secondary">
<td class="ps-2 fw-bold"><span t-out="category['name']">Technical Stuff</span></td>
<td class="fw-bold"/>
<td class="fw-bold"/>
<td class="text-end fw-bold">
<span t-out="category['qty']">0</span>
</td>
<td class="text-end fw-bold">
<t t-if="currency['position']">
<span t-out="category['total']" t-options="{'widget': 'float', 'precision': currency['precision']}">0.00</span><span t-out='currency["symbol"]'>$</span>
</t>
<t t-else="" >
<span t-out='currency["symbol"]'>$</span><span t-out="category['total']" t-options="{'widget': 'float', 'precision': currency['precision']}">0.00</span>
</t>
</td>
<tr t-foreach="category['products']" t-as="line" class="border-bottom border-secondary">
<td class="ps-5"><span t-out="line['product_name']">Laptop</span><span t-if="line['combo_products_label']" t-out="line['combo_products_label']"/></td>
<td/>
<td class="text-end">
<t t-if="line['barcode']">
<img t-att-src="'/report/barcode/Code128/'+line['barcode']" style="width:230px; height:23px" alt="Barcode"/>
</t>
</td>
<td class="text-end">
<span t-out="line['quantity']">0</span>
<t t-if='line["uom"] != "Units"'>
<span t-out='line["uom"]'>Unit</span>
</t>
</td>
<td class="text-end">
<t t-if="currency['position']">
<span t-out='line["base_amount"]' t-options="{'widget': 'float', 'precision': currency['precision']}">0.00</span><span t-out='currency["symbol"]'>$</span>
</t>
<t t-else="" >
<span t-out='currency["symbol"]'>$</span><span t-out='line["base_amount"]' t-options="{'widget': 'float', 'precision': currency['precision']}">0.00</span>
</t>
<t t-if='line["discount"] != 0'>
Disc: <span t-out='line["discount"]'>0</span>%
</t>
</td>
</tr>
</tr>
<tr>
<td><strong>Total</strong></td>
<td/>
<td/>
<td class="text-end">
<strong><span t-out="refund_info['qty']">0</span></strong>
</td>
<td class="text-end">
<t t-if="currency['position']">
<strong><span t-out='refund_info["total"]' t-options="{'widget': 'float', 'precision': currency['precision']}">0.00</span><span t-out='currency["symbol"]'>$</span></strong>
</t>
<t t-else="" >
<strong><span t-out='currency["symbol"]'>$</span><span t-out='refund_info["total"]' t-options="{'widget': 'float', 'precision': currency['precision']}">0.00</span></strong>
</t>
</td>
</tr>
</tbody>
</table>
<div class="oe_structure"></div>
</div>
<div t-if="refund_taxes" id="taxe_refunds" style="page-break-inside: avoid;">
<h6 class="bg-secondary p-1 fw-bold w-50 ms-auto">Taxes on refunds</h6>
<table class="table table-sm table-borderless w-50 ms-auto" >
<tbody>
<tr t-foreach='refund_taxes' t-as='tax' class="border-bottom border-secondary">
<td class="ps-2 fw-bold"><span t-out="tax['name']">Tax Name</span></td>
<td class="text-end">
<span t-if="currency['position']">
<span t-out="tax['tax_amount']" t-options="{'widget': 'float', 'precision': currency['precision']}">123.45</span><span t-out='currency["symbol"]'>$</span>
</span>
<span t-else="">
<span t-out='currency["symbol"]'>$</span><span t-out="tax['tax_amount']" t-options="{'widget': 'float', 'precision': currency['precision']}">123.45</span>
</span>
</td>
<td class="text-end">
<span t-if="currency['position']">
<span t-out="tax['base_amount']" t-options="{'widget': 'float', 'precision': currency['precision']}">123.45</span><span t-out='currency["symbol"]'>$</span>
</span>
<span t-else="">
<span t-out='currency["symbol"]'>$</span><span t-out="tax['base_amount']" t-options="{'widget': 'float', 'precision': currency['precision']}">123.45</span>
</span>
</td>
</tr>
<tr>
<td><strong>Total</strong></td>
<td class="text-end">
<span t-if="currency['position']">
<strong><span t-out='refund_taxes_info["tax_amount"]' t-options="{'widget': 'float', 'precision': currency['precision']}">123.45</span><span t-out='currency["symbol"]'>$</span></strong>
</span>
<span t-else="">
<strong><span t-out='currency["symbol"]'>$</span><span t-out='refund_taxes_info["tax_amount"]' t-options="{'widget': 'float', 'precision': currency['precision']}">123.45</span></strong>
</span>
</td>
<td class="text-end">
<span t-if="currency['position']">
<strong><span t-out='refund_taxes_info["base_amount"]' t-options="{'widget': 'float', 'precision': currency['precision']}">123.45</span><span t-out='currency["symbol"]'>$</span></strong>
</span>
<span t-else="">
<strong><span t-out='currency["symbol"]'>$</span><span t-out='refund_taxes_info["base_amount"]' t-options="{'widget': 'float', 'precision': currency['precision']}">123.45</span></strong>
</span>
</td>
</tr>
</tbody>
</table>
<div class="oe_structure"></div>
</div>
<div class="oe_structure"></div>
<div t-if="payments" id="payments" style="page-break-inside: avoid;">
<t t-if="payments" id="other_payments">
<h6 class="bg-secondary p-1 fw-bold w-50 ms-auto">Payments</h6>
<table class="table table-sm table-borderless w-50 ms-auto" >
<tbody>
<tr t-foreach='payments' t-as='payment'>
<td class="ps-2 fw-bold" ><span t-out="payment['name']">Payment Name Demo</span></td>
<td class="text-end">
<span t-if="currency['position']">
<span t-out="payment['total']" t-options="{'widget': 'float', 'precision': currency['precision']}">123.45</span><span t-out='currency["symbol"]'>$</span>
</span>
<span t-else="">
<span t-out='currency["symbol"]'>$</span><span t-out="payment['total']" t-options="{'widget': 'float', 'precision': currency['precision']}">123.45</span>
</span>
</td>
</tr>
</tbody>
</table>
<table class="table table-sm table-borderless w-50 ms-auto border-top">
<tr class="fs-5">
<th class="ps-2 fw-bolder">Total</th>
<th class="text-end fw-bolder">
<t t-if="currency['position']">
<span t-out="currency['total_paid']" t-options="{'widget': 'float', 'precision': currency['precision']}">11.11</span><span t-out="currency['symbol']">$</span>
</t>
<t t-else="">
<span t-out="currency['symbol']">$</span><span t-out="currency['total_paid']" t-options="{'widget': 'float', 'precision': currency['precision']}">11.11</span>
</t>
</th>
</tr>
<tr t-if="show_payment_per_method" t-foreach="payments_per_method" t-as="ppm">
<td class="ps-2 fw-bold" ><t t-out="ppm['name']"/></td>
<td class="text-end">
<t t-if="currency['position']">
<span t-out="ppm['total']" t-options="{'widget': 'float', 'precision': currency['precision']}">38.83</span><span t-out="currency['symbol']">$</span>
</t>
<t t-else="">
<span t-out="currency['symbol']">$</span><span t-out="ppm['total']" t-options="{'widget': 'float', 'precision': currency['precision']}">38.83</span>
</t>
</td>
</tr>
</table>
<div class="oe_structure"></div>
</t>
</div>
<div id="discounts" style="break-inside: avoid; page-break-inside: avoid;">
<h6 class="bg-secondary p-1 fw-bold">Discounts</h6>
<div class="row">
<div class="col-12">
<strong>Number of discounts</strong>: <span t-out="discount_number">5</span>
</div>
</div>
<div class="row">
<div class="col-12">
<strong>Amount of discounts</strong>:
<span t-if="currency['position']">
<span t-out="discount_amount" t-options="{'widget': 'float', 'precision': currency['precision']}">50.00</span>
<span t-out='currency["symbol"]'>$</span>
</span>
<span t-else="">
<span t-out='currency["symbol"]'>$</span>
<span t-out="discount_amount" t-options="{'widget': 'float', 'precision': currency['precision']}">50.00</span>
</span>
</div>
</div>
<br/>
</div>
<div class="oe_structure"></div>
<div t-if="invoiceTotal" id="invoices">
<br/>
<h6 class="bg-secondary p-1 fw-bold">Invoices</h6>
<table class="table table-sm table-borderless" >
<tbody>
<t t-foreach="invoiceList" t-as="invoiceSession" class="border-bottom border-secondary">
<t t-if="invoiceSession['invoices']">
<tr t-foreach='invoiceSession["invoices"]' t-as='invoice'>
<td class="ps-2 fw-bold"><span t-out="invoice['name']">Invoice Name</span></td>
<td><span t-out="invoice['order_ref']">Order Ref</span></td>
<td class="text-end">
<span t-if="currency['position']">
<span t-out="invoice['total']" t-options="{'widget': 'float', 'precision': currency['precision']}">123.45</span><span t-out='currency["symbol"]'>$</span>
</span>
<span t-else="">
<span t-out='currency["symbol"]'>$</span><span t-out="invoice['total']" t-options="{'widget': 'float', 'precision': currency['precision']}">123.45</span>
</span>
</td>
</tr>
</t>
</t>
<tr>
<td><strong>Total</strong></td>
<td/>
<td class="text-end"><strong>
<span t-if="currency['position']">
<span t-out="invoiceTotal" t-options="{'widget': 'float', 'precision': currency['precision']}">123.45</span><span t-out='currency["symbol"]'>$</span>
</span>
<span t-else="">
<span t-out='currency["symbol"]'>$</span><span t-out="invoiceTotal" t-options="{'widget': 'float', 'precision': currency['precision']}">123.45</span>
</span>
</strong></td>
</tr>
</tbody>
</table>
</div>
<div class="oe_structure"></div>
<t id="closing_session">
<h6 class="bg-secondary p-1 fw-bold">Session Control</h6>
<div class="oe_structure"></div>
<div style="break-inside: avoid;">
<strong>Total:
<span t-if="currency['position']">
<span t-out='currency["total_paid"]' t-options="{'widget': 'float', 'precision': currency['precision']}">99.99</span><span t-out='currency["symbol"]'>$</span>
</span>
<span t-else="">
<span t-out='currency["symbol"]'>$</span><span t-out='currency["total_paid"]' t-options="{'widget': 'float', 'precision': currency['precision']}">99.99</span>
</span>
</strong>
<br/>
<strong>Number of transactions: <span t-out="nbr_orders">10</span></strong>
</div>
<br/>
<div class="oe_structure"></div>
<table class="table table-sm table-borderless" >
<thead><tr>
<th class="text-start">Name</th>
<th/>
<th class="text-end">Expected</th>
<th t-if="(state == 'closed' or state == 'multiple') and payments" class="text-end">Counted</th>
<th t-if="(state == 'closed' or state == 'multiple') and payments" class="text-end">Difference</th>
</tr></thead>
<tbody>
<t t-foreach="payments" t-as="method">
<t t-if="method['count']">
<tr>
<td><strong><span t-out="method['name']">Cash</span></strong></td>
<td/>
<td class="text-end">
<span t-if="currency['position']">
<span t-out="method['final_count']" t-options="{'widget': 'float', 'precision': currency['precision']}">100.00</span><span t-out='currency["symbol"]'>$</span>
</span>
<span t-else="">
<span t-out='currency["symbol"]'>$</span><span t-out="method['final_count']" t-options="{'widget': 'float', 'precision': currency['precision']}">100.00</span>
</span>
</td>
<td t-if="(state == 'closed' or state == 'multiple') and payments" class="text-end">
<span t-if="currency['position']">
<span t-out="method['money_counted']" t-options="{'widget': 'float', 'precision': currency['precision']}">95.00</span><span t-out='currency["symbol"]'>$</span>
</span>
<span t-else="">
<span t-out='currency["symbol"]'>$</span><span t-out="method['money_counted']" t-options="{'widget': 'float', 'precision': currency['precision']}">95.00</span>
</span>
</td>
<td t-if="(state == 'closed' or state == 'multiple') and payments" class="text-end">
<span t-if="currency['position']">
<span t-out="method['money_difference']" t-options="{'widget': 'float', 'precision': currency['precision']}">5.00</span><span t-out='currency["symbol"]'>$</span>
</span>
<span t-else="">
<span t-out='currency["symbol"]'>$</span><span t-out="method['money_difference']" t-options="{'widget': 'float', 'precision': currency['precision']}">5.00</span>
</span>
</td>
</tr>
<tr t-if="(state == 'closed' or state == 'multiple') and payments" t-foreach="method['cash_moves']" t-as="move">
<td/>
<td><span t-out="move['name']">Cash Move 1</span></td>
<td class="text-end">
<span t-if="currency['position']">
<span t-out="move['amount']" t-options="{'widget': 'float', 'precision': currency['precision']}">50.00</span><span t-out='currency["symbol"]'>$</span>
</span>
<span t-else="">
<span t-out='currency["symbol"]'>$</span><span t-out="move['amount']" t-options="{'widget': 'float', 'precision': currency['precision']}">50.00</span>
</span>
</td>
<td></td>
<td></td>
</tr>
</t>
</t>
</tbody>
</table>
<div class="oe_structure"></div>
<div t-if="opening_note or closing_note" style="break-inside: avoid;">
<br/>
<br/>
<span t-if="opening_note" id="opening_note">
<strong>Opening of session note:</strong>
<span t-out="opening_note" t-options="{'widget': 'text'}">Sample Opening Note</span>
</span>
<br/>
<span t-if="closing_note" id="closing_note">
<strong>End of session note:</strong>
<span t-out="closing_note" t-options="{'widget': 'text'}">Sample Closing Note</span>
</span>
</div>
</t>
<div id="end_report" style="page-break-after: always;"/>
</div>
</template>
</data>
</odoo>

View file

@ -7,10 +7,9 @@
<form string="Point of Sale Session" create="0" edit="0">
<header>
<button name="open_frontend_cb" type="object" string="Continue Selling"
attrs="{'invisible' : ['|', ('rescue', '=', True), ('state', 'not in', ['opening_control', 'opened'])]}"/>
<button id="validate_closing_control" name="action_pos_session_closing_control" type="object" string="Close Session &amp; Post Entries" states="closing_control"
attrs="{'invisible': [ '|', '&amp;',('state', '!=', 'closing_control'), ('rescue', '=', False),
'&amp;',('state', '=', 'closed'), ('rescue', '=', True)]}"
invisible="rescue or state not in ['opening_control', 'opened']"/>
<button id="validate_closing_control" name="action_pos_session_closing_control" type="object" string="Close Session &amp; Post Entries"
invisible="(state != 'closing_control' and not rescue or state == 'closed' and rescue) and state != 'closing_control'"
class="oe_highlight"/>
<field name="state" widget="statusbar" statusbar_visible="opened,closing_control,closed" nolabel="1" />
</header>
@ -24,9 +23,9 @@
type="object">
<field name="order_count" widget="statinfo" string="Orders"/>
</button>
<button class="oe_stat_button" name="action_stock_picking" type="object" icon="fa-truck" attrs="{'invisible':[('picking_count', '=', 0)]}">
<field name="picking_count" widget="statinfo" string="Pickings" attrs="{'invisible': [('failed_pickings', '!=', False)]}"/>
<field name="picking_count" widget="statinfo" string="Pickings" class="text-danger" attrs="{'invisible': [('failed_pickings', '=', False)]}"/>
<button class="oe_stat_button" name="action_stock_picking" type="object" icon="fa-truck" invisible="picking_count == 0">
<field name="picking_count" widget="statinfo" string="Pickings" invisible="failed_pickings"/>
<field name="picking_count" widget="statinfo" string="Pickings" class="text-danger" invisible="not failed_pickings"/>
</button>
<button
name="action_show_payments_list"
@ -41,56 +40,59 @@
type="object"
class="oe_stat_button"
icon="fa-bars"
string="Journal Items"
groups="account.group_account_readonly"
>
<div class="o_stat_info">
<span class="o_stat_text">Journal Items</span>
</div>
</button>
<button
name="show_cash_register"
type="object"
class="oe_stat_button"
icon="fa-bars"
string="Cash Register"
attrs="{'invisible':[('cash_control', '=', False)]}"
groups="account.group_account_readonly"
/>
invisible="not cash_control"
groups="account.group_account_readonly">
<div class="o_stat_info">
<span class="o_stat_text">Cash Register</span>
</div>
</button>
</div>
<h1 class="oe_title">
<field name="name" attrs="{'invisible': [('name','=','/')]}" class="oe_inline"/>
<field name="name" invisible="name == '/'" class="oe_inline"/>
</h1>
<group>
<field name="cash_control" invisible="1" />
<field name="user_id"/>
<field name="user_id" readonly="state != 'opening_control'"/>
<field name="currency_id" invisible="1"/>
<field name="config_id" readonly="1"/>
<field name="move_id" readonly="1" groups="account.group_account_readonly" />
<field name="start_at" attrs="{'invisible' : [('state', '=', 'opening_control')]}"/>
<field name="stop_at" attrs="{'invisible' : [('state', '!=', 'closed')]}"/>
<field name="start_at" invisible="state == 'opening_control'"/>
<field name="stop_at" invisible="state != 'closed'"/>
<field name="cash_register_balance_start"/>
<field name="cash_register_balance_end_real" attrs="{'invisible': [('state', '!=', 'closed')]}"/>
<field name="cash_register_balance_end_real" invisible="state != 'closed'"/>
</group>
</sheet>
<div class="oe_chatter">
<field name="activity_ids"/>
<field name="message_follower_ids"/>
<field name="message_ids"/>
</div>
<chatter/>
</form>
</field>
</record>
<record id="view_pos_session_tree" model="ir.ui.view">
<field name="name">pos.session.tree.view</field>
<field name="name">pos.session.list.view</field>
<field name="model">pos.session</field>
<field name="arch" type="xml">
<tree string="Point of Sale Session" create="0" sample="1">
<list string="Point of Sale Session" create="0" sample="1">
<field name="name" decoration-bf="1"/>
<field name="config_id" />
<field name="user_id" widget="many2one_avatar_user"/>
<field name="user_id" widget="many2one_avatar_user" readonly="state != 'opening_control'"/>
<field name="start_at" />
<field name="stop_at" />
<field name="cash_register_balance_start"/>
<field name="cash_register_balance_end_real"/>
<field name="cash_register_balance_end"/>
<field name="state" widget="badge" decoration-info="state in ('opening_control')" decoration-success="state in ('opened', 'closed')" decoration-warning="state == 'closing_control'" />
</tree>
</list>
</field>
</record>
@ -99,33 +101,18 @@
<field name="model">pos.session</field>
<field name="arch" type="xml">
<kanban class="o_kanban_mobile" create="0" sample="1">
<field name="config_id" />
<field name="name" />
<field name="user_id" />
<field name="start_at" />
<field name="state" />
<templates>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_card oe_kanban_global_click">
<div class="o_kanban_record_top">
<div class="o_kanban_record_headings">
<strong class="o_kanban_record_title"><span><field name="config_id"/></span></strong>
</div>
<field name="state" widget="label_selection" options="{'classes': {'opening_control': 'default',
'opened': 'success', 'closing_control': 'warning', 'closed': 'warning'}}"/>
</div>
<div class="o_kanban_record_body">
<field name="name" />
</div>
<div class="o_kanban_record_bottom">
<div class="oe_kanban_bottom_left">
<span><field name="start_at" /></span>
</div>
<div class="oe_kanban_bottom_right">
<field name="user_id" widget="many2one_avatar_user"/>
</div>
</div>
<t t-name="card">
<div class="d-flex">
<field name="config_id" class="fw-bolder mb-1"/>
<field name="state" widget="label_selection" options="{'classes': {'opening_control': 'default',
'opened': 'success', 'closing_control': 'warning', 'closed': 'warning'}}" class="ms-auto"/>
</div>
<field name="name" />
<footer class="pt-1">
<field name="start_at" />
<field name="user_id" widget="many2one_avatar_user" readonly="state != 'opening_control'" class="ms-auto"/>
</footer>
</t>
</templates>
</kanban>
@ -145,7 +132,7 @@
<filter name="open_sessions" string="In Progress" domain="[('state', '=', 'opened')]"/>
<separator/>
<filter string="Opening Date" name="start_date" date="start_at" />
<group expand="0" string="Group By">
<group>
<filter string="Opened By" name="user" domain="[]" context="{'group_by' : 'user_id'}"/>
<filter string="Point of Sale" name="point_of_sale" domain="[]" context="{'group_by': 'config_id'}"/>
<filter string="Status" name="status" domain="[]" context="{'group_by': 'state'}"/>
@ -158,9 +145,9 @@
<record id="action_pos_session" model="ir.actions.act_window">
<field name="name">Sessions</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">pos.session</field>
<field name="view_mode">tree,kanban,form</field>
<field name="path">pos-sessions</field>
<field name="view_mode">list,kanban,form</field>
<field name="search_view_id" ref="view_pos_session_search" />
<field name="help" type="html">
<p class="o_view_nocontent_empty_folder">

View file

@ -5,8 +5,8 @@
<template id="ticket_validation_screen">
<t t-call="portal.portal_layout">
<t t-set="no_breadcrumbs" t-value="True"/>
<div class="row justify-content-md-center">
<form method="post" target="_self" t-att-action="'/pos/ticket/validate'">
<div class="row justify-content-md-center o_customer_address_fill">
<form method="post" target="_self" t-att-action="'/pos/ticket/validate'" onsubmit="$('button:submit').attr('disabled', 'disabled')" class="address_autoformat">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
<input type="hidden" name="access_token" t-att-value="access_token"/>
<div class="col-12 col-md-6 mt-4 offset-md-3">
@ -58,7 +58,7 @@
<t t-if="partner.company_name">
, <t t-out="partner.company_name"/>
</t><br />
<t t-if="partner.vat">
<t id="partner_vat" t-if="partner.vat">
<t t-out="partner.vat" /><br />
</t>
<t t-out="partner_address"/> <a role="button" t-att-href="address_url" class="btn btn-sm btn-link"><i class="fa fa-pencil"/> Edit</a>
@ -88,14 +88,14 @@
</t>
<t t-else="">
<div class="row mt-4">
<div class="col-12">
<div class="col-12" id="get_info_div">
<h4>Please enter your billing information <small class="text-muted">or</small> <a role="button" t-att-href="'/web/login?redirect=/pos/ticket/validate?access_token=%s' % access_token" style="margin-top: -11px"> Sign in</a>:</h4>
</div>
</div>
<div class="row o_portal_details">
<div class="row portal_details">
<div class="col-lg-12">
<div class="row">
<t t-call="portal.portal_my_details_fields" />
<t t-call="portal.address_form_fields"/>
<t t-if="partner_required_fields">
<t t-set="required_fields" t-value="partner_required_fields"/>
<t t-set="field_prefix" t-value="'partner_'"/>
@ -118,12 +118,12 @@
</t>
</t>
<div class="row mt-4">
<div class="col-12 col-md-4">
<div class="col-12 col-md-4" id="get_my_invoice">
<t t-if="user_is_connected and not partner_address">
<button class="btn btn-primary w-100" disabled="True">Get my invoice</button>
<button class="btn btn-primary btn-lg lh-lg w-100" disabled="True">Get my invoice</button>
</t>
<t t-else="">
<button class="btn btn-primary w-100">Get my invoice</button>
<button class="btn btn-primary btn-lg lh-lg w-100">Get my invoice</button>
</t>
</div>
</div>
@ -132,4 +132,51 @@
</div>
</t>
</template>
<template id="ticket_request_with_code" name="Invoice Request">
<t t-call="portal.portal_layout">
<t t-set="no_breadcrumbs" t-value="True"/>
<div class="row justify-content-md-center">
<form method="post" target="_self" t-att-action="'/pos/ticket'">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
<div class="col-12 col-md-6 mt-4 offset-md-3">
<div class="row">
<div t-if="banner_error" class="alert alert-danger" role="alert">
<div class="col-lg-12">
<t t-esc="banner_error"/>
</div>
</div>
<h2>Invoice Request</h2>
<hr class="mt-1 mb-0"/>
<div class="row">
<div class="col-lg-12">
<div class="row">
<div t-attf-class="col-12 mb-6 col-xl-8">
<label class="col-form-label" for="pos_reference">Ticket Nr</label>
<input type="text" name="pos_reference" placeholder="0014-001-00001"
t-attf-class="form-control #{errors.get('pos_reference') and 'is-invalid' or ''}"
t-att-value="form_values.get('pos_reference')"/>
<label class="col-form-label" for="date_order">Date</label>
<input type="date" name="date_order"
t-attf-class="form-control #{errors.get('date_order') and 'is-invalid' or ''}"
t-att-value="form_values.get('date_order')"/>
<label class="col-form-label" for="ticket_code">Unique code</label>
<input type="text" name="ticket_code" placeholder="qx9h1"
t-attf-class="form-control #{errors.get('ticket_code') and 'is-invalid' or ''}"
t-att-value="form_values.get('ticket_code')"/>
</div>
</div>
</div>
</div>
<div class="row mt-4">
<div class="col-12">
<button class="btn btn-primary">Request Invoice</button>
</div>
</div>
</div>
</div>
</form>
</div>
</t>
</template>
</odoo>

View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="point_of_sale.product_combo_view_form" model="ir.ui.view">
<field name="name">product.combo.form.inherit.point.of.sale</field>
<field name="model">product.combo</field>
<field name="inherit_id" ref="product.product_combo_view_form"/>
<field name="arch" type="xml">
<field name="product_id" position="attributes">
<attribute name="context">{'default_available_in_pos': True}</attribute>
</field>
<xpath expr="//field[@name='company_id']" position="replace">
<group>
<span class="o_form_label oe_inline fw-bolder">Maximum</span>
<div>
<field name="qty_max" class="text-center" style="width:50px;"/>
<label for="qty_max" string="items" class="fw-bolder ps-3" />
</div>
<span class="o_form_label oe_inline fw-bolder">Includes</span>
<div>
<field name="qty_free" class="text-center" style="width:50px;"/>
<label for="qty_free" string="items" class="fw-bolder ps-3" />
</div>
</group>
<group>
<field name="base_price" widget="monetary" options="{'field_digits': True}"/>
<field
name="company_id"
placeholder="Visible to all"
groups="base.group_multi_company"
options="{'no_create': True}"
class="oe_inline"
/>
</group>
</xpath>
</field>
</record>
</odoo>

View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Product Tags -->
<record id="product_tag_form_view_inherit_point_of_sale" model="ir.ui.view">
<field name="name">product.tag.form.inherit.point.of.sale</field>
<field name="model">product.tag</field>
<field name="inherit_id" ref="product.product_tag_form_view"/>
<field name="priority" eval="100"/>
<field name="arch" type="xml">
<xpath expr="//form/sheet/group" position="after">
<group name="pos" string="Point of Sale">
<field name="pos_description"/>
</group>
</xpath>
</field>
</record>
<menuitem id="pos_menu_products_tag_action" action="product.product_tag_action"
parent="point_of_sale.pos_menu_products_configuration" sequence="3"/>
</odoo>

View file

@ -5,29 +5,36 @@
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_search_view"/>
<field name="arch" type="xml">
<filter name="filter_to_sell" position="before">
<filter name="filter_to_availabe_pos" string="Available in POS" domain="[('available_in_pos', '=', True)]"/>
<field name="categ_id" position="after">
<field string="POS Product Category" name="pos_categ_ids" filter_domain="[('pos_categ_ids', 'child_of', raw_value)]"/>
</field>
<filter name="filter_to_sell" position="after">
<filter name="filter_to_availabe_pos" string="Point of Sale" domain="[('available_in_pos', '=', True)]"/>
</filter>
<filter name="categ_id" position="after">
<filter string="POS Product Category" name="pos_categ_id" context="{'group_by':'pos_categ_id'}"/>
<filter name="group_by_categ_id" position="after">
<filter string="POS Category" name="pos_categ_ids" context="{'group_by': 'pos_categ_ids'}"/>
</filter>
</field>
</record>
<record id="product_template_action_pos_product" model="ir.actions.act_window">
<field name="name">Products</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">product.template</field>
<field name="view_mode">kanban,tree,form,activity</field>
<field name="context" eval="{'search_default_filter_to_availabe_pos': 1, 'default_available_in_pos': True, 'create_variant_never': 'no_variant'}"/>
<field name="view_mode">kanban,list,form,activity</field>
<field name="context">{'search_default_filter_to_availabe_pos': 1, 'default_available_in_pos': True, 'create_variant_never': 'no_variant', '_pos_self_order': True, 'list_view_ref': 'point_of_sale.product_template_tree_view_point_of_sale'}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create new product
</p><p>
Define products and categories for POS retail and restaurant
</p>
</field>
</record>
<record id="product_product_action" model="ir.actions.act_window">
<field name="name">Product Variants</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">product.product</field>
<field name="view_mode">kanban,tree,form,activity</field>
<field name="context" eval="{'search_default_filter_to_availabe_pos': 1, 'default_available_in_pos': True}"/>
<field name="domain" eval="[]"/>
<field name="view_mode">kanban,list,form,activity</field>
<field name="context">{'search_default_filter_to_availabe_pos': 1, 'default_available_in_pos': True}</field>
<field name="search_view_id" eval="False"/> <!-- Force empty -->
<field name="view_id" ref="product.product_product_tree_view"/>
<field name="help" type="html">
@ -41,38 +48,66 @@
</record>
<record id="product_category_action" model="ir.actions.act_window">
<field name="name">Internal Categories</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">product.category</field>
<field name="search_view_id" ref="product.product_category_search_view"/>
<field name="view_id" ref="product.product_category_list_view"/>
</record>
<record id="product_template_only_form_view" model="ir.ui.view">
<field name="name">product.template.only.form.inherit</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_only_form_view"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='attribute_line_ids']//field[@name='attribute_id']" position="attributes">
<attribute name="context">{'default_create_variant': context.get('create_variant_never', 'always')}</attribute>
</xpath>
</field>
</record>
<record id="product_template_form_view" model="ir.ui.view">
<field name="name">product.template.form.inherit</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='sales']" position="attributes">
<attribute name="invisible">0</attribute>
<attribute name="invisible" remove="1" separator="or"/>
</xpath>
<xpath expr="//page[@name='sales']/group[@name='sale']" position="inside">
<group name="pos" string="Point of Sale" attrs="{'invisible': [('sale_ok','=',False)]}">
<page name="sales" position="after">
<page string="Point of Sale" name="pos" invisible="not available_in_pos">
<group>
<group name="pos" string="Point of Sale">
<field name="color" invisible="True"/>
<field name="to_weight" invisible="type=='service'"/>
<field name="pos_categ_ids"
widget="many2many_tags"
groups="point_of_sale.group_pos_user"
string="Category"
options="{'color_field': 'color'}"/>
<field name="color"
widget="color_picker" string="Color" />
</group>
<group string="Description" name="public_description">
<field name="public_description"
placeholder="Information about your product."
nolabel="1"
colspan="2"/>
</group>
<group string="Upsell &amp; Cross-Sell" name="upsell_pos" >
<field name="pos_optional_product_ids"
widget="many2many_tags"
groups="point_of_sale.group_pos_user"
domain="[('id', '!=', id)]"
options="{'color_field': 'color'}"
placeholder="Recommend when 'Adding to Cart'"/>
</group>
</group>
</page>
</page>
<span name="sale_option" position="after">
<span class="d-inline-block">
<field name="available_in_pos"/>
<field name="to_weight" attrs="{'invisible': [('available_in_pos', '=', False)]}"/>
<field name="pos_categ_id" attrs="{'invisible': [('available_in_pos', '=', False)]}" string="Category"/>
</group>
<label for="available_in_pos" string="Point of Sale"/>
</span>
</span>
</field>
</record>
<record id="product_template_only_form_view" model="ir.ui.view">
<field name="name">product.template.product.form.inherit</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_only_form_view"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='attribute_line_ids']//field[@name='attribute_id']" position="attributes">
<attribute name="context">{'default_create_variant': context.get('create_variant_never', 'always')}</attribute>
</xpath>
</field>
</record>
@ -91,53 +126,114 @@
action="product_product_action"
groups="product.group_product_variant"
sequence="10"/>
<menuitem id="point_of_sale.menu_product_combo"
name="Combo Choices"
parent="point_of_sale.pos_config_menu_catalog"
action="product.product_combo_action"
sequence="15"/>
<menuitem id="pos_config_menu_action_product_pricelist"
parent="point_of_sale.pos_config_menu_catalog"
action="product.product_pricelist_action2"
groups="product.group_product_pricelist"
sequence="20"/>
<record id="product_uom_categ_form_view" model="ir.ui.view">
<field name="name">uom.category.form.inherit</field>
<field name="model">uom.category</field>
<field name="inherit_id" ref="uom.product_uom_categ_form_view"/>
<record id="product_uom_form_view_inherit" model="ir.ui.view">
<field name="name">product.uom.form.view.inherit</field>
<field name="model">uom.uom</field>
<field name="inherit_id" ref="uom.product_uom_form_view"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='name']" position="after">
<div name="relative_factor" position="after">
<field name="is_pos_groupable" groups="base.group_no_one"/>
</xpath>
</field>
</record>
<record id="product_uom_categ_tree_view" model="ir.ui.view">
<field name="name">uom.category.tree.inherit</field>
<field name="model">uom.category</field>
<field name="inherit_id" ref="uom.product_uom_categ_tree_view"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='name']" position="after">
<field name="is_pos_groupable" groups="base.group_no_one"/>
</xpath>
</div>
</field>
</record>
<record id="product_template_tree_view" model="ir.ui.view">
<field name="name">product.template.product.tree.inherit</field>
<field name="name">product.template.product.list.inherit</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_tree_view"/>
<field name="arch" type="xml">
<field name="categ_id" position="before">
<field name="pos_categ_id" optional="hide" string="POS Product Category"/>
<field name="pos_categ_ids" widget="many2many_tags" groups="point_of_sale.group_pos_user" optional="hide" string="POS Product Category"/>
</field>
<field name="pos_categ_ids" position="after">
<field name="available_in_pos" groups="point_of_sale.group_pos_user" optional="hide"/>
</field>
</field>
</record>
<record id="product_template_tree_view_point_of_sale" model="ir.ui.view">
<field name="name">product.template.view.list.point_of_sale</field>
<field name="mode">primary</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="point_of_sale.product_template_tree_view"/>
<field name="arch" type="xml">
<list position="attributes">
<attribute name="default_order">pos_sequence</attribute>
</list>
<field name="is_favorite" position="before">
<field name="pos_sequence" widget="handle" nolabel="1"/>
</field>
</field>
</record>
<record id="product_product_tree_view" model="ir.ui.view">
<field name="name">product.product.product.tree.inherit</field>
<field name="name">product.product.product.list.inherit</field>
<field name="model">product.product</field>
<field name="inherit_id" ref="product.product_product_tree_view"/>
<field name="arch" type="xml">
<field name="categ_id" position="before">
<field name="pos_categ_id" optional="hide" string="POS Product Category"/>
<field name="pos_categ_ids" widget="many2many_tags" groups="point_of_sale.group_pos_user" optional="hide" string="POS Product Category"/>
</field>
</field>
</record>
<record id="product_template_view_form_normalized_pos" model="ir.ui.view">
<field name="name">product.template.view.form.normalized</field>
<field name="model">product.template</field>
<field name="arch" type="xml">
<form>
<sheet>
<field name="image_1920" widget="image" class="oe_avatar" nolabel="1" options="{'convert_to_webp': True,'preview_image': 'image_128'}"/>
<group name="name">
<field name="name" class="oe_inline" placeholder="e.g. Cheese Burger" string="Product Name"/>
<field name="barcode" class="oe_inline" placeholder="e.g. 1234567890"/>
<label for="is_storable" class="oe_inline" invisible="type != 'consu'"/>
<div class="o_row w-100" invisible="type != 'consu'">
<field name="is_storable"/>
<field name="tracking" invisible="not is_storable" groups="stock.group_production_lot"/>
</div>
<field name="list_price" class="oe_inline" widget="monetary"
options="{'currency_field': 'currency_id', 'field_digits': True}"/>
<label for="taxes_id"/>
<div name="tax_info" class="o_row">
<field name="taxes_id" widget="many2many_tags"
readonly="context.get('taxes_readonly', False)"
context="{'search_default_sale': 1}"
options="{'create': false, 'create_edit': false}"/>
<field name="tax_string"/>
</div>
<field name="pos_categ_ids" string="POS Category" class="oe_inline" widget="many2many_tags"/>
<field name="color" widget="color_picker" string="Color" />
</group>
</sheet>
</form>
</field>
</record>
<record id="product_template_action_add_pos" model="ir.actions.act_window">
<field name="name">New Product</field>
<field name="res_model">product.template</field>
<field name="view_mode">form</field>
<field name="target">new</field>
<field name="context" eval="{'default_available_in_pos': True, 'create_variant_never': 'no_variant', 'dialog_size': 'medium', 'can_be_sold': True, 'default_is_storable': True}"/>
<field name="view_id" ref="point_of_sale.product_template_view_form_normalized_pos"/>
</record>
<record id="product_template_action_edit_pos" model="ir.actions.act_window">
<field name="name">Edit Product</field>
<field name="res_model">product.template</field>
<field name="view_mode">form</field>
<field name="target">new</field>
<field name="context" eval="{'dialog_size': 'medium'}"/>
<field name="view_id" ref="point_of_sale.product_template_view_form_normalized_pos"/>
</record>
</odoo>

View file

@ -6,5 +6,11 @@
using <t t-esc="payment_vals['pos_payment_name']" />
</t>
</xpath>
<xpath expr="//div[@name='origin']" position="after">
<div class="col" t-if="o.pos_refunded_invoice_ids" name="source_invoice">
<strong>Source Invoice</strong>
<div t-field="o.pos_refunded_invoice_ids"/>
</div>
</xpath>
</template>
</odoo>

View file

@ -1,90 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<template id="report_saledetails">
<t t-set="company" t-value="env.company"/>
<t t-call="web.html_container">
<t t-call="web.internal_layout">
<div class="page">
<odoo>
<data>
<template id="pos_daily_sales_report_layout" name="Daily Sales Report layout">&lt;!DOCTYPE html&gt;
<html t-att-lang="lang and lang.replace('_', '-')"
t-att-data-report-margin-top="8"
t-att-data-report-margin-bottom="8"
t-att-data-report-header-spacing="data_report_header_spacing"
t-att-data-report-dpi="data_report_dpi"
t-att-data-report-landscape="data_report_landscape"
t-att-web-base-url="web_base_url">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="initial-scale=1"/>
<title><t t-esc="title or 'Odoo Report'"/></title>
<t t-call-assets="web.report_assets_common" t-autoprefix="true"/>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', () => {
if (window.self !== window.top) {
document.body.classList.add("o_in_iframe", "container-fluid");
document.body.classList.remove("container");
}
});
</script>
</head>
<body t-attf-class="o_body_html {{'container' if not full_width else 'container-fluid'}} overflow-x-hidden" t-att-dir="env['res.lang']._get_data(code=lang or env.user.lang).direction or 'ltr'">
<div id="wrapwrap">
<main>
<t t-out="0"/>
</main>
</div>
</body>
</html>
</template>
<div class="text-center">
<h2>Sales Details</h2>
<template id="pos_daily_sales_html_container">
<t t-call="point_of_sale.pos_daily_sales_report_layout">
<t t-out="0"/>
</t>
</template>
<t t-if="date_start and date_stop">
<strong><t t-esc="date_start" t-options="{'widget': 'datetime'}"/> - <t t-esc="date_stop" t-options="{'widget': 'datetime'}"/></strong>
<template id="report_saledetails">
<t t-set="company" t-value="env.company"/>
<t t-call="point_of_sale.pos_daily_sales_html_container">
<t t-call="web.basic_layout">
<t t-call="point_of_sale.pos_session_sales_details"/>
</t>
</div>
<!-- Orderlines -->
<h3>Products</h3>
<table class="table table-sm">
<thead><tr>
<th>Product</th>
<th>Quantity</th>
<th>Price Unit</th>
</tr></thead>
<tbody>
<tr t-foreach='products' t-as='line'>
<t t-set="internal_reference" t-value="line['code'] and '[%s] ' % line['code'] or ''" />
<td><t t-esc="internal_reference" /><t t-esc="line['product_name']" /></td>
<td>
<t t-esc="line['quantity']" />
<t t-if='line["uom"] != "Units"'>
<t t-esc='line["uom"]' />
</t>
</td>
<td>
<t t-esc='line["price_unit"]' />
<t t-if='line["discount"] != 0'>
Disc: <t t-esc='line["discount"]' />%
</t>
</td>
</tr>
</tbody>
</table>
<br/>
<h3>Payments</h3>
<table class="table table-sm">
<thead><tr>
<th>Name</th>
<th>Total</th>
</tr></thead>
<tbody>
<tr t-foreach='payments' t-as='payment'>
<td><t t-esc="payment['name']" /></td>
<td><t t-esc="payment['total']" t-options="{'widget': 'float', 'precision': currency_precision}"/></td>
</tr>
</tbody>
</table>
<br/>
<h3>Taxes</h3>
<table class="table table-sm">
<thead><tr>
<th>Name</th>
<th>Tax Amount</th>
<th>Base Amount</th>
</tr></thead>
<tbody>
<tr t-foreach='taxes' t-as='tax'>
<td><t t-esc="tax['name']" /></td>
<td><t t-esc="tax['tax_amount']" t-options="{'widget': 'float', 'precision': currency_precision}"/></td>
<td><t t-esc="tax['base_amount']" t-options="{'widget': 'float', 'precision': currency_precision}"/></td>
</tr>
</tbody>
</table>
<br/>
<br/>
<strong>Total: <t t-esc='total_paid' t-options="{'widget': 'float', 'precision': currency_precision}"/></strong>
</div>
</t>
</t>
</template>
</data>
</openerp>
</t>
</template>
</data>
</odoo>

View file

@ -3,24 +3,30 @@
<template id="report_userlabel">
<t t-call="web.basic_layout">
<div class="page">
<div class="oe_structure"></div>
<t t-foreach="docs" t-as="user">
<div class="col-6 mb92">
<div class="oe_structure"></div>
<table class="table table-bordered">
<thead>
<tr>
<th class="col-4 danger"/>
<th class="active"/>
<th class="col-4 danger">Badge ID</th>
<th class="active">Name</th>
</tr>
</thead>
<tbody>
<tr>
<td><div t-if="user.sudo().barcode" t-field="user.sudo().barcode" t-options="{'widget': 'barcode', 'symbology': 'EAN13', 'width': 300, 'height': 50, 'img_style': 'width:100%;height:35%;'}"/></td>
<td><strong t-field="user.name"/></td>
<td>
<span t-if="user.sudo().barcode" t-field="user.sudo().barcode" t-options="{'widget': 'barcode', 'symbology': 'EAN13', 'width': 300, 'height': 50, 'img_style': 'width:100%;height:35%;'}">1234567890</span>
</td>
<td><strong><span t-field="user.name">Marc Demo</span></strong></td>
</tr>
</tbody>
</table>
<div class="oe_structure"></div>
</div>
</t>
<div class="oe_structure"></div>
</div>
</t>
</template>

View file

@ -9,8 +9,8 @@
<div name="button_box" position="inside">
<button class="oe_stat_button" type="object" name="action_view_pos_order"
groups="point_of_sale.group_pos_user"
context="{'default_partner_id': active_id}"
attrs="{'invisible': [('pos_order_count', '=', 0)]}"
context="{'default_partner_id': id}"
invisible="pos_order_count == 0"
icon="fa-shopping-bag">
<field string="PoS Orders" name="pos_order_count" widget="statinfo"/>
</button>
@ -20,27 +20,14 @@
<field name="barcode"/>
</group>
</xpath>
</field>
</record>
<record id="view_partner_pos_kanban" model="ir.ui.view">
<field name="name">res.partner.pos.kanban.inherit</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.res_partner_kanban_view"/>
<field name="arch" type="xml">
<field name="state_id" position="before">
<field name="pos_order_count" groups="point_of_sale.group_pos_user"/>
</field>
<xpath expr="//div[hasclass('oe_kanban_bottom_left')]" position="inside">
<a t-if="record.pos_order_count.value>0" data-type="object" data-name="action_view_pos_order"
groups="point_of_sale.group_pos_user"
href="#" class="oe_kanban_action oe_kanban_action_a me-1">
<span class="badge rounded-pill">
<i class="fa fa-fw fa-shopping-bag" role="img" aria-label="Shopping cart" title="Shopping cart"/>
<t t-out="record.pos_order_count.value"/>
</span>
</a>
</xpath>
</field>
<record id="res_partner_action_edit_pos" model="ir.actions.act_window">
<field name="name">Edit Partner</field>
<field name="res_model">res.partner</field>
<field name="view_mode">form</field>
<field name="target">new</field>
<field name="view_id" ref="base.view_partner_form"/>
</record>
</odoo>

View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="stock_reference_pos_view_form" model="ir.ui.view">
<field name="name">stock.reference.pos</field>
<field name="model">stock.reference</field>
<field name="inherit_id" ref="stock.stock_reference_form_view"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='picking_ids']" position="after">
<field name="pos_order_ids" widget="many2many_tags" readonly="True"/>
</xpath>
</field>
</record>
</odoo>