Files
enterprise-addons/pos_blackbox_be/models/pos_session.py
T

200 lines
8.6 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import models, fields, api, _
from odoo.fields import Domain
from odoo.exceptions import UserError
from itertools import groupby
from collections import Counter
class PosSession(models.Model):
_inherit = "pos.session"
cash_box_opening_number = fields.Integer(
help="Count the number of cashbox opening during the session"
)
users_clocked_ids = fields.Many2many(
"res.users",
"users_session_clocking_info",
string="Users Clocked In",
help="This is a technical field used for tracking the status of the session for each users.",
)
employees_clocked_ids = fields.Many2many(
"hr.employee",
"employees_session_clocking_info",
string="Employees Clocked In",
help="This is a technical field used for tracking the status of the session for each employees.",
)
pro_forma_sales_number = fields.Integer()
pro_forma_sales_amount = fields.Monetary()
pro_forma_refund_number = fields.Integer()
pro_forma_refund_amount = fields.Monetary()
correction_number = fields.Integer(
help="Count the number of corrections during the session"
)
correction_amount = fields.Monetary(
help="Sum of the amount of the corrections during the session"
)
def _load_pos_data_read(self, records, config):
read_records = super()._load_pos_data_read(records, config)
if read_records and config._uses_blackbox_v1():
record = read_records[0]
session = self if self.exists() else self.env["pos.session"].browse(record["id"]).exists()
record["_users_clocked_ids"] = session.users_clocked_ids.ids if session else []
record["_employees_clocked_ids"] = session.employees_clocked_ids.ids if session else []
record["_user_latest_clock_in"] = session._get_latest_user_clockin_date(config) if session else None
if config.module_pos_hr:
employees_insz_or_bis_number = self.env['hr.employee'].sudo().search_read(config._employee_domain(config.current_user_id.id), ['id', 'insz_or_bis_number'])
insz_or_bis_number_per_employee_id = {employee['id']: employee['insz_or_bis_number'] for employee in employees_insz_or_bis_number}
record["_employee_insz_or_bis_number"] = insz_or_bis_number_per_employee_id
return read_records
@api.depends("order_ids")
def _compute_amount_of_vat_tickets(self):
for rec in self:
rec.amount_of_vat_tickets = len(rec.order_ids)
def _set_opening_control_data(self, cashbox_value: int, notes: str):
self.env['pos.blackbox.log.ip']._log_ip(self.config_id, None)
super()._set_opening_control_data(cashbox_value, notes)
def increase_cash_box_opening_counter(self):
self.cash_box_opening_number += 1
def increase_correction_counter(self, amount):
self.correction_number += 1
self.correction_amount += self.currency_id.round(amount)
def set_user_session_work_status(self, user_id, status, all_insz):
context = (
"employees_clocked_ids"
if self.config_id.module_pos_hr
else "users_clocked_ids"
)
if all_insz:
self.write({context: [(5,)]})
elif status:
self.write({context: [(4, user_id)]})
else:
self.write({context: [(3, user_id)]})
self.config_id._notify("CLOCKING", {
'session_id': self.id,
'data': {
'pos.session': self._load_pos_data_read(self, self.config_id),
}
})
def _get_user_report_data(self):
data = []
orders = self.order_ids[::-1] # orders are sorted by date_order asc and we want date_order desc, then it needs to be filtered by user_id and employee_id
orders = orders.sorted(lambda order: order.employee_id.id or order.user_id.id) # if one order has an employee id, every order should have one. Otherwise, no orders has an employee id.
for k, g in groupby(orders, lambda order: order.employee_id or order.user_id):
insz = k.sudo().insz_or_bis_number
for order in g:
if order.is_clock:
if order.lines[0].product_id.id == self.env.ref('pos_blackbox_be.product_product_work_in').id:
data.append({
'login': k.name,
'insz_or_bis_number': insz,
'revenue': 0,
'revenue_per_category': Counter(),
'first_ticket_time': order.date_order,
'last_ticket_time': False,
'fdmIdentifier': self.config_id.certified_blackbox_identifier,
'cash_rounding_applied': 0,
})
else:
data[-1]['last_ticket_time'] = order.date_order
elif len(data) > 0 and not data[-1]['last_ticket_time']:
data[-1]['revenue'] += order.amount_paid
data[-1]['cash_rounding_applied'] += self.currency_id.round(order.amount_total - order.amount_paid)
total_sold_per_category = {}
for line in order.lines:
category_name = line.product_id.pos_categ_ids[0].name if len(line.product_id.pos_categ_ids) > 0 else "None"
if category_name not in total_sold_per_category:
total_sold_per_category[category_name] = 0
total_sold_per_category[category_name] += self.currency_id.round(line.price_subtotal_incl)
data[-1]['revenue_per_category'].update(Counter(total_sold_per_category))
for info in data:
info['revenue_per_category'] = list(info['revenue_per_category'].items())
return data
def action_report_journal_file(self):
self.ensure_one()
pos = self.config_id
if not pos.iface_fiscal_data_module:
raise UserError(_("PoS %s is not a certified PoS", pos.name))
return {
"type": "ir.actions.act_url",
"url": "/journal_file/" + str(pos.certified_blackbox_identifier),
"target": "self",
}
def _update_pro_forma(self, order):
self.ensure_one()
if order['state'] == "draft":
amount_total = order['amount_total']
if amount_total < 0:
self.pro_forma_refund_number += 1
self.pro_forma_refund_amount += self.currency_id.round(amount_total)
else:
self.pro_forma_sales_number += 1
self.pro_forma_sales_amount += self.currency_id.round(amount_total)
def get_total_discount_positive_negative(self, positive):
order_ids = self.order_ids.ids
price_operator = ">=" if positive else "<"
orderlines = self.env["pos.order.line"].search(
[("order_id", "in", order_ids), ("price_subtotal_incl", price_operator, 0), ("discount", ">", 0)]
)
amount = sum(
line._get_discount_amount()
for line in orderlines
)
return self.currency_id.round(amount)
def check_everyone_is_clocked_out(self):
if (
self.config_id.module_pos_hr and len(self.employees_clocked_ids.ids) > 0
) or (
not self.config_id.module_pos_hr and len(self.users_clocked_ids.ids) > 0
):
raise UserError(_("You cannot close the POS with employees still clocked in. Please clock them out first."))
def get_insz_clocked(self):
insz_map = {}
if self.config_id.module_pos_hr:
for employee in self.employees_clocked_ids:
insz_map[employee.id] = employee.sudo().insz_or_bis_number
else:
for user in self.users_clocked_ids:
insz_map[user.id] = user.sudo().insz_or_bis_number
return insz_map
def _get_latest_user_clockin_date(self, config):
self.ensure_one()
work_in_product = self.env.ref('pos_blackbox_be.product_product_work_in', raise_if_not_found=False)
if not work_in_product:
return None
domain = Domain('lines.product_id', '=', work_in_product.id)
if config.module_pos_hr:
domain &= Domain('employee_id', '=', self.employee_id.id)
else:
domain &= Domain('user_id', '=', self.user_id.id)
order = self.env['pos.order'].search(domain, order='id desc', limit=1)
return order.date_order if order else None