Initial commit: Pos packages

This commit is contained in:
Ernad Husremovic 2025-08-29 15:20:50 +02:00
commit 95dfb9edb0
1301 changed files with 264148 additions and 0 deletions

View file

@ -0,0 +1,31 @@
odoo.define('pos_hr.CashierName', function (require) {
'use strict';
const CashierName = require('point_of_sale.CashierName');
const Registries = require('point_of_sale.Registries');
const SelectCashierMixin = require('pos_hr.SelectCashierMixin');
const { useBarcodeReader } = require('point_of_sale.custom_hooks');
const PosHrCashierName = (CashierName) =>
class extends SelectCashierMixin(CashierName) {
setup() {
super.setup();
useBarcodeReader({ cashier: this.barcodeCashierAction });
}
//@Override
get avatar() {
if (this.env.pos.config.module_pos_hr) {
const cashier = this.env.pos.get_cashier();
if (!(cashier && cashier.id)) {
return '';
}
return `/web/image/hr.employee.public/${cashier.id}/avatar_128`;
}
return super.avatar;
}
};
Registries.Component.extend(CashierName, PosHrCashierName);
return CashierName;
});

View file

@ -0,0 +1,30 @@
odoo.define('pos_hr.chrome', function (require) {
'use strict';
const Chrome = require('point_of_sale.Chrome');
const Registries = require('point_of_sale.Registries');
const PosHrChrome = (Chrome) =>
class extends Chrome {
async start() {
await super.start();
if (this.env.pos.config.module_pos_hr) this.showTempScreen('LoginScreen');
}
get headerButtonIsShown() {
return !this.env.pos.config.module_pos_hr || this.env.pos.get_cashier().role == 'manager' || this.env.pos.get_cashier_user_id() === this.env.pos.user.id;
}
showCashMoveButton() {
return super.showCashMoveButton() && (!this.env.pos.cashier || this.env.pos.cashier.role == 'manager');
}
shouldShowCashControl() {
if (this.env.pos.config.module_pos_hr){
return super.shouldShowCashControl() && this.env.pos.hasLoggedIn;
}
return super.shouldShowCashControl();
}
};
Registries.Component.extend(Chrome, PosHrChrome);
return Chrome;
});

View file

@ -0,0 +1,28 @@
odoo.define('point_of_sale.HeaderLockButton', function(require) {
'use strict';
const PosComponent = require('point_of_sale.PosComponent');
const Registries = require('point_of_sale.Registries');
const { useState } = owl;
class HeaderLockButton extends PosComponent {
setup() {
super.setup();
this.state = useState({ isUnlockIcon: true, title: 'Unlocked' });
}
async showLoginScreen() {
this.env.pos.reset_cashier();
await this.showTempScreen('LoginScreen');
}
onMouseOver(isMouseOver) {
this.state.isUnlockIcon = !isMouseOver;
this.state.title = isMouseOver ? 'Lock' : 'Unlocked';
}
}
HeaderLockButton.template = "HeaderLockButton";
Registries.Component.add(HeaderLockButton);
return HeaderLockButton;
});

View file

@ -0,0 +1,43 @@
odoo.define('pos_hr.LoginScreen', function (require) {
'use strict';
const PosComponent = require('point_of_sale.PosComponent');
const Registries = require('point_of_sale.Registries');
const SelectCashierMixin = require('pos_hr.SelectCashierMixin');
const { useBarcodeReader } = require('point_of_sale.custom_hooks');
class LoginScreen extends SelectCashierMixin(PosComponent) {
setup() {
super.setup();
useBarcodeReader({cashier: this.barcodeCashierAction}, true);
}
async selectCashier() {
if (await super.selectCashier()) {
this.back();
}
}
async barcodeCashierAction(code) {
if (await super.barcodeCashierAction(code) && this.env.pos.get_cashier().id) {
this.back();
}
}
back() {
this.props.resolve({ confirmed: false, payload: false });
this.trigger('close-temp-screen');
this.env.pos.hasLoggedIn = true;
this.env.posbus.trigger('start-cash-control');
}
confirm() {
this.props.resolve({ confirmed: true, payload: true });
this.trigger('close-temp-screen');
}
get shopName() {
return this.env.pos.config.name;
}
}
LoginScreen.template = 'LoginScreen';
Registries.Component.add(LoginScreen);
return LoginScreen;
});

View file

@ -0,0 +1,18 @@
odoo.define('pos_hr.PaymentScreen', function (require) {
'use strict';
const PaymentScreen = require('point_of_sale.PaymentScreen');
const Registries = require('point_of_sale.Registries');
const PosHrPaymentScreen = (PaymentScreen_) =>
class extends PaymentScreen_ {
async _finalizeValidation() {
this.currentOrder.cashier = this.env.pos.get_cashier();
await super._finalizeValidation();
}
};
Registries.Component.extend(PaymentScreen, PosHrPaymentScreen);
return PaymentScreen;
});

