commit 20a99ff92deace1517a457fca958d7fe2d4d66d6 Author: Suherdy Yacob Date: Fri Oct 31 18:49:07 2025 +0700 first commit diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..9a7e03e --- /dev/null +++ b/__init__.py @@ -0,0 +1 @@ +from . import models \ No newline at end of file diff --git a/__manifest__.py b/__manifest__.py new file mode 100644 index 0000000..332fff7 --- /dev/null +++ b/__manifest__.py @@ -0,0 +1,15 @@ +{ + "name": "POS Cash Opening Adjustment", + "summary": "Prevent opening cash journal entries and exclude opening float from closing totals while keeping reconciliation data.", + "version": "17.0.1.0.0", + "category": "Point of Sale", + "depends": ["point_of_sale"], + "data": [], + "assets": { + "point_of_sale.assets": [ + "pos_cash_opening_adjustment/static/src/xml/closing_popup.xml", + ], + }, + "installable": True, + "license": "LGPL-3", +} \ No newline at end of file diff --git a/models/__init__.py b/models/__init__.py new file mode 100644 index 0000000..22988c7 --- /dev/null +++ b/models/__init__.py @@ -0,0 +1 @@ +from . import pos_session \ No newline at end of file diff --git a/models/pos_session.py b/models/pos_session.py new file mode 100644 index 0000000..409bb07 --- /dev/null +++ b/models/pos_session.py @@ -0,0 +1,110 @@ +# -*- coding: utf-8 -*- +from odoo import api, fields, models + + +class PosSession(models.Model): + _inherit = "pos.session" + + opening_cash_expected = fields.Monetary( + string="Expected Opening Cash", + currency_field="currency_id", + readonly=True, + help="Forecasted cash amount in the drawer when the session is opened.", + ) + opening_cash_counted = fields.Monetary( + string="Counted Opening Cash", + currency_field="currency_id", + readonly=True, + help="Actual cash amount counted by the cashier when the session is opened.", + ) + opening_cash_difference = fields.Monetary( + string="Opening Cash Difference", + currency_field="currency_id", + compute="_compute_opening_cash_difference", + store=True, + help="Difference between the expected and the counted cash at session opening.", + ) + + @api.depends("opening_cash_expected", "opening_cash_counted") + def _compute_opening_cash_difference(self): + for session in self: + expected = session.opening_cash_expected or 0.0 + counted = session.opening_cash_counted or 0.0 + session.opening_cash_difference = counted - expected + + def action_pos_session_open(self): + res = super().action_pos_session_open() + for session in self: + if session.config_id.cash_control: + session.write({ + "opening_cash_expected": session.cash_register_balance_start or 0.0, + "opening_cash_counted": 0.0, + }) + else: + session.write({ + "opening_cash_expected": 0.0, + "opening_cash_counted": 0.0, + }) + return res + + def set_cashbox_pos(self, cashbox_value: int, notes: str): + for session in self: + expected = session.opening_cash_expected if session.config_id.cash_control else 0.0 + if not session.config_id.cash_control: + expected = session.cash_register_balance_start or 0.0 + difference = cashbox_value - (expected or 0.0) + session.write({ + "state": "opened", + "opening_notes": notes, + "cash_register_balance_start": cashbox_value, + "opening_cash_expected": expected, + "opening_cash_counted": cashbox_value if session.config_id.cash_control else 0.0, + }) + session._post_cash_details_message("Opening", difference, notes) + return True + + @api.depends("payment_method_ids", "order_ids", "cash_register_balance_start", "cash_real_transaction", "statement_line_ids") + def _compute_cash_balance(self): + for session in self: + cash_payment_method = session.payment_method_ids.filtered("is_cash_count")[:1] + if cash_payment_method: + result = self.env["pos.payment"]._read_group( + [ + ("session_id", "=", session.id), + ("payment_method_id", "=", cash_payment_method.id), + ], + aggregates=["amount:sum"], + ) + total_cash_payment = result[0][0] or 0.0 + if session.state == "closed": + manual_cash_total = session.cash_real_transaction or 0.0 + else: + manual_cash_total = sum(session.statement_line_ids.mapped("amount")) + session.cash_register_total_entry_encoding = manual_cash_total + total_cash_payment + session.cash_register_balance_end = session.cash_register_balance_start + session.cash_register_total_entry_encoding + session.cash_register_difference = session.cash_register_balance_end_real - session.cash_register_balance_end + else: + session.cash_register_total_entry_encoding = 0.0 + session.cash_register_balance_end = 0.0 + session.cash_register_difference = 0.0 + + def get_closing_control_data(self): + data = super().get_closing_control_data() + default_cash_details = data.get("default_cash_details") + if default_cash_details: + manual_moves_total = sum(move.get("amount", 0.0) for move in default_cash_details.get("moves", [])) + payments_amount = default_cash_details.get("payment_amount") or 0.0 + opening_expected = self.opening_cash_expected or 0.0 + expected_total = opening_expected + payments_amount + manual_moves_total + session_cash_amount = payments_amount + manual_moves_total + + default_cash_details.update({ + "opening": opening_expected, + "opening_cash_expected": opening_expected, + "opening_cash_counted": self.opening_cash_counted or 0.0, + "opening_cash_difference": self.opening_cash_difference or 0.0, + "session_cash_amount": session_cash_amount, + "expected_amount": expected_total, + "amount": expected_total, + }) + return data \ No newline at end of file diff --git a/static/src/xml/closing_popup.xml b/static/src/xml/closing_popup.xml new file mode 100644 index 0000000..892b41c --- /dev/null +++ b/static/src/xml/closing_popup.xml @@ -0,0 +1,17 @@ + + + + + — + + + + Session cash sales & moves + + + + + \ No newline at end of file