Files

203 lines
9.0 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import hashlib
import pathlib
import logging
from markupsafe import Markup
from odoo import http
from odoo.http import request
from odoo.modules import get_module_path
from odoo.addons.point_of_sale.controllers.main import PosController
from odoo.addons.pos_self_order.controllers.orders import PosSelfOrderController
from odoo.tools import consteq
from odoo.service.common import exp_version
from werkzeug.exceptions import Unauthorized
_logger = logging.getLogger(__name__)
BLACKBOX_MODULES = ['pos_blackbox_be']
class GovCertificationController(http.Controller):
@http.route('/fdm_source', auth='user')
def handler(self):
root = pathlib.Path(__file__).parent.parent.parent
modfiles = [
p
for modpath in map(pathlib.Path, map(get_module_path, BLACKBOX_MODULES))
for p in modpath.glob('**/*')
if p.is_file()
if p.suffix in ('.py', '.xml', '.js', '.csv')
if '/tests/' not in str(p)
]
modfiles.sort()
files_data = []
main_hash = hashlib.sha1()
for p in modfiles:
content = p.read_bytes()
content_hash = hashlib.sha1(content).hexdigest()
files_data.append({
'name': str(p.relative_to(root)),
'size_in_bytes': p.stat().st_size,
'contents': Markup(content.decode()),
'hash': content_hash
})
main_hash.update(content_hash.encode())
data = {
'files': files_data,
'main_hash': main_hash.hexdigest(),
}
return request.render('pos_blackbox_be.fdm_source', data, mimetype='text/plain')
@http.route("/journal_file/<string:serial>", auth="user")
def journal_file(self, serial, **kw):
# Give the journal file report for a specific blackbox serial: e.g. BODO001bd6034a
logs = request.env["pos_blackbox_be.log"].search([
("action", "=", "create"),
("description", "ilike", serial),
], order='id')
data = {
'pos_id': serial,
'logs': logs,
}
return request.render("pos_blackbox_be.journal_file", data, mimetype="text/plain")
class BlackboxPosSelfController(PosSelfOrderController):
@http.route('/pos_blackbox_be/send_order', auth='public', type='jsonrpc', website=True)
def pos_self_blackbox_send_order(self, access_token, order_access_token, order_id):
pos_config = self._verify_pos_config(access_token)
order = pos_config.current_session_id.order_ids.browse(order_id)
if not order or not consteq(order_access_token, order.access_token):
return False
return bool(order.blackbox_signature) or pos_config._send_order_to_blackbox(order)
@http.route('/pos_blackbox_be/get_signed_order', auth='public', type='jsonrpc', website=True)
def pos_blackbox_get_signed_order(self, access_token, order_access_token, order_id):
pos_config = self._verify_pos_config(access_token)
order = pos_config.current_session_id.order_ids.browse(order_id)
if not order or not consteq(order_access_token, order.access_token):
return False
if not order.blackbox_signature:
return False
return {
'blackbox_signature': order.blackbox_signature,
'blackbox_date': order.blackbox_date,
'blackbox_time': order.blackbox_time,
'blackbox_ticket_counters': order.blackbox_ticket_counters,
'blackbox_unique_fdm_production_number': order.blackbox_unique_fdm_production_number,
'blackbox_vsc_identification_number': order.blackbox_vsc_identification_number,
'plu_hash': order.plu_hash,
}
@http.route('/pos_self_blackbox/confirmation', methods=['POST'], auth='public', type='jsonrpc')
def pos_self_blackbox_confirmation(self):
def get_log_fields(order, data):
return [{
'state': order.state,
'create_date': order.date_order,
'employee_name': order.user_id.name if order.config_id.module_pos_hr else order.cashier,
'amount_total': order.amount_total,
'amount_paid': order.amount_paid,
'currency_id': order.currency_id.id,
'pos_reference': order.pos_reference,
'config_name': order.config_id.name,
'session_id': order.session_id.id,
'lines': [
{
"product_name": line.product_id.display_name,
"qty": line.qty,
"price_subtotal_incl": line.price_subtotal_incl,
"discount": line.discount,
}
for line in order.lines
],
'blackbox_order_sequence': order.blackbox_order_sequence,
'plu_hash': order.plu_hash,
'pos_version': exp_version()['server_serie'],
'blackbox_ticket_counters': order.blackbox_ticket_counters,
'blackbox_unique_fdm_production_number': order.blackbox_unique_fdm_production_number,
'certified_blackbox_identifier': order.config_id.certified_blackbox_identifier,
'blackbox_signature': order.blackbox_signature,
'change': 0,
}]
data = request.get_json_data()
device_identifier = data.get("device_identifier")
iot_mac = data.get("iot_mac")
if isinstance(device_identifier, str):
box = request.env['iot.box'].sudo().search([('identifier', '=', iot_mac)], limit=1)
if not box:
_logger.warning("No IoT found with mac/identifier '%s'. Request ignored", iot_mac)
return
blackbox = request.env["iot.device"].sudo().search([
('identifier', '=', device_identifier),
('iot_id', '=', box.id)
],
limit=1
)
if not blackbox:
_logger.warning("No blackbox found with identifier '%s' (iot_mac: %s). Request ignored", device_identifier, iot_mac)
return
order = request.env["pos.order"].sudo().browse(data.get("order_id"))
order._update_from_blackbox(data['blackbox_response'])
work_products = request.env["pos.config"]._get_work_products()
if set(order.lines.product_id) & set(work_products):
data["orderAccessToken"] = order.access_token
data["orderId"] = order.id
if order.lines[0].product_id.id == request.env.ref('pos_blackbox_be.product_product_work_in').id:
order.session_id.write({'users_clocked_ids': [(4, order.user_id.id)]})
else:
order.session_id.write({'users_clocked_ids': [(3, order.user_id.id)]})
order.config_id._notify("BLACKBOX_CLOCK", data)
if order.source == "kiosk":
order.config_id._notify("BLACKBOX_CONFIRMATION", data)
order.create_log(get_log_fields(order, data))
@http.route('/pos_self_blackbox/clock', auth='public', type='jsonrpc', website=True)
def pos_self_blackbox_clock(self, access_token, config_id, clock_in=True):
pos_config = self._get_pos_config_force(access_token, config_id)
clocked_users = pos_config.current_session_id.users_clocked_ids
if (clock_in and len(clocked_users) > 0) or (not clock_in and len(clocked_users) == 0):
return
pos_config._clock_kiosk_user(clock_in)
return
@http.route('/pos_self_blackbox/get_clock_order', auth='public', type='jsonrpc', website=True)
def get_clock_order(self, access_token, config_id, order_access_token, order_id):
pos_config = self._get_pos_config_force(access_token, config_id)
order = request.env['pos.order'].sudo().browse(order_id)
if not order or not consteq(order_access_token, order.access_token):
return {}
return self._generate_return_values(order, pos_config)
def _get_pos_config_force(self, access_token, config_id):
pos_config_sudo = request.env['pos.config'].sudo().browse(int(config_id))
if not pos_config_sudo or not consteq(pos_config_sudo.access_token, access_token):
raise Unauthorized("Invalid Access Token.")
company = pos_config_sudo.company_id
user = pos_config_sudo.self_ordering_default_user_id
return pos_config_sudo.sudo(False).with_company(company).with_user(user).with_context(allowed_company_ids=company.ids)
class BlackboxPosController(PosController):
@http.route()
def pos_web(self, config_id=False, from_backend=False, **k):
config = request.env['pos.config'].sudo().browse(int(config_id))
if config.current_session_id.state == "opened":
request.env['pos.blackbox.log.ip']._log_ip(config, None)
return super().pos_web(config_id=config_id, from_backend=from_backend, **k)