Initial commit: Sale packages

This commit is contained in:
Ernad Husremovic 2025-08-29 15:20:49 +02:00
commit 14e3d26998
6469 changed files with 2479670 additions and 0 deletions

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- View Taxes -->
<menuitem id="menu_action_tax_form_open"
action="account.action_tax_form"
parent="point_of_sale.menu_point_config_product"
groups="base.group_no_one"
sequence="40"/>
</odoo>

View file

@ -0,0 +1,13 @@
<?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,16 @@
<?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="model">digest.digest</field>
<field name="priority">50</field>
<field name="inherit_id" ref="digest.digest_digest_view_form" />
<field name="arch" type="xml">
<xpath expr="//group[@name='kpis']/group[last()]" position="before">
<group name="kpi_pos" string="Point of Sale">
<field name="kpi_pos_total"/>
</group>
</xpath>
</field>
</record>
</odoo>

View file

@ -0,0 +1,169 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<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="search_view_id" ref="view_pos_session_search" />
<field name="context">{
'search_default_config_id': [active_id],
'default_config_id': active_id}
</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="search_view_id" ref="view_pos_order_search"/>
<field name="context">{
'search_default_config_id': [active_id],
'default_config_id': active_id}
</field>
</record>
<record id="action_report_pos_order_all_filtered" model="ir.actions.act_window">
<field name="name">Orders Analysis</field>
<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">{
'search_default_config_id': [active_id],
'default_config_id': active_id}
</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
No data yet!
</p><p>
Create a new POS order
</p>
</field>
</record>
<!-- Dashboard -->
<record id="view_pos_config_kanban" model="ir.ui.view">
<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"/>
<field name="current_session_id"/>
<field name="current_session_state"/>
<field name="last_session_closing_date"/>
<field name="pos_session_username"/>
<field name="pos_session_state"/>
<field name="pos_session_duration"/>
<field name="currency_id"/>
<field name="number_of_opened_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"/>
</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>
</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>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
</odoo>

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="report_user_label" model="ir.actions.report">
<field name="name">User Labels</field>
<field name="model">res.users</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">point_of_sale.report_userlabel</field>
<field name="report_file">point_of_sale.report_userlabel</field>
<field name="binding_model_id" ref="base.model_res_users"/>
<field name="binding_type">report</field>
</record>
<record id="sale_details_report" model="ir.actions.report">
<field name="name">Sales Details</field>
<field name="model">pos.session</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">point_of_sale.report_saledetails</field>
</record>
</odoo>

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<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="padding">5</field>
<field name="company_id" eval="False" />
</record>
</data>
</odoo>

View file

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Top menu item -->
<menuitem
id="menu_point_root"
name="Point of Sale"
groups="group_pos_manager,group_pos_user"
web_icon="point_of_sale,static/description/icon.svg"
sequence="50"/>
<!-- Orders menu -->
<menuitem id="menu_point_of_sale"
name="Orders"
parent="menu_point_root"
sequence="10"/>
<menuitem id="menu_point_of_sale_customer"
name="Customers"
parent="menu_point_of_sale"
action="account.res_partner_action_customer"
sequence="100"/>
<!-- Reporting menu -->
<menuitem id="menu_point_rep"
name="Reporting"
parent="menu_point_root"
sequence="90"
groups="group_pos_manager"/>
<!-- Config menu and sub menus -->
<menuitem id="menu_point_config_product"
name="Configuration"
parent="menu_point_root"
sequence="100"
groups="group_pos_manager"/>
<menuitem id="pos_menu_products_configuration"
name="Products"
parent="menu_point_config_product"
sequence="11"/>
<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>
<menuitem id="menu_pos_global_settings"
name="Settings"
parent="menu_point_config_product"
sequence="0"
action="action_pos_configuration"
groups="base.group_system"/>
</odoo>

View file

@ -0,0 +1,12 @@
<?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

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- This contains the tour assets. They are included during testing. -->
<template id="point_of_sale.index" name="POS Index">&lt;!DOCTYPE html&gt;
<html>
<head>
<title>Odoo POS</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="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"/>
<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,
'pos_session_id': pos_session_id,
'debug': debug,
})"/>;
// Prevent the menu_service to load anything. In an ideal world, POS assets would only contain
// what is genuinely necessary, and not the whole backend.
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" />
</head>
<body>
</body>
</html>
</template>
</odoo>

View file

@ -0,0 +1,56 @@
<?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

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_pos_bill_form" model="ir.ui.view">
<field name="name">pos.bill.form</field>
<field name="model">pos.bill</field>
<field name="arch" type="xml">
<form string="Bills">
<sheet>
<group>
<field name="name" />
<field name="value" />
<field name="pos_config_ids" widget="many2many_tags" />
</group>
</sheet>
</form>
</field>
</record>
<record id="view_pos_bill_tree" model="ir.ui.view">
<field name="name">pos.bill.tree</field>
<field name="model">pos.bill</field>
<field name="arch" type="xml">
<tree string="Bills" create="1" delete="1">
<field name="name" />
<field name="value" />
<field name="pos_config_ids" widget="many2many_tags" />
</tree>
</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>
</record>
<menuitem
id="menu_pos_bill"
name="Coins/Bills"
parent="menu_point_config_product"
sequence="4"
action="action_pos_bill"
groups="group_pos_manager"/>
</odoo>

View file

@ -0,0 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="product_pos_category_form_view" model="ir.ui.view">
<field name="name">pos.category.form</field>
<field name="model">pos.category</field>
<field name="arch" type="xml">
<form string="Pos Product Categories">
<sheet>
<field name="image_128" 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>
</div>
<group>
<group>
<field name="parent_id" class="o_text_overflow"/>
<field name="sequence" groups="base.group_no_one" />
</group>
</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="model">pos.category</field>
<field name="field_parent" eval="False"/>
<field name="arch" type="xml">
<tree string="Product Product Categories">
<field name="sequence" widget="handle"/>
<field name="display_name" string="PoS Product Category"/>
</tree>
</field>
</record>
<record id="view_pos_category_kanban" model="ir.ui.view">
<field name="name">pos.category.kanban</field>
<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>
</templates>
</kanban>
</field>
</record>
<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_id" eval="False"/>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Define a new category
</p><p>
Categories are used to browse your products through the
touchscreen interface.
</p>
</field>
</record>
</odoo>

View file

