[IMP] point_of_sale: load default demo data

When loading the pos without demo data, before we had a wizard that allowed the user to load data before the pos starts.
Now, we let the user go to the frontend without preloading products and categories in the database.
In the front end, when no products and categories are loaded, we let the user press buttons to load the default products and categories.

The user can also be redirected to the back end to add new products.

closes odoo/odoo#117823

Task-id: 3054477
Related: odoo/upgrade#4523
Signed-off-by: Samuel Degueldre <sad@odoo.com>
This commit is contained in:
rhe-odoo
2023-05-12 19:54:35 +02:00
committed by Samuel Degueldre
parent 8b64f9dd4e
commit 5e55758d66
11 changed files with 59 additions and 56 deletions
-1
View File
@@ -16,7 +16,6 @@
'wizard/pos_details.xml',
'wizard/pos_payment.xml',
'wizard/pos_close_session_wizard.xml',
'wizard/pos_session_check_product_wizard.xml',
'wizard/pos_daily_sales_reports.xml',
'views/pos_assets_index.xml',
'views/pos_assets_qunit.xml',
@@ -8,6 +8,12 @@
<field name="params" eval="{'menu_id': ref('menu_point_root')}"/>
</record>
<record id="action_client_product_menu" model="ir.actions.client">
<field name="name">Load Product Menu</field>
<field name="tag">reload</field>
<field name="params" eval="{'menu_id': ref('point_of_sale.menu_pos_products')}"/>
</record>
<function model="stock.warehouse" name="_create_missing_pos_picking_types"/>
<record id="product_category_pos" model="product.category">
-14
View File
@@ -527,20 +527,6 @@ class PosConfig(models.Model):
self._check_before_creating_new_session()
self._validate_fields(self._fields)
# check if there's any product for this PoS
domain = [('available_in_pos', '=', True)]
if self.limit_categories and self.iface_available_categ_ids:
domain.append(('pos_categ_id', 'in', self.iface_available_categ_ids.ids))
if not self.env['product.product'].search(domain):
return {
'name': _("There is no product linked to your PoS"),
'type': 'ir.actions.act_window',
'view_mode': 'form',
'res_model': 'pos.session.check_product_wizard',
'target': 'new',
'context': {'config_id': self.id}
}
return self._action_to_open_ui()
def open_existing_session_cb(self):
+7 -1
View File
@@ -8,7 +8,7 @@ from markupsafe import Markup, escape
from odoo import api, fields, models, _, Command
from odoo.exceptions import AccessError, UserError, ValidationError
from odoo.tools import float_is_zero, float_compare
from odoo.tools import float_is_zero, float_compare, convert
from odoo.osv.expression import AND, OR
from odoo.service.common import exp_version
@@ -2125,6 +2125,12 @@ class PosSession(models.Model):
return fps
def load_product_frontend(self):
convert.convert_file(self.env, 'point_of_sale', 'data/point_of_sale_onboarding.xml', None, mode='init',
kind='data')
return self.get_onboarding_data()
class ProcurementGroup(models.Model):
_inherit = 'procurement.group'
@@ -52,5 +52,4 @@ access_pos_make_payment,access.pos.make.payment,model_pos_make_payment,point_of_
access_pos_close_session_wizard,access.pos.close.session.wizard,model_pos_close_session_wizard,point_of_sale.group_pos_user,1,1,1,0
access_account_cash_rounding_pos_user,account.cash.rounding pos_user,account.model_account_cash_rounding,group_pos_user,1,0,0,0
access_pos_bill,pos.bill pos_user,model_pos_bill,group_pos_user,1,1,1,1
access_pos_session_check_product_wizard,access.pos.session.check.product.wizard,model_pos_session_check_product_wizard,group_pos_user,1,1,1,0
access_pos_daily_sales_reports_wizard,access.pos.daily.sales.reports.wizard,model_pos_daily_sales_reports_wizard,group_pos_manager,1,1,1,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
52 access_pos_close_session_wizard access.pos.close.session.wizard model_pos_close_session_wizard point_of_sale.group_pos_user 1 1 1 0
53 access_account_cash_rounding_pos_user account.cash.rounding pos_user account.model_account_cash_rounding group_pos_user 1 0 0 0
54 access_pos_bill pos.bill pos_user model_pos_bill group_pos_user 1 1 1 1
access_pos_session_check_product_wizard access.pos.session.check.product.wizard model_pos_session_check_product_wizard group_pos_user 1 1 1 0
55 access_pos_daily_sales_reports_wizard access.pos.daily.sales.reports.wizard model_pos_daily_sales_reports_wizard group_pos_manager 1 1 1 0
@@ -21,12 +21,19 @@ export class ProductsWidget extends Component {
*/
setup() {
super.setup();
this.state = useState({ previousSearchWord: "", currentOffset: 0 });
this.state = useState({
previousSearchWord: "",
currentOffset: 0,
showReloadMessage: false,
});
this.pos = usePos();
this.popup = useService("popup");
this.notification = useService("pos_notification");
this.orm = useService("orm");
}
get hasProducts() {
return Object.keys(this.pos.globalState.db.product_by_id).length > 0;
}
get selectedCategoryId() {
return this.env.pos.selectedCategoryId;
}
@@ -161,4 +168,18 @@ export class ProductsWidget extends Component {
}
}
}
async loadDemoDataProducts() {
const { products, categories } = await this.orm.call(
"pos.session",
"load_product_frontend",
[this.pos.globalState.pos_session.id]
);
this.pos.globalState.db.add_categories(categories);
this.pos.globalState._loadProductProduct(products);
}
createNewProducts() {
window.open("/web#action=point_of_sale.action_client_product_menu", "_blank");
this.state.showReloadMessage = true;
}
}
@@ -3600,6 +3600,23 @@ td {
background: rgba(104,69,95, 0.7);
}
.pos .no-results-message .button-no-demo {
margin: 3px;
width: 180px;
padding: 10px 0;
cursor: pointer;
font-size: large;
}
.info-load-product-message {
background: lightblue;
color: #017e84;
padding: 8px;
width: fit-content;
display: block;
margin : 3px auto 0 auto;
}
@media screen and (max-width: 768px) {
.pos .search-bar-container.sb-product {
max-width: none;
@@ -26,6 +26,13 @@
<p t-else="">
There are no products in this category.
</p>
<div t-if="!hasProducts">
<button class="button-no-demo" t-on-click="loadDemoDataProducts">Generate demo data</button>
<button class="button-no-demo" t-on-click="createNewProducts">Create new products</button>
<div t-if="state.showReloadMessage" class="info-load-product-message">
Please reload this page once products have been created
</div>
</div>
</div>
<div t-if="searchWord" class="search-more-button">
<div class="button" t-on-click="onPressEnterKey">Search more</div>
-1
View File
@@ -4,5 +4,4 @@
from . import pos_details
from . import pos_payment
from . import pos_close_session_wizard
from . import pos_session_check_product_wizard
from . import pos_daily_sales_reports
@@ -1,18 +0,0 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import models
from odoo.tools import convert
class PosSessionCheckProductWizard(models.TransientModel):
_name = 'pos.session.check_product_wizard'
_description = 'Verify if there are any products for the PoS'
def load_demo_products(self):
convert.convert_file(self.env, 'point_of_sale', 'data/point_of_sale_onboarding.xml', None, mode='init', kind='data')
return self.open_ui()
def open_ui(self):
config = self.env['pos.config'].browse(self.env.context.get('config_id'))
return config._action_to_open_ui()
@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_pos_session_check_product_wizard" model="ir.ui.view">
<field name="name">pos.session.check.product.wizard.form</field>
<field name="model">pos.session.check_product_wizard</field>
<field name="arch" type="xml">
<form string="Check products">
<p>
You can add some from the Products menu, or linked any existing by flagging them as "Available in PoS".
Or you can add demo data for testing purpose. Please mind that this is an irreversible action.
</p>
<footer>
<button name="load_demo_products" string="Add demo data" type="object" class="btn-primary" data-hotkey="q"/>
<button name="open_ui" string="Continue without Demo data" type="object" class="btn-secondary" data-hotkey="z" />
</footer>
</form>
</field>
</record>
</odoo>