From d2cac42d47be0ce337a7b0994c28d80ed129976c Mon Sep 17 00:00:00 2001 From: Suherdy Yacob Date: Tue, 3 Feb 2026 16:46:08 +0700 Subject: [PATCH] feat: Automatically adjust negative cash closing differences to prevent loss journal entries and increment module version. --- .gitignore | 5 +++++ README.md | 3 ++- __manifest__.py | 2 +- __pycache__/__init__.cpython-310.pyc | Bin 226 -> 0 bytes __pycache__/__init__.cpython-312.pyc | Bin 215 -> 0 bytes models/__pycache__/__init__.cpython-310.pyc | Bin 238 -> 0 bytes models/__pycache__/__init__.cpython-312.pyc | Bin 227 -> 0 bytes models/__pycache__/pos_session.cpython-310.pyc | Bin 4483 -> 0 bytes models/__pycache__/pos_session.cpython-312.pyc | Bin 7920 -> 0 bytes models/pos_session.py | 12 ++++++++++++ 10 files changed, 20 insertions(+), 2 deletions(-) delete mode 100755 __pycache__/__init__.cpython-310.pyc delete mode 100644 __pycache__/__init__.cpython-312.pyc delete mode 100755 models/__pycache__/__init__.cpython-310.pyc delete mode 100644 models/__pycache__/__init__.cpython-312.pyc delete mode 100755 models/__pycache__/pos_session.cpython-310.pyc delete mode 100644 models/__pycache__/pos_session.cpython-312.pyc diff --git a/.gitignore b/.gitignore index 50b84e4..16bb03e 100644 --- a/.gitignore +++ b/.gitignore @@ -64,3 +64,8 @@ session/ # System .DS_Store Thumbs.db + +# Editors +.vscode/ +.idea/ +*.swp diff --git a/README.md b/README.md index 7c9f934..ccdc095 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # POS Cash Opening Adjustment -**Version:** 17.0.1.0.0 +**Version:** 17.0.1.1.0 **Author:** Suherdy Yacob **Category:** Point of Sale **License:** LGPL-3 @@ -12,6 +12,7 @@ Prevent opening cash journal entries and exclude opening float from closing tota - **Opening Cash Adjustment:** Modifies how opening cash is handled to prevent unwanted journal entries. - **Closing Totals:** Excludes opening float from closing totals calculation. - **Zero-Amount Payment Cleanup:** Automatically removes `pos.payment` lines with `0.00` amount during session verification. This prevents the creation of "Difference at closing PoS session" journal items triggered by empty payments (e.g. from 100% discount or external payment edge cases). +- **Negative Cash Closing Adjustment:** Automatically overrides the cashier's input to match the expected closing balance if a negative difference is detected, logging the action in the chatter and preventing a loss journal entry. ## Technical Details ### Zero-Amount Payment Fix diff --git a/__manifest__.py b/__manifest__.py index 4274fe5..cfbc726 100755 --- a/__manifest__.py +++ b/__manifest__.py @@ -1,7 +1,7 @@ { "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", + "version": "17.0.1.1.0", "category": "Point of Sale", "author": "Suherdy Yacob", "depends": ["point_of_sale"], diff --git a/__pycache__/__init__.cpython-310.pyc b/__pycache__/__init__.cpython-310.pyc deleted file mode 100755 index 4f113cb3a6225381c1ad928ab6ccb1aba5834122..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 226 zcmYjLK?=e!5KO9w2!$T}L@y13;6L!RW9diCTNJh}1Yz|Jtc z%rcngD@J&2=XRYmnSW$tYMM|G0R!GL$1j{S$j+>sy*aH*J}n%AX~VJ1Cf29Sll60w zAAN43L1#o58`DFqqSAP+o$8dYG*%YGDGm*KO+N$z;$|oG7zT6-0DTZ02B}qOBzDGI hf0qg#ba%!NLQ3oHAZ69XX}PBwV`~nnRY)}o_63mNJDdOj diff --git a/__pycache__/__init__.cpython-312.pyc b/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index ea4bb762cc8ff77d8f74ccf510821174e518cc90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 215 zcmX@j%ge<81QYX}GDU#&V-N=hn4pZ$0zk%eh7^Vr#vF!R#wbQchDs()=9i2>VNJ$c zY`OUbfwCJ-QN5#&`$0og?qlec8MkmI63(&UId##51vqD{f4 zXs5h>^a-lM;1uM$4pjHJ>BYpBxL nxai|u8+hyUy(oU diff --git a/models/__pycache__/__init__.cpython-312.pyc b/models/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index e3695ad0205612f297a431097ca824c667b7e036..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 227 zcmXv|I|{-;5Zy^YLUNHdNMcRy5d;!rEJ{14} diff --git a/models/__pycache__/pos_session.cpython-310.pyc b/models/__pycache__/pos_session.cpython-310.pyc deleted file mode 100755 index 36f8a798674f9cf2497308b42cd5e27ed153604f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4483 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 diff --git a/models/__pycache__/pos_session.cpython-312.pyc b/models/__pycache__/pos_session.cpython-312.pyc deleted file mode 100644 index 0572ea31a6c9256c210238e8bb8a550e169b2564..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7920 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 diff --git a/models/pos_session.py b/models/pos_session.py index ce74f67..e92519d 100755 --- a/models/pos_session.py +++ b/models/pos_session.py @@ -136,6 +136,18 @@ class PosSession(models.Model): def _validate_session(self, balancing_account=False, amount_to_balance=0, bank_payment_method_diffs=None): for session in self: + if session.config_id.cash_control: + difference = session.cash_register_balance_end_real - session.cash_register_balance_end + if session.currency_id.compare_amounts(difference, 0.0) < 0: + session.message_post(body="Auto-adjustment: Cashier input %s overridden to expected %s to suppress negative difference of %s." % ( + session.currency_id.format(session.cash_register_balance_end_real), + session.currency_id.format(session.cash_register_balance_end), + session.currency_id.format(difference) + )) + session.write({'cash_register_balance_end_real': session.cash_register_balance_end}) + if amount_to_balance: + amount_to_balance -= difference + for order in session.order_ids: for payment in order.payment_ids: if session.currency_id.is_zero(payment.amount):