@ -0,0 +1,178 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="pos_config_view_form" model="ir.ui.view">
<field name="name">pos.config.form.view</field>
<field name="model">pos.config</field>
<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)]}"/>
<field name="active" invisible="1"/>
<field name="company_has_template" invisible="1"/>
<field name="has_active_session" invisible="1"/>
<field name="other_devices" invisible="1"/>
<field name="is_posbox" invisible="1"/>
<field name="module_pos_hr" invisible="1"/>
<div class="oe_title" id="title">
<label for="name"/>
<h1><field name="name" placeholder="e.g. NYC Shop"/></h1>
</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">
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>
</div>
<div class="o_notification_alert alert alert-warning" attrs="{'invisible': [('company_has_template','=',True)]}" 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">
<field name="module_pos_restaurant" />
</div>
<div class="o_setting_right_pane">
<label for="module_pos_restaurant"/>
</div>
</div>
</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>
</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
</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>
<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"/>
<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 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>
</p>
</div>
</div>
</sheet>
<!-- Replace the default save/discard buttons so that when any of the buttons is clicked, the modal immediately closes. -->
<footer invisible="not context.get('pos_config_open_modal', False)">
<button string="Save" special="save" class="btn-primary"/>
<button string="Discard" class="btn-secondary" special="cancel"/>
</footer>
</form>
</field>
</record>
<record id="view_pos_config_tree" model="ir.ui.view">
<field name="name">pos.config.tree.view</field>
<field name="model">pos.config</field>
<field name="arch" type="xml">
<tree string="Point of Sale Configuration">
<field name="name" />
<field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/>
</tree>
</field>
</record>
<record id="view_pos_config_search" model="ir.ui.view">
<field name="name">pos.config.search.view</field>
<field name="model">pos.config</field>
<field name="arch" type="xml">
<search string="Point of Sale Config">
<field name="name"/>
<field name="picking_type_id" />
<filter string="Archived" name="inactive" domain="[('active', '=', False)]"/>
</search>
</field>
</record>
<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="res_model">pos.config</field>
<field name="view_mode">kanban,tree,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>
<!-- Products sub Category -->
<menuitem id="menu_products_pos_category"
action="point_of_sale.product_pos_category_action"
parent="point_of_sale.pos_menu_products_configuration"
sequence="1"/>
<menuitem id="pos_menu_products_attribute_action"
action="product.attribute_action"
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"/>
</odoo>

View file

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_report_pos_order_pivot" model="ir.ui.view">
<field name="name">report.pos.order.pivot</field>
<field name="model">report.pos.order</field>
<field name="arch" type="xml">
<pivot string="Point of Sale Analysis" sample="1">
<field name="product_categ_id" type="row"/>
<field name="date" interval="month" type="col"/>
<field name="order_id" type="measure"/>
<field name="product_qty" type="measure"/>
<field name="price_total" type="measure"/>
</pivot>
</field>
</record>
<record id="view_report_pos_order_graph" model="ir.ui.view">
<field name="name">report.pos.order.graph</field>
<field name="model">report.pos.order</field>
<field name="arch" type="xml">
<graph string="Point of Sale Analysis" sample="1">
<field name="product_categ_id"/>
<field name="price_total" type="measure"/>
</graph>
</field>
</record>
<record id="report_pos_order_view_tree" model="ir.ui.view">
<field name="name">report.pos.order.view.tree</field>
<field name="model">report.pos.order</field>
<field name="arch" type="xml">
<tree string="Point of Sale Analysis">
<field name="date" widget="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="state" optional="show"/>
</tree>
</field>
</record>
<record id="view_report_pos_order_search" model="ir.ui.view">
<field name="name">report.pos.order.search</field>
<field name="model">report.pos.order</field>
<field name="arch" type="xml">
<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'])]"/>
<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">
<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'}"/>
<separator/>
<filter string="Order Date" name="order_month" context="{'group_by':'date:month'}"/>
</group>
</search>
</field>
</record>
<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="context">{'group_by': ['date', 'session_id']}</field>
</record>
<record id="action_report_pos_order_all" model="ir.actions.act_window">
<field name="name">Orders Analysis</field>
<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="help" type="html">
<p class="o_view_nocontent_smiling_face">
No data yet!
</p><p>
Create a new POS order
</p>
</field>
</record>
<record id="action_report_pos_details" model="ir.actions.act_window">
<field name="name">Sales Details</field>
<field name="res_model">pos.details.wizard</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
<menuitem id="menu_report_pos_order_all" name="Orders" action="action_report_pos_order_all" parent="menu_point_rep" sequence="3"/>
<menuitem id="menu_report_order_details" name="Sales Details" action="action_report_pos_details" parent="menu_point_rep" sequence="4"/>
</odoo>

View file

@ -0,0 +1,419 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_pos_pos_form" model="ir.ui.view">
<field name="name">pos.order.form</field>
<field name="model">pos.order</field>
<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_order_invoice" string="Invoice" type="object"
attrs="{'invisible': [('state','!=','paid')]}"/>
<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" />
<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)]}"/>
</button>
<button name="action_view_invoice"
string="Invoice"
type="object"
class="oe_stat_button"
icon="fa-pencil-square-o"
attrs="{'invisible':[('state','!=','invoiced')]}">
</button>
<button name="action_view_refund_orders"
type="object"
class="oe_stat_button"
icon="fa-undo"
attrs="{'invisible':[('is_refunded', '=', False)]}">
<field name="refund_orders_count" widget="statinfo" string="Refunds" />
</button>
<button name="action_view_refunded_orders"
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" />
</button>
</div>
<group col="4" colspan="4" name="order_fields">
<field name="name"/>
<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}"/>
</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="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="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="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="refunded_qty" optional="hide" />
</tree>
<form string="Order lines">
<group col="4">
<field name="full_product_name"/>
<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="pack_lot_ids" widget="many2many_tags" groups="stock.group_production_lot"/>
<field name="notice"/>
<field name="currency_id" invisible="1"/>
</group>
</form>
</field>
<group class="oe_subtotal_footer oe_right" 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"
widget="monetary"/>
<field name="amount_paid"
string="Total Paid (with rounding)"
class="oe_subtotal_footer_separator"
widget="monetary"
attrs="{'invisible': [('amount_paid','=', 'amount_total')]}"/>
<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_percent" nolabel="1" class="oe_inline" widget="percentage"/>)
</span>
<span attrs="{'invisible': [('is_total_cost_computed','=', True)]}">TBD</span>
</div>
<field name="is_total_cost_computed" invisible="1"/>
<field name="currency_id" invisible="1"/>
</group>
<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_date"/>
<field name="payment_method_id"/>
<field name="amount"/>
</tree>
</field>
</page>
<page name="extra" string="Extra Info">
<group >
<group
string="Accounting"
groups="account.group_account_manager"
attrs="{'invisible':['|', ('session_move_id','=', False), ('state', '=', 'invoiced')]}"
>
<field name="session_move_id" readonly="1" />
</group>
<group string="Other Information">
<field name="pos_reference"/>
<field name="company_id" groups="base.group_multi_company"/>
<field name="pricelist_id" groups="product.group_product_pricelist"/>
</group>
</group>
</page>
<page string="Notes" name="notes">
<field name="note"/>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<record model="ir.ui.view" id="view_pos_order_kanban">
<field name="name">pos.order.kanban</field>
<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>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<record model="ir.ui.view" id="view_pos_order_pivot">
<field name="name">pos.order.pivot</field>
<field name="model">pos.order</field>
<field name="arch" type="xml">
<pivot string="PoS Orders" sample="1">
<field name="date_order" type="row"/>
<field name="margin"/>
<field name="margin_percent" invisible="1"/>
<field name="amount_total" type="measure"/>
</pivot>
</field>
</record>
<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="view_id" eval="False"/>
<field name="domain">[]</field>
<field name="help" type="html">
<p class="o_view_nocontent_empty_folder">
No orders found
</p><p>
To record new orders, start a new session.
</p>
</field>
</record>
<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="help" type="html">
<p class="o_view_nocontent_smiling_face">
No data yet!
</p><p>
Create a new POS order
</p>
</field>
</record>
<record id="view_pos_order_tree" model="ir.ui.view">
<field name="name">pos.order.tree</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"/>
<field name="name" decoration-bf="1"/>
<field name="session_id" />
<field name="date_order"/>
<field name="pos_reference"/>
<field name="partner_id"/>
<field string="Cashier" name="user_id" widget="many2one_avatar_user"/>
<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>
</record>
<record id="view_pos_order_tree_no_session_id" model="ir.ui.view">
<field name="name">pos.order.tree_no_session_id</field>
<field name="model">pos.order</field>
<field name="mode">primary</field>
<field name="priority">1000</field>
<field name="inherit_id" ref="point_of_sale.view_pos_order_tree"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='session_id']" position="replace"></xpath>
</field>
</record>
<record id="view_pos_order_search" model="ir.ui.view">
<field name="name">pos.order.search.view</field>
<field name="model">pos.order</field>
<field name="arch" type="xml">
<search string="Point of Sale Orders">
<field name="name"/>
<field name="config_id"/>
</search>
</field>
</record>
<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="model">pos.order.line</field>
<field name="arch" type="xml">
<tree string="POS Order lines">
<field name="product_id" readonly="1"/>
<field name="qty" readonly="1" sum="Total qty"/>
<field name="discount" readonly="1"/>
<field name="price_unit" readonly="1" widget="monetary"/>
<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>
</record>
<record id="view_pos_order_line_form" model="ir.ui.view">
<field name="name">pos.order.line.form</field>
<field name="model">pos.order.line</field>
<field name="arch" type="xml">
<form string="POS Order line">
<group col="4">
<field name="product_id" />
<field name="qty" />
<field name="discount"/>
<field name="price_unit" widget="monetary"/>
<field name="create_date" />
<field name="currency_id"/>
</group>
</form>
</field>
</record>
<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_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_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_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>
</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="model">pos.order.line</field>
<field name="arch" type="xml">
<tree 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>
</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>
<record id="view_pos_order_filter" model="ir.ui.view">
<field name="name">pos.order.list.select</field>
<field name="model">pos.order</field>
<field name="arch" type="xml">
<search string="Search Sales Order">
<field name="name"/>
<field name="pos_reference"/>
<field name="date_order"/>
<field name="user_id"/>
<field name="partner_id"/>
<field name="session_id"/>
<filter string="Invoiced" name="invoiced" domain="[('state', '=', 'invoiced')]"/>
<filter string="Posted" name="posted" domain="[('state', '=', 'done')]"/>
<separator/>
<filter string="Order Date" name="order_date" date="date_order"/>
<group expand="0" string="Group By">
<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="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'}"/>
</group>
</search>
</field>
</record>
<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">
The Point of Sale only supports the "add a rounding line" rounding strategy.
</div>
</xpath>
</field>
</record>
</odoo>

