diff options
Diffstat (limited to 'addons/point_of_sale/views')
23 files changed, 2703 insertions, 0 deletions
diff --git a/addons/point_of_sale/views/account_journal_view.xml b/addons/point_of_sale/views/account_journal_view.xml new file mode 100644 index 00000000..8a218447 --- /dev/null +++ b/addons/point_of_sale/views/account_journal_view.xml @@ -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> diff --git a/addons/point_of_sale/views/account_statement_view.xml b/addons/point_of_sale/views/account_statement_view.xml new file mode 100644 index 00000000..781921d5 --- /dev/null +++ b/addons/point_of_sale/views/account_statement_view.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + <record id="view_bank_statement_pos_session" model="ir.ui.view"> + <field name="name">view.bank.statement.pos.session</field> + <field name="model">account.bank.statement</field> + <field name="mode">primary</field> + <field name="priority">1000</field> + <field name="inherit_id" ref="account.view_bank_statement_form"/> + <field name="arch" type="xml"> + <xpath expr="//button[@name='button_validate_or_action']" position="replace"/> + </field> + </record> + + <record id="view_account_bnk_stmt_cashbox" model="ir.ui.view"> + <field name="name">account.bnk_stmt_cashbox.form</field> + <field name="model">account.bank.statement.cashbox</field> + <field name="inherit_id" ref="account.view_account_bnk_stmt_cashbox"/> + <field name="arch" type="xml"> + <xpath expr="//sheet" position="inside"> + <field name="is_a_template" invisible="1"/> + </xpath> + </field> + </record> + + <record id="view_account_bnk_stmt_cashbox_footer" model="ir.ui.view"> + <field name="name">account.bnk_stmt_cashbox.form.close.modal</field> + <field name="model">account.bank.statement.cashbox</field> + <field name="inherit_id" ref="account.view_account_bnk_stmt_cashbox_footer"/> + <field name="mode">primary</field> + <field name="priority">1000</field> + <field name="arch" type="xml"> + <xpath expr="//field[@name='cashbox_lines_ids']" position="before"> + <button name="set_default_cashbox" type="object" string="Set Default Cash Opening" /> + </xpath> + </field> + </record> + + <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> diff --git a/addons/point_of_sale/views/customer_facing_display.xml b/addons/point_of_sale/views/customer_facing_display.xml new file mode 100644 index 00000000..e9468604 --- /dev/null +++ b/addons/point_of_sale/views/customer_facing_display.xml @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + + <template id="customer_facing_display_html" > + <t name="point_of_sale.customer_facing_display_html" > + <div class="pos-customer_facing_display pos-palette_01"> + <div class="pos-customer_products" name="Products list"> + <div class="pos_orderlines"> + <div class="pos_orderlines_item pos_orderlines_header"> + <div/> + <div/> + <div>Quantity</div> + <div>Price</div> + </div> + <div class="pos_orderlines_list"> + <div class="pos_orderlines_item"> + <div><div style="background-image:url(/point_of_sale/static/img/monitor_stand.png)"/></div> + <div>Monitor Stand</div> + <div>2</div> + <div>$ 4.40</div> + </div> + <div class="pos_orderlines_item"> + <div><div style="background-image:url(/point_of_sale/static/img/led_lamp.png)"/></div> + <div>Led Lamp</div> + <div>3</div> + <div>$ 3.12</div> + </div> + <div class="pos_orderlines_item"> + <div><div style="background-image:url(/point_of_sale/static/img/whiteboard_pen.png)"/></div> + <div>Whiteboard Pen</div> + <div>3</div> + <div>$ 8.50</div> + </div> + <div class="pos_orderlines_item"> + <div><div style="background-image:url(/point_of_sale/static/img/desk_organizer.png)"/></div> + <div>Desk Organizer</div> + <div>1</div> + <div>$ 4.50</div> + </div> + </div> + </div> + </div> + + <div class="pos-payment_info"> + <div class="pos-company_logo"/> + + <div class="pos-payment_info_details"> + <div class="pos-total"> + <div> + <span class="total-amount-formatting">TOTAL</span> + </div> + <div> + <span id="total-amount" class="pos_total-amount">$ 469.14</span> + </div> + </div> + <div class="pos-paymentlines"> + <div> + <span>Cash (USD):</span> + </div> + <div> + <span>$ 470.00</span> + </div> + <div> + <span class="pos-change_title">Change</span> + </div> + <div> + <span class="pos-change_amount">$ 0.86</span> + </div> + </div> + <div class="pos-odoo_logo_container"> + <img src="/web/static/src/img/logo_inverse_white_206px.png" alt="Odoo Logo"/> + </div> + </div> + </div> + </div> + </t> + </template> + +</odoo> diff --git a/addons/point_of_sale/views/digest_views.xml b/addons/point_of_sale/views/digest_views.xml new file mode 100644 index 00000000..5c7deb86 --- /dev/null +++ b/addons/point_of_sale/views/digest_views.xml @@ -0,0 +1,15 @@ +<?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="inherit_id" ref="digest.digest_digest_view_form" /> + <field name="arch" type="xml"> + <xpath expr="//group[@name='kpi_general']" position="after"> + <group name="kpi_pos" string="Point of Sale"> + <field name="kpi_pos_total"/> + </group> + </xpath> + </field> + </record> +</odoo> diff --git a/addons/point_of_sale/views/point_of_sale_dashboard.xml b/addons/point_of_sale/views/point_of_sale_dashboard.xml new file mode 100644 index 00000000..76609abe --- /dev/null +++ b/addons/point_of_sale/views/point_of_sale_dashboard.xml @@ -0,0 +1,163 @@ +<?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"/> + <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 && record.pos_session_username.value"> + <div class="badge badge-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 badge-info o_kanban_inline_block">Opening Control</div> + </t> + <t t-if="record.pos_session_state.raw_value == 'closing_control'"> + <div class="badge badge-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 badge-#{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 === 'opened'" class="btn btn-primary" name="open_ui" type="object">Resume</button> + + <button t-if="record.current_session_state.raw_value === 'new_session' || record.current_session_state.raw_value === 'opening_control'" class="btn btn-primary" name="open_existing_session_cb" type="object">Open Session</button> + + <button t-if="_.contains(['opened', 'closing_control'], record.current_session_state.raw_value)" class="btn btn-secondary" name="open_existing_session_cb" type="object">Close</button> + + <button t-if="!record.current_session_id.raw_value && !record.pos_session_username.value" class="btn btn-primary" name="open_session_cb" type="object">New Session</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>Cash Balance</span> + </div> + <div class="col-6"> + <span><field name="last_session_closing_cash" widget="monetary"/></span> + </div> + </div> + </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 type="edit">Settings</a> + </div> + </div> + </div> + </div> + </t> + </templates> + </kanban> + </field> + </record> + +</odoo> diff --git a/addons/point_of_sale/views/point_of_sale_report.xml b/addons/point_of_sale/views/point_of_sale_report.xml new file mode 100644 index 00000000..0ede9537 --- /dev/null +++ b/addons/point_of_sale/views/point_of_sale_report.xml @@ -0,0 +1,31 @@ +<?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> + + <!-- used from POS UI, no need to be in print menu --> + <record id="pos_invoice_report" model="ir.actions.report"> + <field name="name">Invoice</field> + <field name="model">pos.order</field> + <field name="report_type">qweb-pdf</field> + <field name="report_name">point_of_sale.report_invoice</field> + <field name="print_report_name">'Invoice - %s' % (object.name)</field> + </record> + + <record id="sale_details_report" model="ir.actions.report"> + <field name="name">Sales Details</field> + <field name="model">report.point_of_sale.report_saledetails</field> + <field name="report_type">qweb-pdf</field> + <field name="report_name">point_of_sale.report_saledetails</field> + </record> + + <template id="report_invoice" inherit_id="account.report_invoice" primary="True"/> + +</odoo> diff --git a/addons/point_of_sale/views/point_of_sale_sequence.xml b/addons/point_of_sale/views/point_of_sale_sequence.xml new file mode 100644 index 00000000..3b3a3d96 --- /dev/null +++ b/addons/point_of_sale/views/point_of_sale_sequence.xml @@ -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> diff --git a/addons/point_of_sale/views/point_of_sale_view.xml b/addons/point_of_sale/views/point_of_sale_view.xml new file mode 100644 index 00000000..933233bc --- /dev/null +++ b/addons/point_of_sale/views/point_of_sale_view.xml @@ -0,0 +1,42 @@ +<?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.png" + sequence="20"/> + + <!-- 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"/> + +</odoo> diff --git a/addons/point_of_sale/views/pos_assets_common.xml b/addons/point_of_sale/views/pos_assets_common.xml new file mode 100644 index 00000000..c648299b --- /dev/null +++ b/addons/point_of_sale/views/pos_assets_common.xml @@ -0,0 +1,127 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + +<template id="point_of_sale.assets" name="point_of_sale assets"> + <link rel="stylesheet" type="text/scss" href="/web/static/src/scss/fonts.scss"/> + <link rel="stylesheet" href="/web/static/lib/fontawesome/css/font-awesome.css"/> + <link rel="stylesheet" href="/point_of_sale/static/src/css/pos.css" id="pos-stylesheet"/> + <link rel="stylesheet" href="/point_of_sale/static/src/css/keyboard.css"/> + <link rel="stylesheet" href="/point_of_sale/static/src/css/pos_receipts.css"/> + <link rel="stylesheet" type="text/less" href="/web/static/src/scss/fontawesome_overridden.scss"/> + + <script type="text/javascript" src="/point_of_sale/static/lib/html2canvas.js"></script> + <script type="text/javascript" src="/point_of_sale/static/lib/backbone/backbone.js"></script> + <script type="text/javascript" src="/point_of_sale/static/lib/waitfont.js"></script> + <script type="text/javascript" src="/point_of_sale/static/lib/sha1.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/utils.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/ClassRegistry.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/PosComponent.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/PosContext.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/ComponentRegistry.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Registries.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/db.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/models.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/keyboard.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/barcode_reader.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/printers.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Gui.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/PopupControllerMixin.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/ControlButtonsMixin.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Chrome.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/devices.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/payment.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/custom_hooks.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/ProductScreen/ProductScreen.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/ClientListScreen/ClientLine.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/ClientListScreen/ClientDetailsEdit.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/ClientListScreen/ClientListScreen.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/OrderManagementScreen/ControlButtons/InvoiceButton.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/OrderManagementScreen/ControlButtons/ReprintReceiptButton.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/OrderManagementScreen/OrderFetcher.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/OrderManagementScreen/OrderManagementScreen.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/OrderManagementScreen/MobileOrderManagementScreen.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/OrderManagementScreen/OrderManagementControlPanel.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/OrderManagementScreen/OrderList.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/OrderManagementScreen/OrderRow.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/OrderManagementScreen/OrderDetails.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/OrderManagementScreen/OrderlineDetails.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/OrderManagementScreen/ReprintReceiptScreen.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/TicketScreen/TicketScreen.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/PaymentScreen/PSNumpadInputButton.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/PaymentScreen/PaymentScreenNumpad.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/PaymentScreen/PaymentScreenElectronicPayment.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/PaymentScreen/PaymentScreenPaymentLines.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/PaymentScreen/PaymentScreenStatus.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/PaymentScreen/PaymentMethodButton.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/PaymentScreen/PaymentScreen.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/ProductScreen/Orderline.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/ProductScreen/OrderSummary.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/ProductScreen/OrderWidget.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/ProductScreen/NumpadWidget.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/ProductScreen/ActionpadWidget.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/ProductScreen/CategoryBreadcrumb.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/ProductScreen/CashBoxOpening.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/ProductScreen/CategoryButton.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/ProductScreen/CategorySimpleButton.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/ProductScreen/HomeCategoryBreadcrumb.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/ProductScreen/ProductsWidgetControlPanel.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/ProductScreen/ProductItem.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/ProductScreen/ProductList.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/ProductScreen/ProductsWidget.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/ReceiptScreen/WrappedProductNameLines.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/ReceiptScreen/OrderReceipt.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/ReceiptScreen/ReceiptScreen.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/ScaleScreen/ScaleScreen.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/ChromeWidgets/CashierName.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/ChromeWidgets/ProxyStatus.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/ChromeWidgets/SyncNotification.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/ChromeWidgets/OrderManagementButton.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/ChromeWidgets/HeaderButton.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/ChromeWidgets/SaleDetailsButton.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/ChromeWidgets/TicketButton.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Misc/Draggable.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Misc/NotificationSound.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Misc/IndependentToOrderScreen.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Misc/AbstractReceiptScreen.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Misc/SearchBar.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/ChromeWidgets/DebugWidget.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Popups/AbstractAwaitablePopup.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Popups/ErrorPopup.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Popups/ErrorBarcodePopup.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Popups/ConfirmPopup.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Popups/TextInputPopup.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Popups/TextAreaPopup.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Popups/ErrorTracebackPopup.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Popups/SelectionPopup.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Popups/EditListInput.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Popups/EditListPopup.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Popups/NumberPopup.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Popups/OfflineErrorPopup.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Popups/OrderImportPopup.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Popups/ProductConfiguratorPopup.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/ProductScreen/ControlButtons/SetPricelistButton.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Screens/ProductScreen/ControlButtons/SetFiscalPositionButton.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/ChromeWidgets/ClientScreenButton.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Misc/NumberBuffer.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/Misc/MobileOrderWidget.js"></script> +</template> + +<template id="point_of_sale.assets_backend" name="hr assets" inherit_id="web.assets_backend"> + <xpath expr="." position="inside"> + <link rel="stylesheet" type="text/scss" href="/point_of_sale/static/src/scss/pos_dashboard.scss"/> + <script type="text/javascript" src="/point_of_sale/static/src/js/tours/point_of_sale.js"></script> + <script type="text/javascript" src="/point_of_sale/static/src/js/debug_manager.js"></script> + </xpath> +</template> + +<template id="point_of_sale.pos_assets_backend" name="POS UI Backend Assets" inherit_id="web.assets_backend" primary="True"> +</template> + +<template id="point_of_sale.assets_common" name="POS Assets Common"> + <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> diff --git a/addons/point_of_sale/views/pos_assets_index.xml b/addons/point_of_sale/views/pos_assets_index.xml new file mode 100644 index 00000000..c32a7f64 --- /dev/null +++ b/addons/point_of_sale/views/pos_assets_index.xml @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + +<!-- This contains the tour assets. They are included during testing. --> +<template id="assets_tests" name="Point Of Sale Assets Tests" inherit_id="web.assets_tests"> + <xpath expr="." position="inside"> + <script type="text/javascript" src="/point_of_sale/static/tests/tours/helpers/utils.js"></script> + <script type="text/javascript" src="/point_of_sale/static/tests/tours/helpers/ProductScreenTourMethods.js"></script> + <script type="text/javascript" src="/point_of_sale/static/tests/tours/helpers/TicketScreenTourMethods.js"></script> + <script type="text/javascript" src="/point_of_sale/static/tests/tours/helpers/PaymentScreenTourMethods.js"></script> + <script type="text/javascript" src="/point_of_sale/static/tests/tours/helpers/ProductConfiguratorTourMethods.js"></script> + <script type="text/javascript" src="/point_of_sale/static/tests/tours/helpers/OrderManagementScreenTourMethods.js"></script> + <script type="text/javascript" src="/point_of_sale/static/tests/tours/helpers/ClientListScreenTourMethods.js"></script> + <script type="text/javascript" src="/point_of_sale/static/tests/tours/helpers/ReceiptScreenTourMethods.js"></script> + <script type="text/javascript" src="/point_of_sale/static/tests/tours/helpers/ChromeTourMethods.js"></script> + <script type="text/javascript" src="/point_of_sale/static/tests/tours/helpers/NumberPopupTourMethods.js"></script> + <script type="text/javascript" src="/point_of_sale/static/tests/tours/helpers/ErrorPopupTourMethods.js"></script> + <script type="text/javascript" src="/point_of_sale/static/tests/tours/helpers/SelectionPopupTourMethods.js"></script> + <script type="text/javascript" src="/point_of_sale/static/tests/tours/helpers/CompositeTourMethods.js"></script> + <script type="text/javascript" src="/point_of_sale/static/tests/tours/point_of_sale.js"></script> + <script type="text/javascript" src="/point_of_sale/static/tests/tours/ProductScreen.tour.js"></script> + <script type="text/javascript" src="/point_of_sale/static/tests/tours/PaymentScreen.tour.js"></script> + <script type="text/javascript" src="/point_of_sale/static/tests/tours/ProductConfigurator.tour.js"></script> + <script type="text/javascript" src="/point_of_sale/static/tests/tours/OrderManagementScreen.tour.js"></script> + <script type="text/javascript" src="/point_of_sale/static/tests/tours/ReceiptScreen.tour.js"></script> + <script type="text/javascript" src="/point_of_sale/static/tests/tours/Chrome.tour.js"></script> + <script type="text/javascript" src="/point_of_sale/static/tests/tours/TicketScreen.tour.js"></script> + </xpath> +</template> + +<template id="point_of_sale.index" name="POS Index"><!DOCTYPE html> +<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="/web/static/src/img/favicon.ico" type="image/x-icon"/> + + <script type="text/javascript"> + var odoo = <t t-raw="json.dumps({ + 'csrf_token': request.csrf_token(None), + 'session_info': session_info, + 'login_number': login_number, + 'debug': debug, + })"/>; + </script> + + <t t-call="point_of_sale.assets_common"/> + <t t-call="web.conditional_assets_tests"/> + <script type="text/javascript" src="/point_of_sale/static/src/js/main.js"></script> + </head> + <body> + </body> +</html> +</template> + +</odoo> diff --git a/addons/point_of_sale/views/pos_assets_qunit.xml b/addons/point_of_sale/views/pos_assets_qunit.xml new file mode 100644 index 00000000..e58b3059 --- /dev/null +++ b/addons/point_of_sale/views/pos_assets_qunit.xml @@ -0,0 +1,84 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + +<template id="point_of_sale.qunit_suite_assets"> + <t t-call-assets="point_of_sale.pos_assets_backend" t-js="false"/> + + <link type="text/css" rel="stylesheet" href="/web/static/lib/qunit/qunit-2.9.1.css"/> + <script type="text/javascript" src="/web/static/lib/qunit/qunit-2.9.1.js"></script> + <script type="text/javascript" src="/web/static/tests/helpers/qunit_config.js"></script> + <script type="text/javascript" src="/web/static/tests/helpers/qunit_asserts.js"></script> + + <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> + + <script type="text/javascript" src="/web/static/tests/helpers/test_utils_create.js"></script> + <script type="text/javascript" src="/web/static/tests/helpers/test_utils_control_panel.js"></script> + <script type="text/javascript" src="/web/static/tests/helpers/test_utils_dom.js"></script> + <script type="text/javascript" src="/web/static/tests/helpers/test_utils_fields.js"></script> + <script type="text/javascript" src="/web/static/tests/helpers/test_utils_file.js"></script> + <script type="text/javascript" src="/web/static/tests/helpers/test_utils_form.js"></script> + <script type="text/javascript" src="/web/static/tests/helpers/test_utils_graph.js"></script> + <script type="text/javascript" src="/web/static/tests/helpers/test_utils_kanban.js"></script> + <script type="text/javascript" src="/web/static/tests/helpers/test_utils_mock.js"></script> + <script type="text/javascript" src="/web/static/tests/helpers/test_utils_modal.js"></script> + <script type="text/javascript" src="/web/static/tests/helpers/test_utils_pivot.js"></script> + <script type="text/javascript" src="/web/static/tests/helpers/test_utils.js"></script> + <script type="text/javascript" src="/web/static/tests/helpers/mock_server.js"></script> + <script type="text/javascript" src="/web/static/tests/helpers/test_env.js"></script> + + <script type="text/javascript" src="/web/static/tests/component_extension_tests.js"></script> + <script type="text/javascript" src="/web/static/tests/boot_tests.js"></script> + + <script type="text/javascript" src="/point_of_sale/static/tests/unit/helpers/test_env.js"></script> + <script type="text/javascript" src="/point_of_sale/static/tests/unit/helpers/test_main.js"></script> +</template> + +<template id="point_of_sale.qunit_suite_tests"> + <script type="text/javascript" src="/point_of_sale/static/tests/unit/test_ComponentRegistry.js"></script> + <script type="text/javascript" src="/point_of_sale/static/tests/unit/test_NumberBuffer.js"></script> + <script type="text/javascript" src="/point_of_sale/static/tests/unit/test_ChromeWidgets.js"></script> + <script type="text/javascript" src="/point_of_sale/static/tests/unit/test_ProductScreen.js"></script> + <script type="text/javascript" src="/point_of_sale/static/tests/unit/test_PaymentScreen.js"></script> + <script type="text/javascript" src="/point_of_sale/static/tests/unit/test_popups.js"></script> +</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 PosModel --> + <script type="text/javascript"> + var odoo = <t t-raw="json.dumps({ + 'csrf_token': request.csrf_token(None), + 'session_info': session_info, + 'debug': debug, + })"/>; + </script> + + <t t-call="point_of_sale.assets_common" /> + <t t-call="point_of_sale.qunit_suite_assets" /> + <t t-call="point_of_sale.qunit_suite_tests" /> + </t> + + <div id="qunit"/> + <div id="qunit-fixture"/> + </t> +</template> + +</odoo> diff --git a/addons/point_of_sale/views/pos_category_view.xml b/addons/point_of_sale/views/pos_category_view.xml new file mode 100644 index 00000000..db96eb87 --- /dev/null +++ b/addons/point_of_sale/views/pos_category_view.xml @@ -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" class="oe_edit_only"/> + <h1> + <field name="name" placeholder="e.g. Soft Drinks" required="True"/> + </h1> + </div> + <group> + <group> + <field name="parent_id"/> + <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> diff --git a/addons/point_of_sale/views/pos_config_view.xml b/addons/point_of_sale/views/pos_config_view.xml new file mode 100644 index 00000000..7101856c --- /dev/null +++ b/addons/point_of_sale/views/pos_config_view.xml @@ -0,0 +1,607 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + + <!--Account cashbox line--> + + <record id="account_cashbox_line_view_tree" model="ir.ui.view"> + <field name="name">account.cashbox.line.tree</field> + <field name="model">account.cashbox.line</field> + <field name="arch" type="xml"> + <tree string="Cashbox balance" editable="top"> + <field name="coin_value"/> + <field name="number"/> + <field name="subtotal"/> + </tree> + </field> + </record> + + <record id="account_cashbox_line_action" model="ir.actions.act_window"> + <field name="name">Opening/Closing Values</field> + <field name="type">ir.actions.act_window</field> + <field name="res_model">account.cashbox.line</field> + <field name="view_mode">tree,form</field> + <field name="view_id" ref="account_cashbox_line_view_tree"/> + </record> + + <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="currency_id" invisible="1"/> + <field name="selectable_categ_ids" invisible="1"/> + <field name="is_installed_account_accountant" invisible="1"/> + <field name="company_has_template" invisible="1"/> + <field name="allowed_pricelist_ids" invisible="1"/> + <field name="has_active_session" invisible="1"/> + <field name="show_allow_invoicing_alert" invisible="1"/> + <div class="oe_title" id="title"> + <label for="name" class="oe_edit_only"/> + <h1><field name="name"/></h1> + </div> + <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. + </div> + <div class="row mt16 o_settings_container"> + <div id="company" class="col-12 col-lg-6 o_setting_box" groups="base.group_multi_company"> + <div class="o_setting_right_pane"> + <label for="company_id"/> + <div><field name="company_id" readonly="1"/></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> + </div> + </div> + <div class="row mt16 o_settings_container"> + <div class="col-12 col-lg-6 o_setting_box"> + <div class="o_setting_left_pane"> + <field name="module_pos_restaurant" attrs="{'readonly': [('has_active_session','=', True)]}"/> + </div> + <div class="o_setting_right_pane"> + <label for="module_pos_restaurant"/> + <button string="Save" type="object" name="execute" class="oe_highlight" id="btn_use_pos_restaurant" attrs="{'invisible': [('module_pos_restaurant','=',False)]}" /> + </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="module_pos_hr" attrs="{'readonly': [('has_active_session','=', True)]}"/> + </div> + <div class="o_setting_right_pane" id="login_with_employees"> + <span class="o_form_label">Authorized Employees</span> + <div class="text-muted"> + Use employee credentials to log in to the PoS session and switch cashier + </div> + <button string="Save" type="object" name="execute" class="oe_highlight" id="btn_use_employees" attrs="{'invisible': [('module_pos_hr','=',False)]}" /> + </div> + </div> + </div> + <h2 name="order">PoS Interface</h2> + <div class="row mt16 o_settings_container"> + <div class="col-12 col-lg-6 o_setting_box"> + <div class="o_setting_left_pane"> + <field name="manage_orders" /> + </div> + <div class="o_setting_right_pane"> + <label for="manage_orders" /> + <div class="text-muted"> + Reprint receipt, refund and exchange orders + </div> + <div class="o_notification_alert alert alert-warning" attrs="{'invisible':[('show_allow_invoicing_alert', '=', False)]}" role="alert"> + Allow invoicing of paid orders by activating 'Invoicing' in the 'Bills & Receipts' section. + </div> + </div> + </div> + <div class="col-12 col-lg-6 o_setting_box" groups="product.group_product_variant" > + <div class="o_setting_left_pane"> + <field name="product_configurator" /> + </div> + <div class="o_setting_right_pane"> + <label for="product_configurator" /> + <div class="text-muted"> + Select product attributes + </div> + </div> + </div> + <div id="category_reference" class="col-12 col-lg-6 o_setting_box"> + <div class="o_setting_left_pane"> + <field name="iface_display_categ_images"/> + </div> + <div class="o_setting_right_pane"> + <label for="iface_display_categ_images" string="Category Pictures"/> + <div class="text-muted"> + Display pictures of product categories + </div> + <div class="content-group mt16" attrs="{'invisible': [('iface_display_categ_images', '=', 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="limit_categories" attrs="{'readonly': [('has_active_session','=', True)]}"/> + </div> + <div class="o_setting_right_pane"> + <label for="limit_categories"/> + <div class="text-muted"> + Pick which product categories are available + </div> + <div class="content-group mt16" attrs="{'invisible': [('limit_categories', '=', False)]}"> + <field name="iface_available_categ_ids" widget="many2many_tags" attrs="{'readonly': [('has_active_session','=', True)]}"/> + </div> + <div class="content-group mt16" attrs="{'invisible': [('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="start_category"/> + </div> + <div class="o_setting_right_pane"> + <label for="start_category"/> + <div class="text-muted"> + Start selling from a default product category + </div> + <div class="content-group mt16" attrs="{'invisible': [('start_category', '=', False)]}"> + <field name="iface_start_categ_id" domain="[('id','in',selectable_categ_ids)]"/> + </div> + </div> + </div> + <div class="col-12 col-lg-6 o_setting_box" > + <div class="o_setting_left_pane"> + <field name="iface_big_scrollbars"/> + </div> + <div class="o_setting_right_pane"> + <label for="iface_big_scrollbars"/> + <div class="text-muted"> + Improve navigation for imprecise industrial touchscreens + </div> + </div> + </div> + </div> + <h2>Connected Devices</h2> + <div class="row mt16 o_settings_container" id="posbox_reference"> + <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" class="col-lg-4 o_light_label"/> + <field name="iface_customer_facing_display"/> + </div> + <field name="customer_facing_display_html" invisible="1"/> + </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="Direct Devices"/> + <div class="text-muted mb16"> + Connect devices to your PoS directly without an IoT Box + </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> + <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> + <h2>Taxes</h2> + <div class="row mt16 o_settings_container"> + <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="tax_regime_selection"/> + </div> + <div class="o_setting_right_pane"> + <label for="tax_regime_selection" string="Fiscal Position per Order"/> + <div class="text-muted"> + Choose among fiscal positions when processing an order + </div> + <div class="content-group" attrs="{'invisible': [('tax_regime_selection', '=', False)]}"> + <div class="mt16"> + <field name="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_left_pane"> + <field name="tax_regime"/> + </div> + <div class="o_setting_right_pane"> + <label for="tax_regime" string="Fiscal Position"/> + <div class="text-muted"> + Use a default specific tax regime + </div> + <div class="content-group" attrs="{'invisible': [('tax_regime', '=', False)]}"> + <div class="mt16"> + <field name="default_fiscal_position_id" attrs="{'required': [('tax_regime', '=', True)]}" domain="['|',('company_id', '=', company_id),('company_id', '=', False)]"/> + </div> + </div> + </div> + </div> + </div> + <h2>Pricing</h2> + <div class="row mt16 o_settings_container" id="pricing"> + <div class="col-12 col-lg-6 o_setting_box" id="default_pricelist_setting" groups="base.group_multi_currency,product.group_product_pricelist"> + <div class="o_setting_right_pane"> + <span class="o_form_label">Default Pricelist</span> + <div class="content-group mt16"> + <field name="pricelist_id" domain="[('id', 'in', allowed_pricelist_ids)]" options="{'no_create': True}"/> + </div> + <div> + <button name="%(product.product_pricelist_action2)d" icon="fa-arrow-right" type="action" string="Pricelists" class="btn-link"/> + </div> + </div> + </div> + <div class="col-12 col-lg-6 o_setting_box" id="pricelist_setting" groups="product.group_product_pricelist"> + <div class="o_setting_left_pane"> + <field name="use_pricelist" attrs="{'readonly': [('has_active_session','=', True)]}"/> + </div> + <div class="o_setting_right_pane"> + <label for="use_pricelist" string="Advanced Pricelists"/> + <div class="text-muted"> + Set shop-specific prices, seasonal discounts, etc. + </div> + <div class="content-group mt16" attrs="{'invisible': [('use_pricelist','=',False)], 'required' : [('use_pricelist', '=', True)]}"> + <div class="row mt16"> + <label string="Available Pricelists" for="available_pricelist_ids" class="col-lg-3 o_light_label"/> + <field name="available_pricelist_ids" widget="many2many_tags" domain="['|',('company_id', '=', company_id),('company_id', '=', False)]" attrs="{'readonly': [('has_active_session','=', True)]}"/> + </div> + </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="iface_tax_included" string="Product Prices"/> + <div class="text-muted"> + Product prices on receipts + </div> + <div class="content-group"> + <div class="mt16"> + <field name="iface_tax_included" class="o_light_label" widget="radio"/> + </div> + <a attrs="{'invisible': [('iface_tax_included', '!=', 'total')]}" + href="https://www.odoo.com/documentation/14.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="module_pos_discount" attrs="{'readonly': [('has_active_session','=', True)]}"/> + </div> + <div class="o_setting_right_pane"> + <label for="module_pos_discount"/> + <div class="text-muted"> + Allow global discounts on orders + </div> + <div class="content-group " attrs="{'invisible':[('module_pos_discount','=',False)]}"> + <div class="mt16" id="btn_use_pos_discount"> + <button string="Save" type="object" name="execute" class="oe_highlight"/> + </div> + </div> + </div> + </div> + <div class="col-xs-12 col-lg-6 o_setting_box" > + <div class="o_setting_left_pane"> + <field name="manual_discount"/> + </div> + <div class="o_setting_right_pane"> + <label for="manual_discount"/> + <div class="text-muted"> + Allow discounts per line + </div> + </div> + </div> + <div class="col-12 col-lg-6 o_setting_box"> + <div class="o_setting_left_pane"> + <field name="module_pos_loyalty" widget="upgrade_boolean" nolabel="1"/> + </div> + <div class="o_setting_right_pane" title="Loyalty program to use for this point of sale. "> + <label for="module_pos_loyalty"/> + <div class="text-muted" id="loyalty_program"> + Give customer rewards, free samples, etc. + </div> + <div class="content-group" attrs="{'invisible': [('module_pos_loyalty', '=', False)]}"> + <div class="mt16" id="btn_use_pos_loyalty"> + <button string="Save" type="object" name="execute" class="oe_highlight"/> + </div> + </div> + </div> + </div> + </div> + <h2>Payments</h2> + <div class="row mt16 o_settings_container"> + <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="payment_method_ids" colspan="4" nolabel="1" widget="many2many_tags" required="1" attrs="{'readonly': [('has_active_session','=', 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" groups="account.group_cash_rounding"> + <div class="o_setting_left_pane"> + <field name="cash_rounding"/> + </div> + <div class="o_setting_right_pane"> + <label for="cash_rounding"/> + <div class="text-muted"> + Define the smallest coinage of the currency used to pay + </div> + <div class="content-group mt16" attrs="{'invisible': [('cash_rounding', '=', False)]}"> + <div class="row mt16"> + <label string="Rounding Method" for="rounding_method" class="col-lg-3 o_light_label" /> + <field name="rounding_method" attrs="{'required' : [('cash_rounding', '=', True)]}" domain="[('company_id', '=', company_id)]"/> + </div> + <div class="row mt16"> + <label string="Only on cash methods" for="only_round_cash_method" class="col-lg-3 o_light_label" /> + <field name="only_round_cash_method"/> + </div> + </div> + </div> + </div> + <div class="col-12 col-lg-6 o_setting_box"> + <div class="o_setting_left_pane"> + <field name="cash_control" attrs="{'readonly': [('has_active_session','=', True)]}"/> + </div> + <div class="o_setting_right_pane"> + <label for="cash_control"/> + <div class="text-muted"> + Control cash box at opening and closing + </div> + <div attrs="{'invisible': [('cash_control', '=', False)]}"> + <label for="amount_authorized_diff" string="Authorized Difference" class="font-weight-normal"/> + <field name="amount_authorized_diff"/> + </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="iface_tipproduct" attrs="{'readonly': [('has_active_session','=', True)]}"/> + </div> + <div class="o_setting_right_pane"> + <label for="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': [('iface_tipproduct', '=', False)]}"> + <div class="mt16" id="tip_product"> + <label string="Tip Product" for="tip_product_id" class="o_light_label"/> + <field name="tip_product_id"/> + </div> + </div> + </div> + </div> + </div> + <h2>Bills & Receipts</h2> + <div class="row mt16 o_settings_container" id="receipt"> + <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="sequence_id" readonly="1"/> + </div> + </div> + </div> + <div class="col-12 col-lg-6 o_setting_box"> + <div class="o_setting_left_pane"> + <field name="is_header_or_footer"/> + </div> + <div class="o_setting_right_pane"> + <label for="is_header_or_footer"/> + <div class="text-muted"> + Add a custom message to header and footer + </div> + <div class="content-group mt16" attrs="{'invisible' : [('is_header_or_footer', '=', False)]}"> + <div> + <label string="Header" for="receipt_header" class="col-lg-2 o_light_label"/> + <field name="receipt_header" placeholder="e.g. Company Address, Website"/> + </div> + <div> + <label string="Footer" for="receipt_footer" class="col-lg-2 o_light_label"/> + <field name="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="iface_print_auto"/> + </div> + <div class="o_setting_right_pane"> + <label for="iface_print_auto"/> + <div class="text-muted"> + Print receipts automatically once the payment is registered + </div> + <div class="content-group mt16" attrs="{'invisible' : ['|', ('iface_print_auto', '=', False), '&', ('is_posbox', '=', False), ('other_devices', '=', False)]}"> + <div> + <field name="iface_print_skip_screen" class="oe_inline"/><span class="oe_inline"><b>Skip Preview Screen</b></span> + </div> + </div> + </div> + </div> + <div class="col-12 col-lg-6 o_setting_box" id="iface_invoicing"> + <div class="o_setting_left_pane"> + <field name="module_account"/> + </div> + <div class="o_setting_right_pane"> + <label for="module_account"/> + <div class="text-muted" id="invoice_journal"> + Print invoices on customer request + </div> + <div class="content-group mt16" attrs="{'invisible': [('module_account', '=', False)]}"> + <div class="row mt16"> + <label string="Invoice Journal" for="invoice_journal_id" class="col-lg-3 o_light_label"/> + <field name="invoice_journal_id" + domain="[('company_id', '=', company_id), ('type', '=', 'sale')]" + attrs="{'required': [('module_account', '=', True)]}" + context="{'default_company_id': company_id, 'default_type': 'sale'}"/> + </div> + </div> + </div> + </div> + </div> + <h2>Inventory</h2> + <div class="row mt16 o_settings_container" id="inventory_location"> + <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="picking_type_id" string="Operation Type"/> + <div class="text-muted"> + Operation type used to record product pickings <br/> + Products will be taken from the default source location of this operation type + </div> + <div class="content-group mt16"> + <field name="picking_type_id" required="1" domain="[('company_id', '=', company_id)]"/> + </div> + </div> + </div> + </div> + <h2>Accounting</h2> + <div class="row mt16 o_settings_container" id="accounting_section"> + <div class="col-12 col-lg-6 o_setting_box"> + <div class="o_setting_right_pane"> + <span class="o_form_label">Journal Entries</span> + <div class="text-muted"> + Configuration for journal entries of PoS orders + </div> + <div class="content-group"> + <div class="row mt16" 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="Sales Journal" for="journal_id" class="col-lg-3 o_light_label" widget="selection"/> + <field name="journal_id" required="1" domain="[('company_id', '=', company_id), ('type', '=', 'sale')]" context="{'default_company_id': company_id, 'default_type': 'sale'}"/> + </div> + </div> + </div> + </div> + </div> + </sheet> + + </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_pos" 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">tree,form</field> + <field name="search_view_id" ref="view_pos_config_search" /> + </record> + + <menuitem + id="menu_pos_config_pos" + name="Point of Sale" + parent="menu_point_config_product" + sequence="1" + action="action_pos_config_pos" + groups="group_pos_manager"/> + + <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> diff --git a/addons/point_of_sale/views/pos_order_report_view.xml b/addons/point_of_sale/views/pos_order_report_view.xml new file mode 100644 index 00000000..6e708811 --- /dev/null +++ b/addons/point_of_sale/views/pos_order_report_view.xml @@ -0,0 +1,87 @@ +<?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" disable_linking="True" 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" disable_linking="1"> + <field name="product_categ_id" type="row"/> + <field name="price_total" type="measure"/> + </graph> + </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','=',('paid'))]"/> + <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> diff --git a/addons/point_of_sale/views/pos_order_view.xml b/addons/point_of_sale/views/pos_order_view.xml new file mode 100644 index 00000000..ce080eda --- /dev/null +++ b/addons/point_of_sale/views/pos_order_view.xml @@ -0,0 +1,386 @@ +<?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': ['|', ('invoice_group', '=', False), ('state','!=','paid')]}"/> + <button name="refund" string="Return Products" type="object" + attrs="{'invisible':[('state','=','draft')]}"/> + <field name="state" widget="statusbar" statusbar_visible="draft,paid,done" /> + </header> + <sheet> + <field name="failed_pickings" 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> + </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}"/> + <field name="invoice_group" invisible="1"/> + </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="product_uom_id" string="UoM" groups="uom.group_uom"/> + <field name="price_unit" widget="monetary"/> + <field name="discount" string="Disc.%" widget="monetary"/> + <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"/> + </tree> + <form string="Order lines"> + <group col="4"> + <field name="full_product_name"/> + <field name="qty"/> + <field name="discount" widget="monetary"/> + <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"> + <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')]}"/> + <field name="currency_id" invisible="1"/> + </group> + <div class="oe_clear"/> + </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-right text-right"> + <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="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"> + <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" widget="monetary"/> + <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" widget="monetary"/> + <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', '>=', time.strftime('%Y-%m-%d 00:00:00')),('create_date', '<=', 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> diff --git a/addons/point_of_sale/views/pos_payment_method_views.xml b/addons/point_of_sale/views/pos_payment_method_views.xml new file mode 100644 index 00000000..cf30115d --- /dev/null +++ b/addons/point_of_sale/views/pos_payment_method_views.xml @@ -0,0 +1,93 @@ +<?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"/> + <div class="oe_title"> + <label for="name" class="oe_edit_only"/> + <h1><field name="name" class="oe_inline"/></h1> + </div> + <group name="Payment methods"> + <group> + <field name="hide_use_payment_terminal" invisible="1"/> + <field name="receivable_account_id" groups="account.group_account_readonly" /> + <field name="is_cash_count" /> + <field name="cash_journal_id" attrs="{'invisible': [('is_cash_count', '=', False)], 'required': [('is_cash_count', '=', True)]}" /> + <field name="split_transactions" groups="base.group_no_one" /> + <field name="company_id" readonly="1" groups="base.group_multi_company" /> + </group> + <group> + <field name="use_payment_terminal" attrs="{'invisible': [('hide_use_payment_terminal', '=', True)]}" /> + </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"> + <field name="hide_use_payment_terminal" invisible="1"/> + <field name="name" /> + <field name="receivable_account_id" groups="account.group_account_readonly"/> + <field name="is_cash_count" /> + <field name="split_transactions" groups="base.group_no_one" /> + <field name="use_payment_terminal" attrs="{'invisible': [('hide_use_payment_terminal', '=', 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> diff --git a/addons/point_of_sale/views/pos_payment_views.xml b/addons/point_of_sale/views/pos_payment_views.xml new file mode 100644 index 00000000..af855fb1 --- /dev/null +++ b/addons/point_of_sale/views/pos_payment_views.xml @@ -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" delete="0"> + <sheet> + <group> + <field name="currency_id" invisible="1" /> + <field name="name" /> + <field name="amount" /> + <field name="pos_order_id" /> + <field name="payment_method_id" /> + <field name="card_type" attrs="{'invisible': [('card_type', '=', False)]}"/> + <field name="cardholder_name" attrs="{'invisible': [('cardholder_name', '=', False)]}"/> + <field name="transaction_id" 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,kanban,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> diff --git a/addons/point_of_sale/views/pos_session_view.xml b/addons/point_of_sale/views/pos_session_view.xml new file mode 100644 index 00000000..3381b407 --- /dev/null +++ b/addons/point_of_sale/views/pos_session_view.xml @@ -0,0 +1,252 @@ +<?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"> + <header> + <button name="open_cashbox_pos" type="object" string="Open Session" + attrs="{'invisible' : ['|', ('cash_control', '=', False), ('state', '!=', 'new_session')]}" class="oe_highlight" + context="{'balance': 'start'}"/> + <button name="open_frontend_cb" type="object" string="Continue Selling" + attrs="{'invisible' : ['|', ('rescue', '=', True), ('state', 'not in', ['opening_control', 'opened'])]}"/> + <button id="end_session_opened" name="action_pos_session_closing_control" type="object" string="End of Session" + attrs="{'invisible' : ['|', ('cash_control', '=', False),('state', '!=', 'opened')]}" + class="oe_highlight"/> + <button id="validate_opened" name="action_pos_session_closing_control" type="object" string="Close Session & Post Entries" + attrs="{'invisible' : ['|', ('cash_control', '=', True),('state', '!=', 'opened')]}" + class="oe_highlight"/> + <button id="validate_closing_control" name="action_pos_session_validate" type="object" string="Close Session & Post Entries" states="closing_control" + class="oe_highlight"/> + + <field name="state" widget="statusbar" statusbar_visible="opened,closing_control,closed" nolabel="1" /> + </header> + <sheet> + <field name="cash_register_id" invisible="1"/> + <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" + attrs="{'invisible':[('move_id', '=', False)]}" + groups="account.group_account_readonly" + > + </button> + </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"/> + <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')]}"/> + </group> + <notebook> + <page string="Cash Control" name="cash_control" attrs="{'invisible' : [('cash_control', '=', False)]}"> + <group class="col-md-12" style="margin-left: 140px;"> + <group class="col-md-7"> + <div style="margin:0;padding:0;"> + <group style="margin:0;padding:0;" attrs="{'invisible' : [('state', 'in', ['opening_control', 'closed'])]}"> + <field style="text-align:right;margin:0;padding:0;" name="cash_register_total_entry_encoding" widget="monetary" options="{'currency_field': 'currency_id'}" string="+ Transactions"/> + </group> + <group style="margin:0;padding:0;" attrs="{'invisible' : [('state', '!=', 'closed')]}"> + <field style="text-align:right;margin:0;padding:0;" name="cash_real_transaction" widget="monetary" options="{'currency_field': 'currency_id'}" string="+ Transactions"/> + </group> + <group style="margin:0;padding:0;" attrs="{'invisible' : [('state', 'in', ['opening_control', 'closed'])]}"> + <field style="text-align:right;margin:0;padding:0;" name="cash_register_balance_end" widget="monetary" options="{'currency_field': 'currency_id'}" string="= Expected in Cash"/> + </group> + <group style="margin:0;padding:0;" attrs="{'invisible' : [('state', '!=', 'closed')]}"> + <field style="text-align:right;margin:0;padding:0;" name="cash_real_expected" widget="monetary" options="{'currency_field': 'currency_id'}" string="= Expected"/> + </group> + <group style="margin:0;padding:0;" attrs="{'invisible' : [('state', 'in', ['opening_control'])]}"> + <field style="text-align:right;margin:0;padding:0;" name="cash_register_balance_end_real" widget="monetary" options="{'currency_field': 'currency_id'}" string="Actual in Cash"/> + </group> + </div> + <div style="margin:0;padding:0;"> + <group style="margin:0;padding:0;" attrs="{'invisible' : [('state', 'in', ['opening_control'])]}"> + <button class="oe_inline oe_link" name="%(action_pos_box_out)d" type="action" attrs="{'invisible' : [('state', '=', 'closed')]}">Cash In/Out</button> + </group> + <group style="margin:0;padding:0;" attrs="{'invisible' : [('state', '=', 'opening_control')]}"> + </group> + <group style="margin:0;padding:0;" attrs="{'invisible' : [('state', '=', 'opening_control')]}"> + <button class="oe_inline oe_link" name="open_cashbox_pos" type="object" attrs="{'invisible': [('state', '!=', 'closing_control')]}" context="{'balance': 'close'}">Set Closing Cash</button> + </group> + </div> + </group> + </group> + + <div class="col-md-4" attrs="{'invisible' : [('state', '!=', 'closing_control')]}" style="height: 30px"> + <group class="oe_subtotal_footer"> + <field name="cash_register_difference" widget="monetary" options="{'currency_field': 'currency_id'}" decoration-danger="cash_register_difference != 0"/> + </group> + </div> + <div class="col-md-4" attrs="{'invisible' : [('state', '!=', 'closed')]}" style="height: 30px"> + <group class="oe_subtotal_footer"> + <field name="cash_real_difference" widget="monetary" options="{'currency_field': 'currency_id'}" decoration-danger="cash_real_difference != 0"/> + </group> + </div> + </page> + </notebook> + </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_id" ref="model_pos_session"/> + <field name="icon">fa-tasks</field> + <field name="delay_count">0</field> + </record> + + + <record model="ir.ui.view" id="closing_balance_confirm"> + <field name="name">Confirming balance closing</field> + <field name="model">closing.balance.confirm.wizard</field> + <field name="type">form</field> + <field name="arch" type="xml"> + <form> + <group> + <span>There is a difference between the expected and actual closing in cash. Are you sure you want to close the session and post the accounting entries?</span> + </group> + <footer> + <button name="confirm_closing_balance" string="Confirm" type="object" class="oe_highlight, btn-primary" /> + <button string="Discard" special="cancel" class="oe_highlight, btn-secondary"/> + </footer> + </form> + </field> + </record> + + <menuitem + id="menu_pos_session_all" + parent="menu_point_of_sale" + action="action_pos_session" + sequence="2" + groups="group_pos_manager"/> +</odoo> diff --git a/addons/point_of_sale/views/product_view.xml b/addons/point_of_sale/views/product_view.xml new file mode 100644 index 00000000..39b5bbda --- /dev/null +++ b/addons/point_of_sale/views/product_view.xml @@ -0,0 +1,111 @@ +<?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> + </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}"/> + </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_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']" position="after"> + <page name="pos" string="Point of Sale" attrs="{'invisible': [('sale_ok','=',False)]}"> + <group name="pos"> + <group> + <field name="available_in_pos"/> + <field name="pos_categ_id" attrs="{'invisible': [('available_in_pos', '=', False)]}" string="Category"/> + <field name="to_weight" attrs="{'invisible': [('available_in_pos', '=', False)]}"/> + </group> + </group> + </page> + </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> + +</odoo> diff --git a/addons/point_of_sale/views/report_saledetails.xml b/addons/point_of_sale/views/report_saledetails.xml new file mode 100644 index 00000000..5ca914f5 --- /dev/null +++ b/addons/point_of_sale/views/report_saledetails.xml @@ -0,0 +1,88 @@ +<?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> + + <strong><t t-esc="date_start" t-options="{'widget': 'datetime'}"/> - <t t-esc="date_stop" t-options="{'widget': 'datetime'}"/></strong> + </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> diff --git a/addons/point_of_sale/views/report_userlabel.xml b/addons/point_of_sale/views/report_userlabel.xml new file mode 100644 index 00000000..33281bb4 --- /dev/null +++ b/addons/point_of_sale/views/report_userlabel.xml @@ -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><img t-if="user.barcode" t-att-src="'/report/barcode/?type=%s&value=%s&width=%s&height=%s' % ('EAN13', user.barcode, 300, 50)" style="width:100%;height:35%;" alt="Barcode"/></td> + <td><strong t-field="user.name"/></td> + </tr> + </tbody> + </table> + </div> + </t> + </div> + </t> +</template> +</odoo> diff --git a/addons/point_of_sale/views/res_config_settings_views.xml b/addons/point_of_sale/views/res_config_settings_views.xml new file mode 100644 index 00000000..1a9e129c --- /dev/null +++ b/addons/point_of_sale/views/res_config_settings_views.xml @@ -0,0 +1,175 @@ +<?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"> + <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"> + <h2>Taxes</h2> + <div class="row mt16 o_settings_container" name="taxes_setting_container"> + <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"/> + <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> + <h2>Pricing</h2> + <div class="row mt16 o_settings_container" name="pricing_setting_container"> + <div class="col-12 col-lg-6 o_setting_box" id="multiple_prices_setting"> + <div class="o_setting_left_pane"> + <field name="group_product_pricelist"/> + </div> + <div class="o_setting_right_pane"> + <label for="group_product_pricelist"/> + <div class="text-muted"> + Set multiple prices per product, automated discounts, etc. + </div> + <div class="content-group" attrs="{'invisible': [('group_product_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="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" id="multicurrencies_setting" title="This adds the choice of a currency on pricelists."> + <div class="o_setting_left_pane"> + <field name="group_multi_currency"/> + </div> + <div class="o_setting_right_pane"> + <label for="group_multi_currency"/> + <div class="text-muted"> + Record transactions in foreign currencies + </div> + <div class="content-group" attrs="{'invisible': [('group_multi_currency', '=', False)]}"> + <div class="mt8"> + <button type="action" name="%(base.action_currency_form)d" string="Currencies" class="btn-link" icon="fa-arrow-right"/> + </div> + </div> + </div> + </div> + </div> + <h2>Payments</h2> + <div class="row mt16 o_settings_container"> + <div class="col-12 col-lg-6 o_setting_box"> + <div class="o_setting_left_pane"> + <field name="group_cash_rounding"/> + </div> + <div class="o_setting_right_pane"> + <label for="group_cash_rounding"/> + <a href="https://www.odoo.com/documentation/14.0/applications/sales/point_of_sale/shop/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="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> + <h2>Payment Terminals</h2> + <div class="row mt16 o_settings_container" id="o_settings_use_payment_terminals"> + <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="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 & Canada)"/> + <a href="https://www.odoo.com/documentation/14.0/applications/sales/point_of_sale/payment/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/14.0/applications/sales/point_of_sale/payment/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>Inventory</h2> + <div class="row mt16 o_settings_container" name="product_setting_container"> + <div class="col-12 col-lg-6 o_setting_box" id="update_quantities_stock_setting"> + <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> + </div> + </xpath> + </field> + </record> + + <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> diff --git a/addons/point_of_sale/views/res_partner_view.xml b/addons/point_of_sale/views/res_partner_view.xml new file mode 100644 index 00000000..2a35f808 --- /dev/null +++ b/addons/point_of_sale/views/res_partner_view.xml @@ -0,0 +1,40 @@ +<?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="groups_id" eval="[(4, ref('group_pos_user'))]"/> + <field name="arch" type="xml"> + <div name="button_box" position="inside"> + <button class="oe_stat_button" type="action" name="%(point_of_sale.action_pos_pos_form)d" + context="{'search_default_partner_id': active_id,'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"> + <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="groups_id" eval="[(4, ref('group_pos_user'))]"/> + <field name="arch" type="xml"> + <field name="state_id" position="before"> + <field name="pos_order_count"/> + </field> + <xpath expr="//span[hasclass('oe_kanban_partner_links')]" position="inside"> + <span t-if="record.pos_order_count.value>0" class="badge badge-pill"><i class="fa fa-fw fa-shopping-bag" role="img" aria-label="Shopping cart" title="Shopping cart"/><t t-esc="record.pos_order_count.value"/></span> + </xpath> + </field> + </record> +</odoo> |
