# -*- coding: utf-8 -*- from odoo import models, api class PosSession(models.Model): _inherit = 'pos.session' def _get_last_active_cashier_name(self): self.ensure_one() order_domain = [('session_id', '=', self.id)] if 'payer_id' in self.env['pos.order']._fields: last_order = self.env['pos.order'].search( order_domain + [('payer_id', '!=', False)], order='id desc', limit=1 ) if last_order: return last_order.payer_id.name last_order = self.env['pos.order'].search( order_domain + [('employee_id', '!=', False)], order='id desc', limit=1 ) if last_order: return last_order.employee_id.name return self.employee_id.name or self.user_id.name or '' def get_closing_control_data(self): data = super().get_closing_control_data() data['last_cashier_name'] = self._get_last_active_cashier_name() return data def action_reprint_closing_summary(self): """Open the closing summary report for this session (backend reprint).""" self.ensure_one() return self.env.ref( 'pos_closing_receipt.action_report_pos_closing_summary' ).report_action(self) def get_closing_summary_data(self): """ Return structured data consumed by the QWeb report template. Aggregates payments grouped by payment method for all orders in this session. """ self.ensure_one() session = self payments = self.env['pos.payment'].search([ ('session_id', '=', session.id), ]) method_totals = {} for payment in payments: pm = payment.payment_method_id if pm.id not in method_totals: method_totals[pm.id] = { 'name': pm.name, 'is_cash': pm.type == 'cash', 'amount': 0.0, } method_totals[pm.id]['amount'] += payment.amount sorted_methods = sorted( method_totals.values(), key=lambda m: (0 if m['is_cash'] else 1, m['name']) ) cash_payment = None non_cash_payments = [] for m in sorted_methods: if m['is_cash']: cash_payment = m else: non_cash_payments.append(m) grand_total = sum(m['amount'] for m in sorted_methods) cashier_name = session._get_last_active_cashier_name() closing_time = '' if session.stop_at: tz = self.env.user.tz or 'UTC' try: import pytz utc_dt = session.stop_at.replace(tzinfo=pytz.utc) local_dt = utc_dt.astimezone(pytz.timezone(tz)) closing_time = local_dt.strftime('%Y-%m-%d %H:%M:%S') except Exception: closing_time = session.stop_at.strftime('%Y-%m-%d %H:%M:%S') return { 'session': session, 'session_name': session.name, 'cashier_name': cashier_name, 'closing_time': closing_time, 'cash_payment': cash_payment, 'non_cash_payments': non_cash_payments, 'grand_total': grand_total, } @api.model def get_last_closed_session_summary(self, config_id): """ Called from the POS frontend (Navbar) to reprint the last closed session summary for the given config. Returns a dict with: - session_name - cashier_name - closing_time (localized to current user's timezone) - payment_methods: [{id, name, is_cash, amount}] Returns False if no closed session exists for this config. """ session = self.search( [('config_id', '=', config_id), ('state', '=', 'closed')], order='stop_at desc', limit=1, ) if not session: return False payments = self.env['pos.payment'].search([ ('session_id', '=', session.id), ]) method_totals = {} for payment in payments: pm = payment.payment_method_id if pm.id not in method_totals: method_totals[pm.id] = { 'id': pm.id, 'name': pm.name, 'is_cash': pm.type == 'cash', 'amount': 0.0, } method_totals[pm.id]['amount'] += payment.amount # Sort: cash first, then alphabetically payment_methods = sorted( method_totals.values(), key=lambda m: (0 if m['is_cash'] else 1, m['name']) ) cashier_name = session._get_last_active_cashier_name() closing_time = '' if session.stop_at: tz = self.env.user.tz or 'UTC' try: import pytz utc_dt = session.stop_at.replace(tzinfo=pytz.utc) local_dt = utc_dt.astimezone(pytz.timezone(tz)) closing_time = local_dt.strftime('%Y-%m-%d %H:%M:%S') except Exception: closing_time = session.stop_at.strftime('%Y-%m-%d %H:%M:%S') return { 'session_name': session.name, 'cashier_name': cashier_name, 'closing_time': closing_time, 'payment_methods': payment_methods, }