Skip to content

Commit a03981a

Browse files
committed
[ADD] point_of_sale: added salesperson field
Introduced the functionality to assign a salesperson to a Point of Sale order. Added new dialog menu, populated with employees from hr.employee, has been added to the main POS interface. A (Many2one) field was added to the model to store the selected employee. The POS Order form and list views in the backend have been updated to display the salesperson's name. Employee data is now loaded into the POS session to make it available in the UI. task-4968717
1 parent fbf9ee9 commit a03981a

File tree

10 files changed

+188
-0
lines changed

10 files changed

+188
-0
lines changed

pos_salesperson/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import models

pos_salesperson/__manifest__.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
'name': "POS salesperson",
3+
'version': '1.0',
4+
'license': 'LGPL-3',
5+
'depends': ['pos_hr'],
6+
'author': "Kalpan Desai",
7+
'category': 'Sales/Point of Sale',
8+
'description': """
9+
Salesperson in POS
10+
""",
11+
'installable': True,
12+
'application': True,
13+
'data': [
14+
'views/pos_view.xml',
15+
],
16+
'assets': {
17+
'point_of_sale._assets_pos': [
18+
'pos_salesperson/static/src/**/*'
19+
]
20+
},
21+
}

pos_salesperson/models/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from . import pos_order
2+
from . import pos_session

pos_salesperson/models/pos_order.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from odoo import fields, models
2+
3+
4+
class PosOrder(models.Model):
5+
_inherit = 'pos.order'
6+
7+
salesperson_id = fields.Many2one(
8+
'hr.employee',
9+
string='Salesperson',
10+
help='The salesperson responsible for this order.'
11+
)

pos_salesperson/models/pos_session.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from odoo import api, models
2+
3+
4+
class PosSession(models.Model):
5+
"""Inherit the pos.session to load the data of hr.employee model"""
6+
_inherit = 'pos.session'
7+
8+
@api.model
9+
def _load_pos_data_models(self, config_id):
10+
data = super()._load_pos_data_models(config_id)
11+
data += ['hr.employee']
12+
return data
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { SalespersonList } from '../salesperson_list/salesperson_list';
2+
import { ControlButtons } from '@point_of_sale/app/screens/product_screen/control_buttons/control_buttons';
3+
import { makeAwaitable } from "@point_of_sale/app/store/make_awaitable_dialog";
4+
import { patch } from '@web/core/utils/patch';
5+
import { useState } from '@odoo/owl';
6+
7+
patch(ControlButtons.prototype, {
8+
setup(){
9+
super.setup();
10+
this.state = useState({
11+
salesperson_id: null,
12+
});
13+
},
14+
async selectSalesperson() {
15+
const currentOrder = this.pos.get_order();
16+
if (!currentOrder) {
17+
return;
18+
}
19+
20+
const currentSalesperson = currentOrder.salesperson_id || null;
21+
const payload = await makeAwaitable(this.dialog, SalespersonList, {
22+
salesperson: currentSalesperson,
23+
getPayload: (newSalesperson) => newSalesperson || null,
24+
});
25+
this.state.salesperson_id = payload || null;
26+
currentOrder.salesperson_id = payload || null;
27+
return currentOrder.salesperson_id;
28+
29+
}
30+
})
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<templates id="template" xml:space="preserve">
3+
<t t-name="salesperson_button" t-inherit="point_of_sale.ControlButtons" t-inherit-mode="extension">
4+
<xpath expr="//OrderlineNoteButton" position="after">
5+
<button class="btn btn-light btn-lg lh-lg text-truncate w-auto" t-on-click="selectSalesperson">
6+
<div t-if="state.salesperson_id" t-out="state.salesperson_id.name" class="text-truncate text-action" />
7+
<t t-else="">Salesperson</t>
8+
</button>
9+
</xpath>
10+
</t>
11+
</templates>
12+
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { _t } from "@web/core/l10n/translation";
2+
import { useService } from "@web/core/utils/hooks";
3+
import { Dialog } from "@web/core/dialog/dialog";
4+
import { usePos } from "@point_of_sale/app/store/pos_hook";
5+
import { Component, useState } from "@odoo/owl";
6+
import { useHotkey } from "@web/core/hotkeys/hotkey_hook";
7+
8+
9+
export class SalespersonList extends Component {
10+
static template = "POS_Salesperson.SalespersonList";
11+
static components = { Dialog };
12+
static props = {
13+
salesperson: {
14+
optional: true,
15+
type: [{ value: null }, Object],
16+
},
17+
getPayload : { type: Function },
18+
close : { type: Function }
19+
}
20+
21+
setup() {
22+
this.pos = usePos();
23+
this.ui = useState(useService("ui"));
24+
this.dialog = useService("dialog");
25+
26+
this.state = useState({
27+
query: null,
28+
previousQuery: "",
29+
currentOffset: 0,
30+
});
31+
useHotkey("enter", () => this.onEnter());
32+
}
33+
getSalesPerson(){
34+
const salesperson = this.pos.models['hr.employee'].getAll();
35+
return salesperson;
36+
}
37+
38+
clickSalesPerson(salesperson) {
39+
this.props.getPayload(salesperson);
40+
this.props.close();
41+
}
42+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<templates id="template" xml:space="preserve">
3+
<t t-name="POS_Salesperson.SalespersonList">
4+
<Dialog bodyClass="'overflow-y-auto'" contentClass="'h-100'">
5+
<table class="table table-hover">
6+
<thead>
7+
<tr>
8+
<th>Name</th>
9+
</tr>
10+
</thead>
11+
<tbody>
12+
<t t-foreach="getSalesPerson()" t-as="salesperson" t-key="salesperson.id">
13+
<tr
14+
t-att-class="salesperson.id == props.salesperson?.id ? 'active' : ''"
15+
t-on-click="() => this.clickSalesPerson(salesperson)">
16+
<td t-out="salesperson.name"/>
17+
</tr>
18+
</t>
19+
</tbody>
20+
</table>
21+
22+
<t t-set-slot="footer">
23+
<div class="d-flex justify-content-start flex-wrap gap-2 w-100">
24+
<button
25+
class="btn btn-secondary btn-lg lh-lg o-default-button"
26+
t-on-click="() => this.clickSalesPerson(salesperson)">
27+
Discard
28+
</button>
29+
</div>
30+
</t>
31+
</Dialog>
32+
</t>
33+
</templates>

pos_salesperson/views/pos_view.xml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<odoo>
3+
<record id="view_pos_pos_form_inherit" model="ir.ui.view">
4+
<field name="name">pos.order.form.inherit</field>
5+
<field name="model">pos.order</field>
6+
<field name="inherit_id" ref="point_of_sale.view_pos_pos_form" />
7+
<field name="arch" type="xml">
8+
<xpath expr="//field[@name='fiscal_position_id']" position="after">
9+
<field name="salesperson_id" />
10+
</xpath>
11+
</field>
12+
</record>
13+
14+
<record id="view_pos_list_inherit" model="ir.ui.view">
15+
<field name="name">pos.order.list.inherit</field>
16+
<field name="model">pos.order</field>
17+
<field name="inherit_id" ref="point_of_sale.view_pos_order_tree" />
18+
<field name="arch" type="xml">
19+
<xpath expr="//field[@name='partner_id']" position="after">
20+
<field name="salesperson_id" />
21+
</xpath>
22+
</field>
23+
</record>
24+
</odoo>

0 commit comments

Comments
 (0)