Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion hr_expense_petty_cash/models/account_move.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,36 @@ class AccountMove(models.Model):

def action_post(self):
self._check_petty_cash_amount()
return super().action_post()
res = super().action_post()
# Posting a petty cash clearing entry pays the expense sheet directly,
# there is no payment to register for it.
petty_cash_sheets = (
self.sudo()
.mapped("expense_sheet_id")
.filtered(lambda sheet: sheet.payment_mode == "petty_cash")
)
if petty_cash_sheets:
petty_cash_sheets.write(
{"state": "done", "amount_residual": 0.0, "payment_state": "paid"}
)
return res

def button_draft(self):
if self.env.context.get("skip_invoice_sync"):
return super().button_draft()
# Petty cash clearing entries keep an explicit balance + explicit tax
# lines. The tax recompute done by the sync when resetting to draft
# would otherwise strip the tax twice and create a spurious
# "Automatic Balancing Line".
petty_cash_moves = self.filtered(
lambda m: m.move_type == "entry"
and m.expense_sheet_id
and m.expense_sheet_id.payment_mode == "petty_cash"
)
if not petty_cash_moves:
return super().button_draft()
(self - petty_cash_moves).button_draft()
return petty_cash_moves.with_context(skip_invoice_sync=True).button_draft()

def _prepare_product_base_line_for_taxes_computation(self, product_line):
results = super()._prepare_product_base_line_for_taxes_computation(product_line)
Expand Down
8 changes: 0 additions & 8 deletions hr_expense_petty_cash/models/hr_expense_sheet.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,3 @@ def _prepare_bills_vals(self):
}
)
return res

def action_sheet_move_post(self):
res = super().action_sheet_move_post()
paid_petty_cash = self.filtered(lambda m: m.payment_mode == "petty_cash")
paid_petty_cash.write(
{"state": "done", "amount_residual": 0.0, "payment_state": "paid"}
)
return res
47 changes: 21 additions & 26 deletions hr_expense_petty_cash/tests/test_hr_expense_petty_cash.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,9 +258,6 @@ def test_02_create_expense_petty_cash(self):
expense_petty_cash_2 = self._create_expense(
200.0, self.employee_1, "petty_cash", self.petty_cash_holder_2
)
expense_petty_cash_3 = self._create_expense(
100.0, self.employee_2, "petty_cash", self.petty_cash_holder_2
)
expense_report = expense_own + expense_petty_cash + expense_petty_cash_2
# Check expenses must have 1 petty cash holder only
with self.assertRaises(ValidationError):
Expand All @@ -283,26 +280,7 @@ def test_02_create_expense_petty_cash(self):
sheet.action_submit_sheet()
self.assertEqual(sheet.state, "submit")
sheet.action_approve_expense_sheets()
# Check if the sheet is approved (could be 'approve' or
# 'post' depending on configuration)
self.assertIn(sheet.state, ["approve", "post"])
# Check state != draft, many employee and don't have product
with self.assertRaises(UserError):
expense_petty_cash.action_submit_expenses()
expense_test = expense_petty_cash_2 + expense_petty_cash_3
with self.assertRaises(UserError):
expense_test.action_submit_expenses()
expense_petty_cash_3.product_id = False
with self.assertRaises(UserError):
expense_petty_cash_3.action_submit_expenses()
# Check if journal entries were created and sheet is in final state
if sheet.state == "approve":
# If still in approve state, we need to post manually
sheet.action_sheet_move_post()
self.assertEqual(sheet.state, "post")
else:
# If already posted, just verify
self.assertEqual(sheet.state, "post")
self.assertEqual(sheet.state, "done")
self.assertTrue(sheet.account_move_ids.id)
self.assertEqual(self.petty_cash_holder.petty_cash_balance, 600.0)

Expand Down Expand Up @@ -371,9 +349,9 @@ def test_05_petty_cash_with_analytic_and_tax(self):
sheet = self._create_expense_sheet(expense)
sheet.action_submit_sheet()
sheet.action_approve_expense_sheets()
if sheet.state == "approve":
sheet.action_sheet_move_post()
self.assertEqual(sheet.state, "post")
# Petty cash sheets are paid automatically upon approval.
self.assertEqual(sheet.state, "done")
self.assertEqual(sheet.payment_state, "paid")

move = sheet.account_move_ids
self.assertEqual(move.move_type, "entry")
Expand Down Expand Up @@ -405,3 +383,20 @@ def test_05_petty_cash_with_analytic_and_tax(self):
tax_lines,
"Petty cash entry should generate a tax line.",
)

# Resetting the move to draft must not create a spurious
# "Automatic Balancing Line" and must keep the same line count.
line_count = len(move.line_ids)
move.button_draft()
self.assertEqual(len(move.line_ids), line_count)
self.assertFalse(
move.line_ids.filtered(lambda line: line.name == "Automatic Balancing Line")
)
self.assertEqual(sheet.state, "approve")
# Re-posting the move marks the petty cash sheet done/paid again
# without creating any extra line.
move.action_post()
self.assertEqual(move.state, "posted")
self.assertEqual(len(move.line_ids), line_count)
self.assertEqual(sheet.state, "done")
self.assertEqual(sheet.payment_state, "paid")
Loading