View file

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="pos_payment_method_view_form" model="ir.ui.view">
<field name="name">pos.payment.method.form</field>
<field name="model">pos.payment.method</field>
<field name="arch" type="xml">
<form string="Payment Methods">
<sheet>
<widget name="web_ribbon" title="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
<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>
</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="company_id" readonly="1" groups="base.group_multi_company" />
</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>
</group>
</sheet>
</form>
</field>
</record>
<record id="pos_payment_method_view_tree" model="ir.ui.view">
<field name="name">pos.payment.method.tree</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"/>
<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="company_id" groups="base.group_multi_company" />
</tree>
</field>
</record>
<record id="pos_payment_method_view_search" model="ir.ui.view">
<field name="name">pos.payment.search.view</field>
<field name="model">pos.payment.method</field>
<field name="arch" type="xml">
<search string="Payment Methods">
<field name="name"/>
<field name="receivable_account_id" groups="account.group_account_readonly" />
<group expand="1" string="Group By">
<filter name="group_by_receivable_account" string="Account" domain="[]" context="{'group_by':'receivable_account_id'}"/>
</group>
<filter string="Archived" name="active" domain="[('active', '=', False)]"/>
</search>
</field>
</record>
<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_id" eval="False"/>
<field name="domain">[]</field>
<field name="context">{'search_default_group_by_account': 1}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Add a new payment method
</p>
<p>
Installing chart of accounts from the General Settings of
Invocing/Accounting app will create Bank and Cash payment
methods automatically.
</p>
</field>
</record>
<menuitem id="menu_pos_payment_method" parent="menu_point_config_product" action="action_pos_payment_method_form" sequence="3" groups="group_pos_manager,group_pos_user"/>
<record id="action_payment_methods_tree" model="ir.actions.act_window">
<field name="context">{}</field>
<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>
</record>
</odoo>

View file

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_pos_payment_form" model="ir.ui.view">
<field name="name">pos.payment.form</field>
<field name="model">pos.payment</field>
<field name="arch" type="xml">
<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" />
</group>
</sheet>
</form>
</field>
</record>
<record id="view_pos_payment_tree" model="ir.ui.view">
<field name="name">pos.payment.tree</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" />
<field name="payment_date"/>
<field name="payment_method_id" />
<field name="pos_order_id" />
<field name="amount" />
</tree>
</field>
</record>
<record id="view_pos_payment_search" model="ir.ui.view">
<field name="name">pos.payment.search.view</field>
<field name="model">pos.payment</field>
<field name="arch" type="xml">
<search string="Payments">
<field name="name"/>
<field name="amount"/>
<field name="pos_order_id" />
<group expand="0" string="Group By">
<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>
</search>
</field>
</record>
<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_id" eval="False"/>
<field name="domain">[]</field>
<field name="context">{'search_default_group_by_payment_method': 1}</field>
<field name="help" type="html">
<p class="o_view_nocontent_empty_folder">
No orders found
</p><p>
To record new orders, start a new session.
</p>
</field>
</record>
<menuitem id="menu_pos_payment" parent="menu_point_of_sale" action="action_pos_payment_form" sequence="3" groups="group_pos_manager,group_pos_user"/>
</odoo>

View file

