Skip to content

Claim Payment Documentation

Overview

The Claim Payment model (claim.payment) is a transient wizard model that provides a streamlined interface for recording payments against expense claims. It simplifies the reimbursement process by automatically creating and posting payment records.


Model Information

Model Name: claim.payment Display Name: Claim Payment Key Fields: None (transient model)

Features

  • ✅ Transient model (temporary data)
  • ❌ Audit logging enabled (_audit_log)
  • ❌ Multi-company support (company_id)
  • ✅ Automatic payment creation and posting
  • ✅ Amount validation against due amount
  • ✅ Bank account filtering

Key Fields Reference

All Fields

Field Type Required Description
amount Decimal Payment amount
date Date Payment date
account_id Many2One Bank account for payment
claim_id Many2One Claim being paid
ref Char Payment reference

Account Filtering

The account_id field is filtered to show only bank accounts:

condition=[["type", "=", "bank"]]


API Methods

1. Add Payment

Method: add_payment(ids, context)

Creates and posts a payment for the expense claim.

Behavior: 1. Validates payment amount doesn't exceed amount due 2. Gets unpaid claims account from Settings 3. Creates outgoing payment with type claim 4. Posts the payment 5. Returns navigation to claim edit view

Example:

# Create payment wizard
wizard_id = get_model("claim.payment").create({
    "claim_id": claim_id,
    "amount": 1000.00,
    "date": "2024-12-15",
    "account_id": bank_account_id,
    "ref": "REIMB-001",
})

# Process payment
result = get_model("claim.payment").add_payment([wizard_id])
# Returns: {"next": {...}, "flash": "Payment recorded"}

Raises: - Exception("Amound paid exceeds the amount due.") - If amount > claim.amount_due - AssertionError - If unpaid claims account not configured


Payment Structure

The wizard creates a payment with:

{
    "type": "out",                    # Outgoing payment
    "pay_type": "claim",              # Payment for claim
    "date": wizard.date,
    "ref": wizard.ref,
    "account_id": wizard.account_id,  # Bank account
    "currency_id": settings.currency_id,
    "lines": [{
        "type": "claim",
        "claim_id": claim.id,
        "account_id": claim.account_id,  # Unpaid claims account
        "amount": wizard.amount,
    }]
}

Model Relationship Description
account.claim Many2One (claim_id) Claim being reimbursed
account.account Many2One (account_id) Bank account
account.payment Created Payment record
settings Reference For unpaid claims account

Common Use Cases

Use Case 1: Full Claim Reimbursement

# Get claim
claim = get_model("account.claim").browse([claim_id])[0]

# Pay full amount due
wizard_id = get_model("claim.payment").create({
    "claim_id": claim_id,
    "amount": claim.amount_due,
    "date": "2024-12-15",
    "account_id": bank_account_id,
    "ref": "REIMB-FULL",
})

get_model("claim.payment").add_payment([wizard_id])

# Claim should now be "paid"
claim = get_model("account.claim").browse([claim_id])[0]
assert claim.state == "paid"

Use Case 2: Partial Reimbursement

# Pay partial amount
wizard_id = get_model("claim.payment").create({
    "claim_id": claim_id,
    "amount": 500.00,  # Partial
    "date": "2024-12-15",
    "account_id": bank_account_id,
    "ref": "REIMB-PARTIAL-1",
})

get_model("claim.payment").add_payment([wizard_id])

# Claim remains in "waiting_payment" with reduced amount_due

Use Case 3: Multiple Payments

# First payment
wizard1 = get_model("claim.payment").create({
    "claim_id": claim_id,
    "amount": 300.00,
    "date": "2024-12-10",
    "account_id": bank_account_id,
    "ref": "REIMB-1",
})
get_model("claim.payment").add_payment([wizard1])

# Second payment
wizard2 = get_model("claim.payment").create({
    "claim_id": claim_id,
    "amount": 200.00,
    "date": "2024-12-15",
    "account_id": bank_account_id,
    "ref": "REIMB-2",
})
get_model("claim.payment").add_payment([wizard2])

# Track payments
claim = get_model("account.claim").browse([claim_id])[0]
print(f"Total paid: {claim.amount_paid}")
print(f"Remaining: {claim.amount_due}")

Reimbursement Flow

1. Claim is in "waiting_payment" state
2. User initiates payment
3. Payment wizard displayed
   ├─ Enter payment amount
   ├─ Select bank account
   └─ Add reference
4. System validates amount <= amount_due
5. Payment created and posted
6. Claim amount_due reduced
7. If amount_due = 0, state changes to "paid"

Best Practices

1. Verify Claim State First

# Good: Check claim is ready for payment
claim = get_model("account.claim").browse([claim_id])[0]

if claim.state != "waiting_payment":
    raise Exception(f"Claim not ready for payment (state: {claim.state})")

if claim.amount_due <= 0:
    raise Exception("No amount due on this claim")

2. Include Reference for Audit Trail

# Good: Clear reference
wizard = get_model("claim.payment").create({
    "ref": f"REIMB-{claim.number}-{date}",
    ...
})

3. Use Correct Bank Account

# Good: Use designated reimbursement account
wizard = get_model("claim.payment").create({
    "account_id": petty_cash_account_id,  # or payroll_bank_id
    ...
})

Troubleshooting

"Amound paid exceeds the amount due"

Cause: Payment amount greater than claim.amount_due Solution: Reduce amount to claim.amount_due or less

"Missing unpaid expense claims account"

Cause: unpaid_claim_id not configured in Settings Solution: Configure Settings > unpaid_claim_id

"No bank accounts in dropdown"

Cause: No accounts with type="bank" Solution: Create bank account in Chart of Accounts


Testing Examples

Unit Test: Claim Payment

def test_claim_payment():
    # Assume claim exists in waiting_payment state
    claim = get_model("account.claim").browse([claim_id])[0]
    initial_due = claim.amount_due

    # Create payment
    wizard_id = get_model("claim.payment").create({
        "claim_id": claim_id,
        "amount": 100.00,
        "date": "2024-12-15",
        "account_id": bank_account_id,
    })

    # Process
    get_model("claim.payment").add_payment([wizard_id])

    # Verify
    claim = get_model("account.claim").browse([claim_id])[0]
    assert claim.amount_due == initial_due - 100.00
    assert claim.amount_paid >= 100.00

Security Considerations

Permission Model

  • Users need payment creation permissions
  • Bank account access required

Data Access

  • Transient model - wizard data not persisted
  • Creates permanent payment records

Configuration Requirements

Setting Location Description
unpaid_claim_id Settings Account for unpaid claims liability
currency_id Settings Default currency

Version History

Last Updated: December 2024 Model Version: claim_payment.py Framework: Netforce


Additional Resources

  • Account Claim Documentation: account.claim
  • Payment Documentation: account.payment
  • Account Documentation: account.account

This documentation is generated for developer onboarding and reference purposes.