[IMP] point_of_sale: trigger cash drawer opening when cash transaction
Adding methods to trigger the cash drawer opening as well as a log in the message to state by who and for which action the cash drawer was opened. There is also a log now for when in an action for which the cash drawer was opened is canceled. The action concerned are: Cash control at opening, cash in / out, Cash control at closing. task-3293113 closes odoo/odoo#121110 Signed-off-by: Monnom David (moda) <moda@odoo.com>
This commit is contained in:
@@ -1822,7 +1822,7 @@ class PosSession(models.Model):
|
||||
return {
|
||||
'search_params': {
|
||||
'domain': [('id', '=', self.env.user.id)],
|
||||
'fields': ['name', 'groups_id'],
|
||||
'fields': ['name', 'groups_id', 'partner_id'],
|
||||
},
|
||||
}
|
||||
|
||||
@@ -2127,6 +2127,13 @@ class PosSession(models.Model):
|
||||
|
||||
return fps
|
||||
|
||||
def log_partner_message(self, partner_id, action, message_type):
|
||||
if message_type == 'ACTION_CANCELLED':
|
||||
body = 'Action cancelled ({ACTION})'.format(ACTION=action)
|
||||
elif message_type == 'CASH_DRAWER_ACTION':
|
||||
body = 'Cash drawer opened ({ACTION})'.format(ACTION=action)
|
||||
self.message_post(body=body, author_id=partner_id)
|
||||
|
||||
def load_product_frontend(self):
|
||||
convert.convert_file(self.env, 'point_of_sale', 'data/point_of_sale_onboarding.xml', None, mode='init',
|
||||
kind='data')
|
||||
|
||||
@@ -190,6 +190,14 @@ export class HardwareProxy extends EventBus {
|
||||
log() {
|
||||
return this.message("log", { arguments: [...arguments] });
|
||||
}
|
||||
async openCashbox(action = false) {
|
||||
if (this.pos.config.iface_cashdrawer && this.connectionInfo.status === "connected") {
|
||||
this.printer.openCashbox();
|
||||
if (action) {
|
||||
this.pos.logEmployeeMessage(action, "CASH_DRAWER_ACTION");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const hardwareProxyService = {
|
||||
|
||||
@@ -108,4 +108,13 @@ export class CashMovePopup extends AbstractAwaitablePopup {
|
||||
this.state.errorMessage = "";
|
||||
this.amountInput.el.focus();
|
||||
}
|
||||
async cancel() {
|
||||
super.cancel();
|
||||
if (
|
||||
this.pos.globalState.config.iface_cashdrawer &&
|
||||
this.pos.globalState.hardwareProxy.connectionInfo.status === "connected"
|
||||
) {
|
||||
this.pos.globalState.logEmployeeMessage(_t("Cash in / out"), "ACTION_CANCELLED");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import { TicketScreen } from "@point_of_sale/js/Screens/TicketScreen/TicketScree
|
||||
import { BackButton } from "@point_of_sale/app/navbar/BackButton";
|
||||
import { Component, useState, useExternalListener } from "@odoo/owl";
|
||||
import { ClosePosPopup } from "@point_of_sale/js/Popups/ClosePosPopup";
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
|
||||
export class Navbar extends Component {
|
||||
static template = "point_of_sale.Navbar";
|
||||
@@ -50,9 +51,9 @@ export class Navbar extends Component {
|
||||
}
|
||||
|
||||
onCashMoveButtonClick() {
|
||||
this.hardwareProxy.openCashbox(_t("Cash in / out"));
|
||||
this.popup.add(CashMovePopup);
|
||||
}
|
||||
|
||||
async onTicketButtonClick() {
|
||||
if (this.isTicketScreenShown) {
|
||||
this.pos.closeScreen();
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useAutofocus, useService } from "@web/core/utils/hooks";
|
||||
import { usePos } from "@point_of_sale/app/pos_hook";
|
||||
import { MoneyDetailsPopup } from "./MoneyDetailsPopup";
|
||||
import { useState } from "@odoo/owl";
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
|
||||
export class CashOpeningPopup extends AbstractAwaitablePopup {
|
||||
static template = "CashOpeningPopup";
|
||||
@@ -22,6 +23,7 @@ export class CashOpeningPopup extends AbstractAwaitablePopup {
|
||||
this.popup = useService("popup");
|
||||
this.orm = useService("orm");
|
||||
useAutofocus({ refName: "cash-input" });
|
||||
this.hardwareProxy = useService("hardware_proxy");
|
||||
}
|
||||
//@override
|
||||
async confirm() {
|
||||
@@ -35,9 +37,12 @@ export class CashOpeningPopup extends AbstractAwaitablePopup {
|
||||
super.confirm();
|
||||
}
|
||||
async openDetailsPopup() {
|
||||
const action = _t("Cash control - opening");
|
||||
this.hardwareProxy.openCashbox(action);
|
||||
const { confirmed, payload } = await this.popup.add(MoneyDetailsPopup, {
|
||||
moneyDetails: this.moneyDetails,
|
||||
total: this.manualInputCashCount ? 0 : this.state.openingCash,
|
||||
action: action,
|
||||
});
|
||||
if (confirmed) {
|
||||
const { total, moneyDetails, moneyDetailsNotes } = payload;
|
||||
|
||||
@@ -70,11 +70,14 @@ export class ClosePosPopup extends AbstractAwaitablePopup {
|
||||
}
|
||||
}
|
||||
async openDetailsPopup() {
|
||||
const action = _t("Cash control - closing");
|
||||
this.hardwareProxy.openCashbox(action);
|
||||
const { confirmed, payload } = await this.popup.add(MoneyDetailsPopup, {
|
||||
moneyDetails: this.moneyDetails,
|
||||
total: this.manualInputCashCount
|
||||
? 0
|
||||
: this.state.payments[this.defaultCashDetails.id].counted,
|
||||
action: action,
|
||||
});
|
||||
if (confirmed) {
|
||||
const { total, moneyDetailsNotes, moneyDetails } = payload;
|
||||
|
||||
@@ -17,6 +17,7 @@ export class MoneyDetailsPopup extends AbstractAwaitablePopup {
|
||||
? { ...this.props.moneyDetails }
|
||||
: Object.fromEntries(this.pos.globalState.bills.map((bill) => [bill.value, 0])),
|
||||
total: this.props.total ? this.props.total : 0,
|
||||
action: this.props.action ? this.props.action : null,
|
||||
});
|
||||
}
|
||||
get firstHalfMoneyDetails() {
|
||||
@@ -52,6 +53,16 @@ export class MoneyDetailsPopup extends AbstractAwaitablePopup {
|
||||
total: this.state.total,
|
||||
moneyDetailsNotes,
|
||||
moneyDetails: { ...this.state.moneyDetails },
|
||||
action: this.state.action,
|
||||
};
|
||||
}
|
||||
async cancel() {
|
||||
super.cancel();
|
||||
if (
|
||||
this.pos.globalState.config.iface_cashdrawer &&
|
||||
this.pos.globalState.hardwareProxy.connectionInfo.status === "connected"
|
||||
) {
|
||||
this.pos.globalState.logEmployeeMessage(this.state.action, "ACTION_CANCELLED");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ export class PaymentScreen extends Component {
|
||||
this.currentOrder.set_to_invoice(!this.currentOrder.is_to_invoice());
|
||||
}
|
||||
openCashbox() {
|
||||
this.hardwareProxy.printer.openCashbox();
|
||||
this.hardwareProxy.openCashbox();
|
||||
}
|
||||
async addTip() {
|
||||
// click_tip
|
||||
@@ -227,11 +227,8 @@ export class PaymentScreen extends Component {
|
||||
}
|
||||
async _finalizeValidation() {
|
||||
const { globalState } = this.pos;
|
||||
if (
|
||||
(this.currentOrder.is_paid_with_cash() || this.currentOrder.get_change()) &&
|
||||
globalState.config.iface_cashdrawer
|
||||
) {
|
||||
this.hardwareProxy.printer.openCashbox();
|
||||
if (this.currentOrder.is_paid_with_cash() || this.currentOrder.get_change()) {
|
||||
this.hardwareProxy.openCashbox();
|
||||
}
|
||||
|
||||
this.currentOrder.initialize_validation_date();
|
||||
|
||||
@@ -1532,6 +1532,14 @@ export class PosGlobalState extends PosModel {
|
||||
switchPane() {
|
||||
this.mobile_pane = this.mobile_pane === "left" ? "right" : "left";
|
||||
}
|
||||
async logEmployeeMessage(action, message) {
|
||||
await this.orm.call("pos.session", "log_partner_message", [
|
||||
this.pos_session.id,
|
||||
this.user.partner_id.id,
|
||||
action,
|
||||
message,
|
||||
]);
|
||||
}
|
||||
}
|
||||
PosGlobalState.prototype.electronic_payment_interfaces = {};
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ class PosSession(models.Model):
|
||||
domain = ['&', ('company_id', '=', self.config_id.company_id.id), '|', ('user_id', '=', self.user_id.id), ('id', 'in', self.config_id.employee_ids.ids)]
|
||||
else:
|
||||
domain = [('company_id', '=', self.config_id.company_id.id)]
|
||||
return {'search_params': {'domain': domain, 'fields': ['name', 'id', 'user_id'], 'load': False}}
|
||||
return {'search_params': {'domain': domain, 'fields': ['name', 'id', 'user_id', 'work_contact_id'], 'load': False}}
|
||||
|
||||
def _get_pos_ui_hr_employee(self, params):
|
||||
employees = self.env['hr.employee'].search_read(**params['search_params'])
|
||||
|
||||
@@ -56,6 +56,18 @@ patch(PosGlobalState.prototype, "pos_hr.PosGlobalState", {
|
||||
}
|
||||
return this._super(...arguments);
|
||||
},
|
||||
async logEmployeeMessage(action, message) {
|
||||
if (!this.config.module_pos_hr) {
|
||||
this._super(...arguments);
|
||||
return;
|
||||
}
|
||||
await this.orm.call("pos.session", "log_partner_message", [
|
||||
this.pos_session.id,
|
||||
this.cashier.work_contact_id,
|
||||
action,
|
||||
message,
|
||||
]);
|
||||
},
|
||||
});
|
||||
|
||||
patch(Order.prototype, "pos_hr.Order", {
|
||||
|
||||
Reference in New Issue
Block a user