@ -0,0 +1,189 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_pos_session_form" model="ir.ui.view">
<field name="name">pos.session.form.view</field>
<field name="model">pos.session</field>
<field name="arch" type="xml">
<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)]}"
class="oe_highlight"/>
<field name="state" widget="statusbar" statusbar_visible="opened,closing_control,closed" nolabel="1" />
</header>
<sheet>
<field name="failed_pickings" invisible="1"/>
<field name="rescue" invisible="1"/>
<div class="oe_button_box" name="button_box">
<button name="action_view_order"
class="oe_stat_button"
icon="fa-shopping-basket"
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>
<button
name="action_show_payments_list"
type="object"
class="oe_stat_button"
icon="fa-dollar"
>
<field name="total_payments_amount" widget="statinfo" string="Payments"/>
</button>
<button
name="show_journal_items"
type="object"
class="oe_stat_button"
icon="fa-bars"
string="Journal Items"
groups="account.group_account_readonly"
>
</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"
/>
</div>
<h1 class="oe_title">
<field name="name" attrs="{'invisible': [('name','=','/')]}" class="oe_inline"/>
</h1>
<group>
<field name="cash_control" invisible="1" />
<field name="user_id"/>
<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="cash_register_balance_start"/>
<field name="cash_register_balance_end_real" attrs="{'invisible': [('state', '!=', 'closed')]}"/>
</group>
</sheet>
<div class="oe_chatter">
<field name="activity_ids"/>
<field name="message_follower_ids"/>
<field name="message_ids"/>
</div>
</form>
</field>
</record>
<record id="view_pos_session_tree" model="ir.ui.view">
<field name="name">pos.session.tree.view</field>
<field name="model">pos.session</field>
<field name="arch" type="xml">
<tree 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="start_at" />
<field name="stop_at" />
<field name="state" widget="badge" decoration-info="state in ('opening_control')" decoration-success="state in ('opened', 'closed')" decoration-warning="state == 'closing_control'" />
</tree>
</field>
</record>
<record model="ir.ui.view" id="view_pos_session_kanban">
<field name="name">pos.session.kanban</field>
<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>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<record id="view_pos_session_search" model="ir.ui.view">
<field name="name">pos.session.search.view</field>
<field name="model">pos.session</field>
<field name="arch" type="xml">
<search string="Point of Sale Session">
<field name="name"/>
<field name="config_id" />
<field name="user_id" />
<filter name="my_sessions" string="My Sessions" domain="[('user_id', '=', uid)]"/>
<separator/>
<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">
<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'}"/>
<filter string="Opening Date" name="opening_date" domain="[]" context="{'group_by': 'start_at'}"/>
<filter string="Closing Date" name="closing_date" domain="[]" context="{'group_by': 'stop_at'}"/>
</group>
</search>
</field>
</record>
<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="search_view_id" ref="view_pos_session_search" />
<field name="help" type="html">
<p class="o_view_nocontent_empty_folder">
No sessions found
</p><p>
A session is a period of time, usually one day, during which you sell through the Point of Sale.
</p>
</field>
</record>
<record id="mail_activity_old_session" model="mail.activity.type">
<field name="name">Session open over 7 days</field>
<field name="summary">note</field>
<field name="category">default</field>
<field name="res_model">pos.session</field>
<field name="icon">fa-tasks</field>
<field name="delay_count">0</field>
</record>
<menuitem
id="menu_pos_session_all"
parent="menu_point_of_sale"
action="action_pos_session"
sequence="2"
groups="group_pos_manager"/>
</odoo>

View file

@ -0,0 +1,135 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- This is the "validation" screen. Recap the ticket info, warn the user to check/set his address and eventually set localization fields if needed. -->
<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'">
<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">
<div class="row">
<h2>Invoicing confirmation</h2>
<hr class="mt-1 mb-0"/>
</div>
<div class="row">
<h4 class="mt-2"><t t-out="pos_order.pos_reference"/></h4>
</div>
<div class="row">
<div class="col-12 fw-bold">
Products:
</div>
</div>
<div class="row">
<div class="col-12">
<ul>
<t t-foreach="pos_order.lines" t-as="order_line">
<li><t t-out="int(order_line.qty)"/> <t t-out="order_line.full_product_name"/> for <t t-out="format_amount(env, order_line.price_subtotal_incl, order_line.currency_id)"/></li>
</t>
</ul>
</div>
</div>
<div class="row">
<div class="col-12">
<strong>Amounting to:</strong> <t t-out="format_amount(env, pos_order.amount_total, pos_order.currency_id)"/>
</div>
</div>
<t t-if="user_is_connected">
<div class="row mt-4">
<div class="col-12">
<h4>Billing address:</h4>
</div>
</div>
<div t-if="error_message" class="alert alert-danger" role="alert">
<div class="col-lg-12">
<t t-foreach="error_message" t-as="err"><t t-esc="err"/><br /></t>
</div>
</div>
<t t-if="not partner_address">
Your address is missing or incomplete. <br/>
Please make sure to <a t-att-href="address_url">fill all relevant information</a> before continuing.
</t>
<t t-else="">
<div class="row">
<div class="col-12">
<t t-out="partner.name"/>
<t t-if="partner.company_name">
, <t t-out="partner.company_name"/>
</t><br />
<t 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>
</div>
</div>
</t>
<t t-if="partner_required_fields">
<div class="row mt-4">
<div class="col-12">
<h4>Additional required user information:</h4>
<t t-set="required_fields" t-value="partner_required_fields"/>
<t t-set="field_prefix" t-value="'partner_'"/>
<t t-call="account.portal_invoice_required_fields_form"/>
</div>
</div>
</t>
<t t-if="invoice_required_fields">
<div class="row mt-4">
<div class="col-12">
<h4>Additional required invoicing information:</h4>
<t t-set="required_fields" t-value="invoice_required_fields"/>
<t t-set="field_prefix" t-value="'invoice_'"/>
<t t-call="account.portal_invoice_required_fields_form"/>
</div>
</div>
</t>
</t>
<t t-else="">
<div class="row mt-4">
<div class="col-12">
<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="col-lg-12">
<div class="row">
<t t-call="portal.portal_my_details_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_'"/>
<t t-call="account.portal_invoice_required_fields_form"/>
</t>
</div>
</div>
</div>
<t t-if="invoice_required_fields">
<div class="row mt-4">
<div class="col-12">
<div class="row">
<h4>Additional required information:</h4>
<t t-set="required_fields" t-value="invoice_required_fields"/>
<t t-set="field_prefix" t-value="'invoice_'"/>
<t t-call="account.portal_invoice_required_fields_form"/>
</div>
</div>
</div>
</t>
</t>
<div class="row mt-4">
<div class="col-12 col-md-4">
<t t-if="user_is_connected and not partner_address">
<button class="btn btn-primary w-100" disabled="True">Get my invoice</button>
</t>
<t t-else="">
<button class="btn btn-primary w-100">Get my invoice</button>
</t>
</div>
</div>
</div>
</form>
</div>
</t>
</template>
</odoo>

View file

@ -0,0 +1,143 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="product_template_search_view_pos" model="ir.ui.view">
<field name="name">product.template.search.pos.form</field>
<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)]"/>
</filter>
<filter name="categ_id" position="after">
<filter string="POS Product Category" name="pos_categ_id" context="{'group_by':'pos_categ_id'}"/>
</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'}"/>
</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="search_view_id" eval="False"/> <!-- Force empty -->
<field name="view_id" ref="product.product_product_tree_view"/>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a new product variant
</p><p>
You must define a product for everything you sell through
the point of sale interface.
</p>
</field>
</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>
</xpath>
<xpath expr="//page[@name='sales']/group[@name='sale']" position="inside">
<group name="pos" string="Point of Sale" attrs="{'invisible': [('sale_ok','=',False)]}">
<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>
</xpath>
</field>
</record>
<!-- Product Catalog menus and sub menus -->
<menuitem id="pos_config_menu_catalog"
name="Products"
parent="point_of_sale.menu_point_root"/>
<menuitem id="menu_pos_products"
action="product_template_action_pos_product"
parent="point_of_sale.pos_config_menu_catalog"
sequence="5"/>
<menuitem id="pos_config_menu_action_product_product"
name="Product Variants"
parent="point_of_sale.pos_config_menu_catalog"
action="product_product_action"
groups="product.group_product_variant"
sequence="10"/>
<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"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='name']" 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>
</field>
</record>
<record id="product_template_tree_view" model="ir.ui.view">
<field name="name">product.template.product.tree.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>
</field>
</record>
<record id="product_product_tree_view" model="ir.ui.view">
<field name="name">product.product.product.tree.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>
</field>
</record>
</odoo>

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="point_of_sale.report_invoice_document" inherit_id="account.report_invoice_document">
<xpath expr="//i[hasclass('oe_payment_label')]" position="inside">
<t t-if="payment_vals.get('pos_payment_name')">
using <t t-esc="payment_vals['pos_payment_name']" />
</t>
</xpath>
</template>
</odoo>

View file

@ -0,0 +1,90 @@
<?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">
<div class="text-center">
<h2>Sales Details</h2>
<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>
</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>