View file

@ -0,0 +1,71 @@
/* global Sha1 */
odoo.define('pos_hr.SelectCashierMixin', function (require) {
'use strict';
const SelectCashierMixin = (PosComponent) => class ComponentWithSelectCashierMixin extends PosComponent {
async askPin(employee) {
const { confirmed, payload: inputPin } = await this.showPopup('NumberPopup', {
isPassword: true,
title: this.env._t('Password ?'),
startingValue: null,
});
if (!confirmed) return;
if (employee.pin === Sha1.hash(inputPin)) {
return employee;
} else {
await this.showPopup('ErrorPopup', {
title: this.env._t('Incorrect Password'),
});
return;
}
}
/**
* Select a cashier, the returning value will either be an object or nothing (undefined)
*/
async selectCashier() {
if (this.env.pos.config.module_pos_hr) {
const employeesList = this.env.pos.employees
.filter((employee) => employee.id !== this.env.pos.get_cashier().id)
.map((employee) => {
return {
id: employee.id,
item: employee,
label: employee.name,
isSelected: false,
};
});
let {confirmed, payload: employee} = await this.showPopup('SelectionPopup', {
title: this.env._t('Change Cashier'),
list: employeesList,
});
if (!confirmed) {
return;
}
if (employee && employee.pin) {
employee = await this.askPin(employee);
}
if (employee) {
this.env.pos.set_cashier(employee);
}
return employee;
}
}
async barcodeCashierAction(code) {
const employee = this.env.pos.employees.find(
(emp) => emp.barcode === Sha1.hash(code.code)
);
if (employee && employee !== this.env.pos.get_cashier() && (!employee.pin || (await this.askPin(employee)))) {
this.env.pos.set_cashier(employee);
}
return employee;
}
}
return SelectCashierMixin;
});

View file

@ -0,0 +1,82 @@
odoo.define('pos_hr.employees', function (require) {
"use strict";
var { PosGlobalState, Order } = require('point_of_sale.models');
const Registries = require('point_of_sale.Registries');
const PosHrPosGlobalState = (PosGlobalState) => class PosHrPosGlobalState extends PosGlobalState {
async _processData(loadedData) {
await super._processData(...arguments);
if (this.config.module_pos_hr) {
this.employees = loadedData['hr.employee'];
this.employee_by_id = loadedData['employee_by_id'];
this.reset_cashier();
}
}
async after_load_server_data() {
await super.after_load_server_data(...arguments);
if (this.config.module_pos_hr) {
this.hasLoggedIn = !this.config.module_pos_hr;
}
}
reset_cashier() {
this.cashier = {name: null, id: null, barcode: null, user_id: null, pin: null, role: null};
}
set_cashier(employee) {
this.cashier = employee;
const selectedOrder = this.get_order();
if (selectedOrder && !selectedOrder.get_orderlines().length) {
// Order without lines can be considered to be un-owned by any employee.
// We set the cashier on that order to the currently set employee.
selectedOrder.cashier = employee;
}
if (!this.cashierHasPriceControlRights() && this.numpadMode === 'price') {
this.numpadMode = 'quantity';
}
}
/**{name: null, id: null, barcode: null, user_id:null, pin:null}
* If pos_hr is activated, return {name: string, id: int, barcode: string, pin: string, user_id: int}
* @returns {null|*}
*/
get_cashier() {
if (this.config.module_pos_hr) {
return this.cashier;
}
return super.get_cashier();
}
get_cashier_user_id() {
if (this.config.module_pos_hr) {
return this.cashier.user_id ? this.cashier.user_id : null;
}
return super.get_cashier_user_id();
}
}
Registries.Model.extend(PosGlobalState, PosHrPosGlobalState);
const PosHrOrder = (Order) => class PosHrOrder extends Order {
constructor(obj, options) {
super(...arguments);
if (!options.json && this.pos.config.module_pos_hr) {
this.cashier = this.pos.get_cashier();
}
}
init_from_JSON(json) {
super.init_from_JSON(...arguments);
if (this.pos.config.module_pos_hr && json.employee_id) {
this.cashier = this.pos.employee_by_id[json.employee_id];
}
}
export_as_JSON() {
const json = super.export_as_JSON(...arguments);
if (this.pos.config.module_pos_hr) {
json.employee_id = this.cashier ? this.cashier.id : false;
}
return json;
}
}
Registries.Model.extend(Order, PosHrOrder);
});