[16.0][ADD] advance_payment: advance payment agreement module#591
Open
[16.0][ADD] advance_payment: advance payment agreement module#591
Conversation
93c4bc2 to
e00fbc8
Compare
881a4bc to
1050af8
Compare
…ญญายืมเงิน) Implement complete advance payment lifecycle management with loan agreement tracking, usage records, and return workflows. Includes master data for loan types and banks, Thai Buddhist year sequence, and full state machine workflow. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
…kflow - Rename model advance.payment.agreement → advance.payment - New state flow: draft → submitted → approved → in_progress → done - Replace borrower_name/department/etc. with requested_by (res.users) and department_id (hr.department) - Add Reference field linking to purchase.request - Add advance.payment.method model (pattern: purchase.guarantee.method) - Auto-create outbound account.payment on approve - Auto-transition to in_progress when linked payment is posted - Add payment stat button on form - Add account_payment_kmitl, hr, purchase_request dependencies - Bump version to 16.0.2.0.0
- Batch _compute_method_id: single search instead of N+1 - Batch action_approve: create payments in one call, write state once - Add action_start() method to encapsulate in_progress transition - account_payment.action_post: delegate to action_start() and batch write
…ent field - Remove advance.payment.method model (not needed) - Remove reference_model and method_id fields from advance.payment - Hide advance_payment_id on account.payment form when empty
…cle events Post informative internal notes at each workflow step: - action_submit: submitted by, loan amount, and reason - action_approve: payment link, amount, partner, journal - action_start: payment link, disbursed amount, partner - action_close: amount used vs. remaining
…ation Add exception rules to validate loan amount must be > 100 and <= 50,000 baht using the base_exception framework with configurable blocking rules.
Use xpath to add related_model_id before exception_ids instead of trying to modify a non-existent field in the parent view.
Move exception_rule_views.xml after advance_payment_menus.xml so the parent menu_advance_payment_config exists when referenced.
- Wizard: check blocking exceptions before allowing ignore (match purchase_exception pattern), reset ignore_exception when blocked - Remove dead onchange_ignore_exception (loan_amount is readonly in submitted state) - Remove action_ignore_exceptions button from form (both rules are blocking so it always errors)
Add 4 accounting dimension fields (store=False) computed from analytic_distribution with inverse functions: - department_analytic_id (ส่วนงาน) - source_analytic_id (แหล่งเงิน) - fund_analytic_id (กองทุน) - activity_analytic_id (ด้าน/แผนงาน/กิจกรรม) Depends on account_analytic_kmitl for plan code support.
…bution to payment - Rename _ANALYTIC_PLAN_TO_FIELD to _analytic_keys (matches analytic.mixin convention) - Replace custom _inverse_analytic_id with _update_analytic_distribution from analytic.mixin - Pass analytic_distribution to account.payment in _prepare_account_payment_vals
…base_exception UI Set view_id to base_exception.view_exception_rule_confirm in the action, following the pattern used by purchase_exception, disbursement, kmitl_project. Without view_id, Odoo cannot find a primary form view for the wizard model so the exception dialog renders blank. Remove the redundant inherited view — related_model_id is populated via default_get context and does not need to appear in the view.
Call payments.action_post() immediately after creating the payment so the advance.payment transitions directly to in_progress without requiring manual confirmation of the payment. The existing hook in account_payment.action_post handles the state transition and chatter via action_start().
… for payment action_submit is the KMITL workflow step defined in account_payment_kmitl, not action_post. Move the advance_payment hook accordingly.
…status - Add disbursement_state field (pending/paid) on advance.payment - Set to 'pending' when payment is created on approval - Set to 'paid' when account.payment is posted - Show in tree view as optional badge after state column
- Add module category and two security groups: - User: can create/submit advance payments, sees own records - Manager: can approve, sees all records, inherits user - Add record rules: users restricted to own records (requested_by) - Restrict approve button to manager group - Restrict root menu to advance_payment_user group - Update access CSV to use module-specific groups - Remove unlink permission for users on usage lines
- Fix 1: simplify department_id default lambda (unnecessary conditional) - Fix 2: add copy=False to usage_line_ids and payment_ids - Fix 3: avoid duplicate chatter on exception re-submission by writing state directly instead of calling action_submit() in exception wizard - QW1: override write() to block protected field changes on non-draft records - QW2: validate submitter in action_submit() (requestor or manager only) - QW3: add date_submitted, date_approved, date_closed tracking fields - QW4: show disbursement_state in form view (hidden when False), tree optional=hide - QW5: enforce agreement number uniqueness via @api.constrains (skips 'New')
…yment redesign F1 - Cancel/Reject Workflow: - Add 'cancel' state to agreement lifecycle - Add cancel_reason field (readonly, copy=False) - Override write() already blocks protected fields on cancel state - action_open_reject_wizard(): manager sends submitted agreement back to draft with reason - action_open_cancel_wizard(): manager cancels submitted/approved/in_progress agreement - _action_do_cancel(): voids linked payments (draft/submitted → cancel, posted → draft → cancel) - _action_do_reject(): submitted → draft with reason stored in cancel_reason - New advance.payment.cancel.wizard model with reason input - Manager-only buttons in form header: ส่งกลับแก้ไข (reject) and ยกเลิกสัญญา (cancel) - 'cancel' badge decoration-danger in list view - 'Cancelled' filter in search view F2 - Return Payment Flow Redesign: - Add is_return_requested Boolean field on agreement - Return wizard now requires proof attachment (Many2many ir.attachment) - Wizard confirms return request only (no auto-close): sets is_return_requested=True, relinks attachments to agreement, posts chatter message - 'แจ้งคืนเงิน' button: visible for in_progress + NOT is_return_requested - 'ปิดสัญญา' button (manager only): visible for in_progress + is_return_requested - Manager manually creates inbound payment then closes the agreement
Close workflow: - action_close() shows confirmation wizard when amount_remaining > 0, with warning about outstanding balance; closes directly when remaining=0 - New wizard: advance.payment.close.confirm State protections when done/cancel: - Return lines tab: readonly (no create/edit/delete) - Attachments tab: readonly (prevents deletion of existing attachments) - Chatter still allows adding new attachments (default Odoo behavior) Reopen closed agreements: - New action_reopen(): done → in_progress, clears date_closed - Visible only to base.group_system (ERP admin) with confirm dialog Alert banner fix: - Hide disbursement_state banners when state is done or cancel Tests: 36 cases (+5 new: wizard confirm, direct close, reopen, guards)
Translate all 199 entries including field labels, state selections, validation messages, chatter log messages, and wizard UI strings.
…yment Part A — advance_payment fixes: - Remove required=True from bank_id (now optional at creation) - Add exception rules: missing bank account, missing department, missing analytic dimensions (all 4 required before submit) Part B — purchase_request_kmitl: - Rename payment_type 'loan' → 'advance' (value + label) - Update view warning message for advance payment type Part C — New module purchase_request_advance_payment: - Extend purchase.request with advance_payment_id (1:1 link) - "สร้างสัญญาเงินยืม" button on approved PRs with payment_type=advance Creates draft advance.payment with data from PR: requested_by, department_id, loan_amount (estimated_cost), loan_type=procurement, loan_reason, analytic_distribution, reference - Smart button "สัญญาเงินยืม" to navigate to linked AP - Cross-post: disbursement message posted to PR chatter when AP is paid
Follow-up to payment_type rename in purchase_request_kmitl. Demo purchase requests used the old 'loan' value which no longer exists.
…_type on AP from PR When an advance payment is created from a purchase request, the reference and loan_type_id fields are now readonly on the AP form to prevent accidental changes. Fields remain editable when creating AP standalone (reference is empty).
- Add row-level decoration colors matching state badge colors - Add create_date column (optional=show) - Move main_exception_id to optional=show (was always visible) - Add reference and loan_reason as optional=hide columns - Code formatting: self-closing XML tags, consistent indentation
… PR fields - Extract _prepare_advance_payment_vals() for override support - Use self.department_id.id directly instead of traversing employee - Lock additional fields on AP form when created from PR: loan_amount, requested_by, department_id (readonly when reference is set)
New setting in Settings → สัญญายืมเงิน: - Strict Submit Mode (advance_payment.strict_submit) - When ON: only the requestor or ERP admin can submit - When OFF (default): requestor, manager, or admin can submit Refactor action_submit() submitter check into _check_submit_permission() for clarity and to read the config parameter.
- Add @api.constrains: loan_amount cannot be negative (< 0) - Update exception rule: loan_amount must be > 0 to submit (changed from previous threshold of 100)
New group: group_advance_payment_officer - Hierarchy: User → Officer → Manager - Officer sees all records (same record rule as Manager) - Read-only access on all models (no create/write/delete) - Intended for finance staff who need to monitor agreements without modifying them
New module adding operating unit filtering to advance payments. Models: - advance.payment: operating_unit_id field (editable in draft, readonly after) - advance.payment.usage.line: related from agreement - advance.payment.return.line: related from agreement Security: - Global ir.rules filtering by user's allowed operating units for advance.payment, usage lines, and return lines Views: - Form: operating_unit_id before requested_by - Tree: operating_unit_id column (optional=hide) - Search: group by operating unit filter - All views restricted to group_multi_operating_unit
…lacement New module: advance_payment_operating_unit_access_all - Group: Access all OUs' advance payment - Overrides ir.rules for advance.payment, usage lines, and return lines to allow full cross-OU access for users in the group Fix advance_payment_operating_unit views (diff comments): - Form: move operating_unit_id after department_id (was before requested_by) - Tree: use xpath //tree/inside instead of field position
Add config parameter 'advance_payment.allow_manual_reference': - When enabled: users can specify Reference field manually on create - When disabled (default): Reference field is readonly, can only be set by the system (e.g. when creating from a purchase request)
ir.config_parameter.get_param returns string "True"/"False", not boolean. Compare with == "True" to get the correct boolean value.
Use base_setup.action_general_configuration instead of base.action_general_configuration (not available in CE). Add base_setup to depends.
Two issues: 1. Bridge module's attrs on reference field completely replaced the base view's attrs, so allow_manual_reference was never checked. Fixed by merging both conditions: readonly when setting disabled OR reference already has a value (from PR). 2. Simplified config param read to explicit string comparison (param == "True") instead of str2bool which had edge cases with boolean default values.
…le method Replace view-level attrs override with a Python method pattern: - Base module: _is_reference_readonly() checks config setting - Bridge module: overrides to also lock when reference has a value - View uses computed is_reference_readonly field for attrs This avoids bridge module attrs completely replacing base attrs, and makes the readonly logic extensible for future modules.
Fill all remaining empty msgstr entries including new fields: officer group, strict submit mode, allow manual reference, is_reference_readonly, loan amount constraint, and Thai UI strings.
… update Thai translations
15 test cases covering the full PR → AP bridge flow: - Create AP from approved PR (fields populated, analytic distribution) - Validation guards (state, payment_type, 1:1 constraint) - Cross-post on disbursement (action_start posts to PR chatter) - No cross-post for standalone AP without reference - is_reference_readonly override (from PR vs standalone) - Config setting allow_manual_reference integration - Smart button action returns correct AP form action
…le field locking Add computed field is_locked_by_reference with overridable method _is_locked_by_reference() in the base module. Fields loan_type_id, loan_amount, requested_by, and department_id use this field in attrs to become readonly when locked. Base module always returns False (no locking). Bridge module overrides to return True when reference has a value (created from PR). This removes all attrs overrides from the bridge module view, following the same pattern as is_reference_readonly for the reference field.
…verridable field locking" This reverts commit c29c77c.
…tralize field locking
Loan Type Model:
- Add reference_model (Char) field: empty=standalone, value=reference-required
- Set reference_model="purchase.request" on loan_type_procurement
- Standalone types (travel, education, etc.) have no reference_model
Advance Payment Model:
- Replace is_reference_readonly with two computed fields:
is_reference_visible (show/hide reference field based on loan_type + setting)
is_locked_by_reference (lock all data fields when reference has a value)
- Add _prepare_vals_from_reference() hook for bridge modules to auto-fill
- Add @api.onchange('reference') to call auto-fill on selection
- Add @api.onchange('loan_type_id') to clear reference when switching to standalone
- Domain on loan_type_id filters to standalone types by default
- Reference field: invisible when not needed, readonly after save (id != False)
View:
- All lockable fields (requested_by, department_id, loan_type_id, loan_amount,
loan_reason) use is_locked_by_reference for readonly attrs in base view
- No attrs overrides needed in bridge modules
Bridge Module (purchase_request_advance_payment):
- Remove _is_reference_readonly override (no longer exists)
- Add _prepare_vals_from_reference override for PR-specific auto-fill
- Remove all view attrs overrides (empty view file)
DX for future bridge modules:
1. Create loan_type with reference_model = "your.model"
2. Override _prepare_vals_from_reference() to return auto-fill vals
3. Provide action to create AP — no view changes needed
…om_reference override Simplify bridge module — the override added complexity without clear benefit since AP is already created with all values populated via _prepare_advance_payment_vals() in purchase_request.py.
42e3e6f to
61b9c73
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Add complete advance payment agreement lifecycle management module (สัญญายืมเงิน) for employee loan tracking. Includes 4 core models with state workflow (draft → in_progress → in_review → done), 2 wizards for usage records and return confirmations, master data for loan types and banks, and Thai Buddhist year sequence.
Implementation
🤖 Generated with Claude Code