View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="report_userlabel">
<t t-call="web.basic_layout">
<div class="page">
<t t-foreach="docs" t-as="user">
<div class="col-6 mb92">
<table class="table table-bordered">
<thead>
<tr>
<th class="col-4 danger"/>
<th class="active"/>
</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>
</tr>
</tbody>
</table>
</div>
</t>
</div>
</t>
</template>
</odoo>

View file

@ -0,0 +1,722 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="res_config_settings_view_form" model="ir.ui.view">
<field name="name">res.config.settings.view.form.inherit.point_of_sale</field>
<field name="model">res.config.settings</field>
<field name="priority" eval="95"/>
<field name="inherit_id" ref="base.res_config_settings_view_form" />
<field name="arch" type="xml">
<xpath expr="//div[hasclass('settings')]" position="inside">
<t groups="point_of_sale.group_pos_manager">
<field name="pos_selectable_categ_ids" invisible="1"/>
<field name="pos_has_active_session" invisible="1"/>
<field name="pos_allowed_pricelist_ids" invisible="1"/>
<field name="pos_cash_control" invisible="1"/>
<field name="pos_iface_print_via_proxy" invisible="1"/>
<field name="pos_company_has_template" invisible="1"/>
<field name="is_default_pricelist_displayed" invisible="1"/>
<field name="group_cash_rounding" invisible="1"/>
</t>
<div class="app_settings_block" data-string="Point of sale" string="Point of Sale" data-key="point_of_sale" groups="point_of_sale.group_pos_manager">
<div class="app_settings_header pt-1 pb-1 bg-warning bg-opacity-25">
<div class="col-xs-12 col-md-6 ms-0 o_setting_box">
<div class="o_setting_right_pane border-start-0 ms-0 ps-0">
<div class="content-group">
<div class="row flex-row flex-nowrap mt8 align-items-center">
<label class="col text-nowrap ml8 flex-nowrap" string="Point of Sale" for="pos_config_id"/>
<field name="pos_config_id" class="w-50" options="{'no_open': True, 'no_create': True}" title="Settings on this page will apply to this point of sale."/>
<button name="action_pos_config_create_new" type="object" string="+ New Shop" class="col btn-link ms-2 text-nowrap" style="line-height: 0.5;"/>
</div>
</div>
</div>
</div>
</div>
<div class="o_view_nocontent" attrs="{'invisible': [('pos_config_id', '!=', False)]}">
<div class="o_nocontent_help">
<p class="o_view_nocontent_empty_folder">No Point of Sale selected</p>
<p>Please create/select a Point of Sale above to show the configuration options.</p>
</div>
</div>
<div attrs="{'invisible': [('pos_config_id', '=', False)]}">
<h2 name="pos_interface">PoS Interface</h2>
<div class="row mt16 o_settings_container" id="pos_interface_section">
<div class="o_setting_box">
<!-- Wrap the warnings in an o_setting_box so that it doesn't show in the search. -->
<div class="o_notification_alert alert alert-warning" attrs="{'invisible':[('pos_has_active_session','=', False)]}" role="alert">
A session is currently opened for this PoS. Some settings can only be changed after the session is closed.
<button class="btn-link" style="padding:0" name="pos_open_ui" type="object" context="{'pos_config_id': pos_config_id}">Click here to close the session</button>
</div>
<div class="o_notification_alert alert alert-warning" attrs="{'invisible': [('pos_company_has_template','=',True)]}" 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>
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="pos_module_pos_restaurant" attrs="{'readonly': [('pos_has_active_session', '=', True)]}"/>
</div>
<div class="o_setting_right_pane">
<label for="pos_module_pos_restaurant"/>
<div class="content-group" id="warning_text_pos_restaurant" attrs="{'invisible': [('pos_module_pos_restaurant', '=', False)]}">
<div class="text-warning mt16 mb4">
Save this page and come back here to set up the feature.
</div>
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="pos_start_category"/>
</div>
<div class="o_setting_right_pane">
<label for="pos_start_category"/>
<div class="text-muted">
Start selling from a default product category
</div>
<div class="content-group mt16" attrs="{'invisible': [('pos_start_category', '=', False)]}">
<field name="pos_iface_start_categ_id" domain="[('id', 'in', pos_selectable_categ_ids)]"/>
</div>
</div>
</div>
<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="pos_module_pos_hr" attrs="{'readonly': [('pos_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': [('pos_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>
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="pos_limit_categories" attrs="{'readonly': [('pos_has_active_session','=', True)]}"/>
</div>
<div class="o_setting_right_pane">
<label for="pos_limit_categories"/>
<div class="text-muted">
Pick which product categories are available
</div>
<div class="content-group mt16" attrs="{'invisible': [('pos_limit_categories', '=', False)]}">
<field name="pos_iface_available_categ_ids" widget="many2many_tags" attrs="{'readonly': [('pos_has_active_session','=', True)]}"/>
</div>
<div class="content-group mt16" attrs="{'invisible': [('pos_limit_categories', '=', False)]}">
<button name="%(product_pos_category_action)d" icon="fa-arrow-right" type="action" string="PoS Product Categories" class="btn-link"/>
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="pos_iface_big_scrollbars"/>
</div>
<div class="o_setting_right_pane">
<label for="pos_iface_big_scrollbars"/>
<div class="text-muted">
Improve navigation for imprecise industrial touchscreens
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="pos_is_margins_costs_accessible_to_every_user"/>
</div>
<div class="o_setting_right_pane">
<label for="pos_is_margins_costs_accessible_to_every_user" string="Margins &amp; Costs"/>
<div class="text-muted">
Show margins &amp; costs on product information
</div>
</div>
</div>
</div>
<h2>Accounting</h2>
<div class="row mt16 o_settings_container" id="pos_accounting_section">
<div class="col-12 col-lg-6 o_setting_box"
id="default_sales_tax_setting"
title="This tax is applied to any new product created in the catalog.">
<div class="o_setting_right_pane">
<div>
<label string="Default Sales Tax" for="sale_tax_id"/>
<i class="fa fa-info-circle me-1" title="This setting is common to all PoS." pos-data-toggle="tooltip"/>
<div class="text-muted">
Default sales tax for products
</div>
<div class="content-group mt16">
<field name="sale_tax_id" colspan="4" nolabel="1" domain="[('type_tax_use', 'in', ('sale', 'all')), ('company_id', '=', company_id)]"/>
</div>
</div>
<div class="mt8">
<button name="%(account.action_tax_form)d" icon="fa-arrow-right" type="action" string="Taxes" class="btn-link"/>
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box"
groups="account.group_account_readonly">
<div class="o_setting_right_pane">
<div>
<label string="Default Temporary Account" for="account_default_pos_receivable_account_id"/>
<i class="fa fa-info-circle me-1" title="This setting is common to all PoS." pos-data-toggle="tooltip"/>
<div class="text-muted">
Intermediary account used for unidentified customers.
</div>
<div class="content-group mt16">
<field name="account_default_pos_receivable_account_id" colspan="4" nolabel="1" domain="[('reconcile', '=', True), ('account_type', '=', 'asset_receivable'), ('company_id', '=', company_id)]"/>
</div>
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box" title="Choose a specific fiscal position at the order depending on the kind of customer (tax exempt, onsite vs. takeaway, etc.).">
<div class="o_setting_left_pane">
<field name="pos_tax_regime_selection"/>
</div>
<div class="o_setting_right_pane">
<label for="pos_tax_regime_selection" string="Flexible Taxes"/>
<div class="text-muted">
Use fiscal positions to get different taxes by order
</div>
<div class="content-group mt16" attrs="{'invisible': [('pos_tax_regime_selection', '=', False)]}">
<div class="row">
<label string="Default" for="pos_default_fiscal_position_id" class="col-lg-3 o_light_label"/>
<field name="pos_default_fiscal_position_id" domain="['|',('company_id', '=', company_id),('company_id', '=', False)]"/>
</div>
<div class="row">
<label string="Allowed" for="pos_fiscal_position_ids" class="col-lg-3 o_light_label"/>
<field name="pos_fiscal_position_ids" widget="many2many_tags" options="{'no_create': True}" domain="['|',('company_id', '=', company_id),('company_id', '=', False)]"/>
</div>
<div>
<button name="%(account.action_account_fiscal_position_form)d" icon="fa-arrow-right" type="action" string="Fiscal Positions" class="btn-link"/>
</div>
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_right_pane">
<span class="o_form_label">Default Journals</span>
<div class="text-muted">
Default journals for orders and invoices
</div>
<div class="content-group mt16">
<div class="row" title="Whenever you close a session, one entry is generated in the following accounting journal for all the orders not invoiced. Invoices are recorded in accounting separately.">
<label string="Orders" for="pos_journal_id" class="col-lg-3 o_light_label" options="{'no_open': True, 'no_create': True}"/>
<field name="pos_journal_id" domain="[('company_id', '=', company_id), ('type', 'in', ('general', 'sale'))]" context="{'default_company_id': company_id, 'default_type': 'general'}" attrs="{'required': [('pos_company_has_template', '=', True)]}"/>
</div>
<div class="row">
<label string="Invoices" for="pos_invoice_journal_id" class="col-lg-3 o_light_label"/>
<field name="pos_invoice_journal_id"
domain="[('company_id', '=', company_id), ('type', '=', 'sale')]"
attrs="{'required': [('pos_company_has_template', '=', True)]}"
context="{'default_company_id': company_id, 'default_type': 'sale'}"/>
</div>
</div>
</div>
</div>
</div>
<h2>Pricing</h2>
<div class="row mt16 o_settings_container" id="pos_pricing_section">
<div class="col-12 col-lg-6 o_setting_box" id="multiple_prices_setting">
<div class="o_setting_left_pane">
<field name="pos_use_pricelist" attrs="{'readonly': [('pos_has_active_session','=', True)]}"/>
</div>
<div class="o_setting_right_pane">
<label for="pos_use_pricelist" string="Flexible Pricelists" />
<div class="text-muted">
Set multiple prices per product, automated discounts, etc.
</div>
<div class="content-group" attrs="{'invisible': [('pos_use_pricelist' ,'=', False)]}">
<div class="mt16">
<field name="group_sale_pricelist" invisible="1"/>
<field name="product_pricelist_setting" widget="radio" class="o_light_label"/>
</div>
<div class="row mt16">
<label string="Available" for="pos_available_pricelist_ids" class="col-lg-3 o_light_label"/>
<field name="pos_available_pricelist_ids" widget="many2many_tags" domain="['|',('company_id', '=', company_id),('company_id', '=', False)]" attrs="{'readonly': [('pos_has_active_session','=', True)]}"/>
</div>
<div class="row mt16" attrs="{'invisible': [('is_default_pricelist_displayed', '=', False)]}">
<label string="Default" for="pos_pricelist_id" class="col-lg-3 o_light_label"/>
<field name="pos_pricelist_id" domain="[('id', 'in', pos_allowed_pricelist_ids)]" options="{'no_create': True}"/>
</div>
<div class="mt8">
<button name="%(product.product_pricelist_action2)d" icon="fa-arrow-right" type="action" string="Pricelists" groups="product.group_product_pricelist" class="btn-link"/>
</div>
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box price_control" title="Only users with Manager access rights for PoS app can modify the product prices on orders.">
<div class="o_setting_left_pane">
<field name="pos_restrict_price_control"/>
</div>
<div class="o_setting_right_pane">
<label for="pos_restrict_price_control" string="Price Control"/>
<div class="text-muted">
Restrict price modification to managers
</div>
</div>
</div>
<div class="col-xs-12 col-lg-6 o_setting_box" id="product_prices">
<div class="o_setting_right_pane">
<label for="pos_iface_tax_included" string="Product Prices"/>
<div class="text-muted">
Product prices on receipts
</div>
<div class="content-group">
<div class="mt16">
<field name="pos_iface_tax_included" class="o_light_label" widget="radio"/>
</div>
<a attrs="{'invisible': [('pos_iface_tax_included', '!=', 'total')]}"
href="https://www.odoo.com/documentation/16.0/applications/finance/accounting/taxation/taxes/B2B_B2C.html"
target="_blank" class="oe-link"><i class="fa fa-fw fa-arrow-right"/>How to manage tax-included prices</a>
</div>
</div>
</div>
<div class="col-xs-12 col-lg-6 o_setting_box" >
<div class="o_setting_left_pane">
<field name="pos_manual_discount"/>
</div>
<div class="o_setting_right_pane">
<label for="pos_manual_discount"/>
<div class="text-muted">
Allow cashiers to set a discount per line
</div>
</div>
</div>
<div class="col-xs-12 col-lg-6 o_setting_box" >
<div class="o_setting_left_pane">
<field name="pos_module_pos_discount" attrs="{'readonly': [('pos_has_active_session','=', True)]}"/>
</div>
<div class="o_setting_right_pane">
<label for="pos_module_pos_discount"/>
<div class="text-muted">
Adds a button to set a global discount
</div>
<div class="content-group mt16" attrs="{'invisible':[('pos_module_pos_discount','=',False)]}">
<div class="text-warning mb4" id="warning_text_pos_discount" >
Save this page and come back here to set up the feature.
</div>
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box" id="pos-loyalty"
title="Boost your sales with multiple kinds of programs: Coupons, Promotions, Gift Card, Loyalty. Specific conditions can be set (products, customers, minimum purchase amount, period). Rewards can be discounts (% or amount) or free products.">
<div class="o_setting_left_pane">
<field name="module_loyalty" nolabel="1"/>
</div>
<div class="o_setting_right_pane">
<label for="module_loyalty" string="Promotions, Coupons, Gift Card &amp; Loyalty Program"/>
<div class="text-muted" id="loyalty_program_text" >
Manage promotion that will grant customers discounts or gifts
</div>
</div>
</div>
</div>
<h2>Bills &amp; Receipts</h2>
<div class="row mt16 o_settings_container" id="pos_bills_and_receipts_section">
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="pos_is_header_or_footer"/>
</div>
<div class="o_setting_right_pane">
<label for="pos_is_header_or_footer"/>
<div class="text-muted">
Add a custom message to header and footer
</div>
<div class="content-group mt16" attrs="{'invisible' : [('pos_is_header_or_footer', '=', False)]}">
<div>
<label string="Header" for="pos_receipt_header" class="col-lg-2 o_light_label"/>
<field name="pos_receipt_header" placeholder="e.g. Company Address, Website"/>
</div>
<div>
<label string="Footer" for="pos_receipt_footer" class="col-lg-2 o_light_label"/>
<field name="pos_receipt_footer" placeholder="e.g. Return Policy, Thanks for shopping with us!"/>
</div>
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box" id="auto_printing">
<div class="o_setting_left_pane">
<field name="pos_iface_print_auto"/>
</div>
<div class="o_setting_right_pane">
<label for="pos_iface_print_auto"/>
<div class="text-muted">
Print receipts automatically once the payment is registered
</div>
<div class="content-group mt16" attrs="{'invisible' : ['|', ('pos_iface_print_auto', '=', False), '&amp;', ('pos_is_posbox', '=', False), ('pos_other_devices', '=', False)]}">
<div>
<field name="pos_iface_print_skip_screen" class="oe_inline"/><span class="oe_inline"><b>Skip Preview Screen</b></span>
</div>
</div>
</div>
<div class="o_setting_left_pane mt-4">
<field name="point_of_sale_use_ticket_qr_code"/>
</div>
<div class="o_setting_right_pane mt-4">
<label for="point_of_sale_use_ticket_qr_code"/>
<div class="text-muted">
Print a QR code on the receipt to allow the user to easily request the invoice for an order.
</div>
</div>
</div>
<div id="order_reference" class="col-12 col-lg-6 o_setting_box" groups="base.group_no_one">
<div class="o_setting_right_pane">
<span class="o_form_label">Order Reference</span>
<div class="text-muted">
Generation of your order references
</div>
<div class="content-group mt16">
<field name="pos_sequence_id" readonly="1"/>
</div>
</div>
</div>
</div>
<h2>Payment</h2>
<div class="row mt16 o_settings_container" id="pos_payment_section">
<div class="col-12 col-lg-6 o_setting_box" id="payment_methods_new">
<div class="o_setting_right_pane">
<span class="o_form_label">Payment Methods</span>
<div class="text-muted">
Payment methods available
</div>
<div class="content-group mt16">
<field name="pos_payment_method_ids" colspan="4" nolabel="1" widget="many2many_tags" attrs="{'readonly': [('pos_has_active_session','=', True)], 'required': [('pos_company_has_template', '=', True)]}" options="{'no_create': True}" />
</div>
<div>
<button name="%(action_payment_methods_tree)d" icon="fa-arrow-right" type="action" string="Payment Methods" class="btn-link"/>
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="pos_cash_rounding" attrs="{'readonly': [('pos_has_active_session', '=', True)]}"/>
</div>
<div class="o_setting_right_pane">
<label for="pos_cash_rounding" string="Cash Rounding" />
<a href="https://www.odoo.com/documentation/16.0/applications/sales/point_of_sale/pricing/cash_rounding.html"
title="Documentation" class="o_doc_link" target="_blank"></a>
<div class="text-muted">
Define the smallest coinage of the currency used to pay by cash
</div>
<div class="content-group mt16" attrs="{'invisible': [('pos_cash_rounding', '=', False)]}">
<div class="row mt16">
<label string="Rounding Method" for="pos_rounding_method" class="col-lg-3 o_light_label" />
<field name="pos_rounding_method" attrs="{'readonly': [('pos_has_active_session', '=', True)], 'required' : [('pos_cash_rounding', '=', True)]}" domain="[('company_id', '=', company_id)]"/>
</div>
<div class="row mt16">
<div class="col">
<field name="pos_only_round_cash_method" attrs="{'readonly': [('pos_has_active_session', '=', True)]}"/>
<label string="Only on cash methods" for="pos_only_round_cash_method" class="o_light_label" />
</div>
</div>
</div>
<div class="mt8">
<button name="%(account.rounding_list_action)d" icon="fa-arrow-right"
type="action" string="Cash Roundings" class="btn-link"
attrs="{'invisible': [('group_cash_rounding', '=', False)]}"/>
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="pos_set_maximum_difference" />
</div>
<div class="o_setting_right_pane">
<label for="pos_set_maximum_difference" />
<div class="text-muted">
Set a maximum difference allowed between the expected and counted money during the closing of the session
</div>
<div class="content-group mt16" attrs="{'invisible': [('pos_set_maximum_difference', '=', False)]}">
<label for="pos_amount_authorized_diff" string="Authorized Difference" class="fw-normal"/>
<field name="pos_amount_authorized_diff"/>
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box" attrs="{'invisible': [('pos_cash_control', '=', False)]}">
<div class="o_setting_right_pane">
<label for="pos_default_bill_ids" string="Coins/Bills" />
<div class="text-muted">
Set of coins/bills that will be used in opening and closing control
</div>
<div class="content-group mt16">
<field name="pos_default_bill_ids" colspan="4" widget="many2many_tags" options="{'no_create_edit': True}" context="{'default_pos_config_ids':[(6, False, [pos_config_id])]}"/>
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box"
id="iface_tipproduct"
title="This product is used as reference on customer receipts.">
<div class="o_setting_left_pane">
<field name="pos_iface_tipproduct" attrs="{'readonly': [('pos_has_active_session','=', True)]}"/>
</div>
<div class="o_setting_right_pane">
<label for="pos_iface_tipproduct" string="Tips"/>
<div class="text-muted">
Accept customer tips or convert their change to a tip
</div>
<div class="content-group" attrs="{'invisible': [('pos_iface_tipproduct', '=', False)]}">
<div class="mt16" id="tip_product">
<label string="Tip Product" for="pos_tip_product_id" class="o_light_label"/>
<field name="pos_tip_product_id"/>
</div>
</div>
</div>
</div>
</div>
<h2>
Payment Terminals
<i class="fa fa-info-circle me-1" title="Those settings are common to all PoS." pos-data-toggle="tooltip"/>
</h2>
<div class="row mt16 o_settings_container" id="pos_payment_terminals_section">
<div class="col-12 col-lg-6 o_setting_box"
id="adyen_payment_terminal_setting"
title="The transactions are processed by Adyen. Set your Adyen credentials on the related payment method.">
<div class="o_setting_left_pane">
<field name="module_pos_adyen"/>
</div>
<div class="o_setting_right_pane">
<label for="module_pos_adyen" string="Adyen"/>
<div class="text-muted">
Accept payments with an Adyen payment terminal
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box"
id="stripe_payment_terminal_setting"
title="The transactions are processed by Stripe. Set your Stripe credentials on the related payment method.">
<div class="o_setting_left_pane">
<field name="module_pos_stripe"/>
</div>
<div class="o_setting_right_pane">
<label for="module_pos_stripe" string="Stripe"/>
<div class="text-muted">
Accept payments with a Stripe payment terminal
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box"
id="vantiv_payment_terminal_setting"
title="The transactions are processed by Vantiv. Set your Vantiv credentials on the related payment method.">
<div class="o_setting_left_pane">
<field name="module_pos_mercury"/>
</div>
<div class="o_setting_right_pane">
<label for="module_pos_mercury" string="Vantiv (US &amp; Canada)"/>
<a href="https://www.odoo.com/documentation/16.0/applications/sales/point_of_sale/payment_methods/terminals/vantiv.html" title="Documentation" class="o_doc_link" target="_blank"></a>
<div class="text-muted">
Accept payments with a Vantiv payment terminal
</div>
<div class="content-group" attrs="{'invisible': [('module_pos_mercury', '=', False)]}">
<div class="mt16" id="btn_use_pos_mercury">
</div>
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box" title="The transactions are processed by Six. Set the IP address of the terminal on the related payment method.">
<div class="o_setting_left_pane">
<field name="module_pos_six"/>
</div>
<div class="o_setting_right_pane">
<label for="module_pos_six" string="Six"/>
<a href="https://www.odoo.com/documentation/16.0/applications/sales/point_of_sale/payment_methods/terminals/six.html" title="Documentation" class="o_doc_link" target="_blank"></a>
<div class="text-muted">
Accept payments with a Six payment terminal
</div>
</div>
</div>
</div>
<h2>Connected Devices</h2>
<div class="row mt16 o_settings_container" id="pos_connected_devices_section">
<div class="col-12 col-lg-6 o_setting_box" id="pos_other_devices">
<div class="o_setting_left_pane">
<field name="pos_other_devices"/>
</div>
<div class="o_setting_right_pane">
<label for="pos_other_devices" string="ePos Printer"/>
<div class="text-muted mb16">
Connect device to your PoS without an IoT Box
</div>
</div>
</div>
<div id="customer_display" class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="pos_iface_customer_facing_display_local"/>
</div>
<div class="o_setting_right_pane">
<label for="pos_iface_customer_facing_display_local" string="Customer Display"/>
<div class="text-muted">
Show checkout to customers through a second display
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="pos_is_posbox"/>
</div>
<div class="o_setting_right_pane">
<label for="pos_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' : [('pos_is_posbox', '=', False)]}">
<div class="row">
<label string="IoT Box IP Address" for="pos_proxy_ip" class="col-lg-4 o_light_label"/>
<field name="pos_proxy_ip"/>
</div>
<div class="row iot_barcode_scanner">
<label string="Barcode Scanner/Card Reader" for="pos_iface_scan_via_proxy" class="col-lg-4 o_light_label"/>
<field name="pos_iface_scan_via_proxy"/>
</div>
<div class="row">
<label string="Electronic Scale" for="pos_iface_electronic_scale" class="col-lg-4 o_light_label"/>
<field name="pos_iface_electronic_scale"/>
</div>
<div class="row">
<label string="Receipt Printer" for="pos_iface_print_via_proxy" class="col-lg-4 o_light_label"/>
<field name="pos_iface_print_via_proxy"/>
</div>
<div class="row" attrs="{'invisible': [('pos_iface_print_via_proxy', '=', False)]}">
<label string="Cashdrawer" for="pos_iface_cashdrawer" class="col-lg-4 o_light_label"/>
<field name="pos_iface_cashdrawer"/>
</div>
<div class="row">
<label string="Customer Display" for="pos_iface_customer_facing_display_via_proxy" class="col-lg-4 o_light_label"/>
<field name="pos_iface_customer_facing_display_via_proxy"/>
</div>
</div>
</div>
</div>
</div>
<h2>Inventory</h2>
<div class="row mt16 o_settings_container" id="pos_inventory_section">
<div class="col-12 col-lg-6 o_setting_box" title="Operation types show up in the Inventory dashboard.">
<div class="o_setting_right_pane">
<label for="pos_picking_type_id" string="Operation Type"/>
<div class="text-muted">
Used to record product pickings. Products are consumed from its default source location.
</div>
<div class="content-group mt16">
<field name="pos_picking_type_id" domain="[('company_id', '=', company_id)]" attrs="{'required': [('pos_config_id', '!=', False)]}"/>
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="pos_ship_later"/>
</div>
<div class="o_setting_right_pane">
<label for="pos_ship_later" string="Allow Ship Later"/>
<div class="text-muted">
Sell products and deliver them later.
</div>
<div class="mt16" attrs="{'invisible' : [('pos_ship_later', '=', False)]}">
<div>
<label for="pos_warehouse_id" string="Warehouse" class="fw-normal"/>
<field name="pos_warehouse_id" attrs="{'required': [('pos_ship_later', '=', True)]}"/>
</div>
<div groups="stock.group_adv_location">
<label for="pos_route_id" string="Specific route" class="fw-normal"/>
<field name="pos_route_id"/>
</div>
<div>
<label for="pos_picking_policy" class="fw-normal"/>
<field name="pos_picking_policy" attrs="{'required': [('pos_ship_later', '=', True)]}"/>
</div>
</div>
</div>
</div>
<div id="barcode_scanner" class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane">
</div>
<div class="o_setting_right_pane">
<span class="o_form_label">Barcodes</span>
<i class="fa fa-info-circle me-1" title="This setting is common to all PoS." pos-data-toggle="tooltip"/>
<div class="text-muted">
Use barcodes to scan products, customer cards, etc.
</div>
<div class="content-group mt16 row">
<label for="barcode_nomenclature_id" string="Barcode Nomenclature" class="col-lg-3 o_light_label"/>
<field name="barcode_nomenclature_id"/>
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box" id="update_quantities_stock_setting" groups="base.group_no_one">
<div class="o_setting_right_pane">
<div>
<label string="Inventory Management" for="update_stock_quantities"/>
<span class="fa fa-lg fa-building-o" title="Values set here are company-specific." aria-label="Values set here are company-specific." groups="base.group_multi_company" role="img"/>
<div class="text-muted">
Update quantities in stock
</div>
<div class="content-group mt16 o_light_label">
<field name="update_stock_quantities" colspan="4" nolabel="1" widget="radio"/>
</div>
</div>
</div>
</div>
</div>
<h2 groups="base.group_no_one">Technical</h2>
<div class="row mt16 o_settings_container" id="pos_technical_section" groups="base.group_no_one">
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="pos_limited_products_loading"/>
</div>
<div class="o_setting_right_pane">
<label for="pos_limited_products_loading" string="Limited Products Loading"/>
<div class="text-muted">
Only load most common products at the opening of the PoS.
</div>
<div class="content-group mt16" attrs="{'invisible' : [('pos_limited_products_loading', '=', False)]}">
<div class="row">
<label for="pos_limited_products_amount" string="Number of Products Loaded" class="col-lg-3 o_light_label"/>
<field name="pos_limited_products_amount" class="oe_inline"/>
</div>
<div class="mt8">
<field name="pos_product_load_background" class="oe_inline" />
<label for="pos_product_load_background" string="Load all remaining products in the background" />
</div>
</div>
</div>
</div>
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="pos_limited_partners_loading"/>
</div>
<div class="o_setting_right_pane">
<label for="pos_limited_partners_loading" string="Limited Partners Loading"/>
<div class="text-muted">
Only load a limited number of customers at the opening of the PoS.
</div>
<div class="content-group mt16" attrs="{'invisible' : [('pos_limited_partners_loading', '=', False)]}">
<div class="row">
<label for="pos_limited_partners_amount" string="Number of Partners Loaded" class="col-lg-3 o_light_label"/>
<field name="pos_limited_partners_amount" class="oe_inline"/>
</div>
<div class="mt8">
<field name="pos_partner_load_background" class="oe_inline" />
<label for="pos_partner_load_background" string="Load all remaining partners in the background" />
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</xpath>
</field>
</record>
</odoo>

View file

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<record id="view_partner_property_form" model="ir.ui.view">
<field name="name">res.partner.pos.form.inherit</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="priority" eval="4"/>
<field name="arch" type="xml">
<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)]}"
icon="fa-shopping-bag">
<field string="PoS Orders" name="pos_order_count" widget="statinfo"/>
</button>
</div>
<xpath expr="//group[@name='purchase']" position="after">
<group string="Point Of Sale" name="point_of_sale" groups="point_of_sale.group_pos_user">
<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>
</odoo>