feat: Display a customer's top 3 purchased products in the POS partner editor.
This commit is contained in:
parent
84ae87fdcf
commit
ebab33f7a9
Binary file not shown.
@ -25,3 +25,22 @@ class ResPartner(models.Model):
|
|||||||
'price_subtotal_incl': line.price_subtotal_incl,
|
'price_subtotal_incl': line.price_subtotal_incl,
|
||||||
} for line in order.lines],
|
} for line in order.lines],
|
||||||
} for order in orders]
|
} for order in orders]
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def get_pos_top_products(self, partner_id):
|
||||||
|
# SQL query to get top 3 products by quantity for a specific partner
|
||||||
|
query = """
|
||||||
|
SELECT
|
||||||
|
pt.name ->> 'en_US' as product_name,
|
||||||
|
SUM(pol.qty) as total_qty
|
||||||
|
FROM pos_order_line pol
|
||||||
|
JOIN pos_order po ON pol.order_id = po.id
|
||||||
|
JOIN product_product pp ON pol.product_id = pp.id
|
||||||
|
JOIN product_template pt ON pp.product_tmpl_id = pt.id
|
||||||
|
WHERE po.partner_id = %s
|
||||||
|
GROUP BY pt.name
|
||||||
|
ORDER BY total_qty DESC
|
||||||
|
LIMIT 3
|
||||||
|
"""
|
||||||
|
self.env.cr.execute(query, (partner_id,))
|
||||||
|
return self.env.cr.dictfetchall()
|
||||||
|
|||||||
@ -9,21 +9,25 @@ patch(PartnerDetailsEdit.prototype, {
|
|||||||
setup() {
|
setup() {
|
||||||
super.setup();
|
super.setup();
|
||||||
this.orm = useService("orm");
|
this.orm = useService("orm");
|
||||||
this.state = useState({ ...this.state, lastOrders: [] });
|
this.state = useState({ ...this.state, lastOrders: [], topProducts: [] });
|
||||||
|
|
||||||
onWillStart(async () => {
|
onWillStart(async () => {
|
||||||
await this.fetchLastOrders();
|
await this.fetchData();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
async fetchLastOrders() {
|
async fetchData() {
|
||||||
const partnerId = this.props.partner.id;
|
const partnerId = this.props.partner.id;
|
||||||
if (partnerId) {
|
if (partnerId) {
|
||||||
try {
|
try {
|
||||||
const orders = await this.orm.call("res.partner", "get_pos_last_orders", [partnerId]);
|
const [orders, topProducts] = await Promise.all([
|
||||||
|
this.orm.call("res.partner", "get_pos_last_orders", [partnerId]),
|
||||||
|
this.orm.call("res.partner", "get_pos_top_products", [partnerId])
|
||||||
|
]);
|
||||||
this.state.lastOrders = orders;
|
this.state.lastOrders = orders;
|
||||||
|
this.state.topProducts = topProducts;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching orders:", error);
|
console.error("Error fetching data:", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,24 @@
|
|||||||
<xpath expr="//section" position="after">
|
<xpath expr="//section" position="after">
|
||||||
<section class="partner-details-orders d-flex flex-column m-3">
|
<section class="partner-details-orders d-flex flex-column m-3">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
<h3 class="mb-3">Top 3 Products</h3>
|
||||||
|
<t t-if="state.topProducts and state.topProducts.length > 0">
|
||||||
|
<div class="list-group mb-4">
|
||||||
|
<t t-foreach="state.topProducts" t-as="product" t-key="product.product_name">
|
||||||
|
<div class="list-group-item d-flex justify-content-between align-items-center">
|
||||||
|
<span class="fw-bold" t-esc="product.product_name"/>
|
||||||
|
<span class="text-muted">
|
||||||
|
<i class="fa fa-shopping-cart me-1"/>
|
||||||
|
<strong class="text-dark" style="font-size: 1.1em;"><t t-esc="product.total_qty"/></strong> Units
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
<t t-else="">
|
||||||
|
<div class="alert alert-info mb-4">No top products found.</div>
|
||||||
|
</t>
|
||||||
|
|
||||||
<h3 class="mb-3">Last Orders</h3>
|
<h3 class="mb-3">Last Orders</h3>
|
||||||
<t t-if="state.lastOrders and state.lastOrders.length > 0">
|
<t t-if="state.lastOrders and state.lastOrders.length > 0">
|
||||||
<div class="list-group">
|
<div class="list-group">
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user