vendor_payment_diff_amount/FINAL_FIX.md

264 lines
7.1 KiB
Markdown

# Final Fix: "Missing required account on accountable line"
## Problem Solved
The error "Missing required account on accountable line" has been resolved by ensuring proper `partner_id` handling on journal entry lines.
## Root Cause Analysis
Odoo's validation requires that:
1. Lines with **payable/receivable accounts** MUST have `partner_id`
2. Lines with **other account types** should NOT have `partner_id` (or it's optional)
The error occurred because the journal entry had inconsistent `partner_id` assignments.
## Complete Solution
### 1. Counterpart Line (Payable/Expense)
**Always set `partner_id`** on the counterpart line:
```python
# CRITICAL: Always ensure partner_id is set on counterpart line
counterpart_line['partner_id'] = self.partner_id.id
# Also ensure the account_id is set
if not counterpart_line.get('account_id'):
counterpart_line['account_id'] = self.destination_account_id.id
```
### 2. Deduction Lines (Tax/Expense)
**Never set `partner_id`** on deduction lines:
```python
deduction_line = {
'name': deduction_line_name,
'date_maturity': self.date,
'amount_currency': -deduction.amount_substract,
'currency_id': self.currency_id.id,
'debit': 0.0,
'credit': deduction_balance,
'account_id': deduction.substract_account_id.id,
# No partner_id - deduction accounts are tax/expense accounts
}
```
### 3. Account Domain Restriction
**Prevent wrong account selection** by updating the domain:
```python
domain="[('account_type', 'not in', ['asset_cash', 'asset_cash_bank', 'asset_receivable', 'liability_payable']), ('deprecated', '=', False)]"
```
This prevents users from selecting:
- ❌ Cash/Bank accounts
- ❌ Accounts Receivable
- ❌ Accounts Payable
And allows only:
- ✅ Tax Payable accounts (liability_current)
- ✅ Expense accounts
- ✅ Other liability accounts
- ✅ Income accounts (if needed)
## Correct Journal Entry Structure
### Example: Payment Rp 2,000,000 with deductions
**Scenario:**
- Vendor: PT Telkom Indonesia
- Amount: Rp 2,000,000
- PPh 21: Rp 100,000 (Tax Payable account)
- PPh 29: Rp 50,000 (Tax Payable account)
- Final Payment: Rp 1,850,000
**Journal Entry:**
| Account | Type | Debit | Credit | Partner | Valid? |
|---------|------|-------|--------|---------|--------|
| Accounts Payable | liability_payable | 2,000,000 | | PT Telkom | ✅ Required |
| PPh 21 | liability_current | | 100,000 | (none) | ✅ Correct |
| PPh 29 | liability_current | | 50,000 | (none) | ✅ Correct |
| Bank | asset_cash | | 1,850,000 | (none) | ✅ Correct |
**Total:** Debit 2,000,000 = Credit 2,000,000 ✅ Balanced
## Why This Works
### Odoo's Validation Logic
Odoo checks each journal entry line:
```python
# Pseudo-code of Odoo's validation
for line in journal_entry.lines:
if line.account.account_type in ('asset_receivable', 'liability_payable'):
if not line.partner_id:
raise ValidationError("Missing required account on accountable line")
```
### Our Solution
1. **Counterpart line** (Payable): Has `partner_id`
2. **Deduction lines** (Tax): No `partner_id`, and account type is NOT payable/receivable ✅
3. **Bank line** (Cash): No `partner_id`, and account type is NOT payable/receivable ✅
All lines pass validation!
## Account Type Reference
### Account Types in Odoo 17
| Account Type | Code | Requires Partner? | Use for Deductions? |
|--------------|------|-------------------|---------------------|
| Accounts Receivable | asset_receivable | ✅ Yes | ❌ No |
| Accounts Payable | liability_payable | ✅ Yes | ❌ No |
| Bank/Cash | asset_cash | ❌ No | ❌ No |
| Current Liabilities | liability_current | ❌ No | ✅ Yes (Tax Payable) |
| Expenses | expense | ❌ No | ✅ Yes |
| Other Liabilities | liability_non_current | ❌ No | ✅ Yes |
| Income | income | ❌ No | ⚠️ Rare |
## Testing Checklist
After applying this fix, test:
### ✅ Test 1: Payment without expense account
```
- Create vendor payment
- Amount: 1,000
- Add deduction: PPh 21 - 100 (use tax payable account)
- Post payment
- Expected: Success, no errors
```
### ✅ Test 2: Payment with expense account
```
- Create vendor payment
- Amount: 2,000
- Expense Account: Telepon & Internet
- Add deduction 1: PPh 21 - 100
- Add deduction 2: PPh 29 - 50
- Post payment
- Expected: Success, no errors
```
### ✅ Test 3: Verify journal entry
```
- Open posted payment
- View journal entry
- Check:
- Payable/Expense line has partner ✅
- Tax lines don't have partner ✅
- Entry is balanced ✅
```
### ❌ Test 4: Try wrong account (should fail gracefully)
```
- Create vendor payment
- Try to add deduction with Accounts Payable account
- Expected: Account not available in dropdown (domain restriction)
```
## Files Modified
1. **`models/account_payment.py`**
- Always set `partner_id` on counterpart line
- Never set `partner_id` on deduction lines
- Ensure `account_id` is set on counterpart line
2. **`models/payment_deduction_line.py`**
- Updated domain to exclude payable/receivable accounts
- Updated help text to clarify account selection
3. **Documentation files**
- `FIX_SUMMARY.md` - Initial fix documentation
- `FINAL_FIX.md` - This comprehensive guide
- `SCENARIOS.md` - Updated validation rules
## Common Mistakes to Avoid
### ❌ Don't Do This:
1. **Using Accounts Payable for deductions**
```
Wrong: PPh 21 → Accounts Payable (vendor account)
Right: PPh 21 → Tax Payable (liability account)
```
2. **Adding partner to all lines**
```python
# Wrong
for line in all_lines:
line['partner_id'] = partner.id # ❌
# Right
if line.account.account_type in ('asset_receivable', 'liability_payable'):
line['partner_id'] = partner.id # ✅
```
3. **Using expense accounts for tax withholding**
```
Wrong: PPh 21 → Expense account (reduces expense)
Right: PPh 21 → Tax Payable (creates liability)
```
## Accounting Best Practices
### Withholding Tax Treatment
When you withhold tax from a vendor payment:
1. **Record full expense/payable** (Debit)
2. **Record tax liability** (Credit) - you owe this to tax office
3. **Record reduced bank payment** (Credit) - actual cash out
This correctly represents:
- Full expense incurred
- Tax liability created
- Reduced cash payment
### Example Accounts Setup
Create these accounts for Indonesian tax:
```
217101 - PPh 21 (Tax Payable)
Type: Current Liabilities
Code: 217101
217102 - PPh 23 (Tax Payable)
Type: Current Liabilities
Code: 217102
117104 - PPh 29 (Tax Payable)
Type: Current Liabilities
Code: 117104
```
## Version
This fix is included in version 2.0.0 of the `vendor_payment_diff_amount` module.
## Support
If you still encounter issues:
1. Check that deduction accounts are NOT payable/receivable types
2. Verify the partner is set on the payment
3. Check Odoo logs for detailed error messages
4. Ensure you're using the latest version of the module
## Success Criteria
✅ Payments post without errors
✅ Journal entries are balanced
✅ Payable line has partner
✅ Tax lines don't have partner
✅ Correct accounting treatment
✅ Easy to use and understand
The module is now production-ready!