diff --git a/README.md b/README.md
index 7b39e4b..a6a6668 100644
--- a/README.md
+++ b/README.md
@@ -33,7 +33,12 @@ This module enhances Odoo's standard Expense workflow by providing account-split
- **Create Vendor Payment**: One-click button on the realization form to pay the employee the difference.
- **Create Customer Payment**: One-click button on the realization form to record the employee returning the excess funds.
-### 6. Validation & Security
+### 6. Custom Payment Wizard
+- **Company Advances**: Replaces the standard Odoo "Post Journal Entries" workflow for company-paid expenses with a custom "Register Payment" wizard.
+- **Vendor & Date Selection**: Allows the finance team to specify the exact vendor and payment date during the advance payment.
+- **Automated Uang Muka Routing**: The wizard automatically forces the payment debit to `118101 Uang Muka Operasional`, ensuring advances are correctly booked as prepaid expenses before receipts are realized.
+
+### 7. Validation & Security
- **Mandatory Receipts**: Prevents submission of employee-paid expenses without attachments.
- **Overdue Tracking**: Highlights missing realization receipts in red/alerts for company-paid expenses.
diff --git a/__manifest__.py b/__manifest__.py
index c5e25a1..9701e17 100644
--- a/__manifest__.py
+++ b/__manifest__.py
@@ -11,6 +11,7 @@
'views/product_views.xml',
'views/hr_expense_views.xml',
'views/hr_expense_realization_views.xml',
+ 'views/hr_expense_payment_wizard_views.xml',
'views/hr_expense_kiosk_templates.xml',
'views/res_config_settings_views.xml',
],
diff --git a/models/__init__.py b/models/__init__.py
index 4b9255e..dca7fdb 100644
--- a/models/__init__.py
+++ b/models/__init__.py
@@ -7,3 +7,4 @@ from . import hr_expense_realization
from . import account_payment
from . import res_company
from . import res_config_settings
+from . import hr_expense_payment_wizard
diff --git a/models/hr_expense_payment_wizard.py b/models/hr_expense_payment_wizard.py
new file mode 100644
index 0000000..72dd7bb
--- /dev/null
+++ b/models/hr_expense_payment_wizard.py
@@ -0,0 +1,82 @@
+from odoo import models, fields, api, _
+from odoo.exceptions import UserError
+
+class HrExpensePaymentWizard(models.TransientModel):
+ _name = 'hr.expense.payment.wizard'
+ _description = 'Expense Payment Wizard'
+
+ expense_sheet_id = fields.Many2one('hr.expense.sheet', required=True)
+ amount = fields.Monetary(string='Payment Amount', required=True, readonly=True)
+ currency_id = fields.Many2one('res.currency', related='expense_sheet_id.currency_id')
+ company_id = fields.Many2one('res.company', related='expense_sheet_id.company_id')
+
+ partner_id = fields.Many2one(
+ 'res.partner',
+ string='Vendor',
+ required=True,
+ domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]"
+ )
+ journal_id = fields.Many2one(
+ 'account.journal',
+ string='Payment Journal',
+ required=True,
+ domain="[('type', 'in', ('bank', 'cash')), ('company_id', '=', company_id)]"
+ )
+ payment_method_line_id = fields.Many2one(
+ 'account.payment.method.line',
+ string='Payment Method',
+ required=True,
+ domain="[('journal_id', '=', journal_id), ('payment_type', '=', 'outbound')]"
+ )
+ payment_date = fields.Date(string='Payment Date', default=fields.Date.context_today, required=True)
+
+ @api.onchange('journal_id')
+ def _onchange_journal_id(self):
+ if self.journal_id:
+ available_payment_methods = self.journal_id.outbound_payment_method_line_ids
+ if available_payment_methods:
+ self.payment_method_line_id = available_payment_methods[0].id
+ else:
+ self.payment_method_line_id = False
+
+ def action_create_payment(self):
+ self.ensure_one()
+
+ # Find 118101 account
+ uang_muka_account = self.env['account.account'].search([
+ ('code', '=', '118101'),
+ ('company_id', '=', self.company_id.id)
+ ], limit=1)
+
+ if not uang_muka_account:
+ raise UserError(_("Account 118101 Uang Muka Operasional not found for this company!"))
+
+ payment_vals = {
+ 'date': self.payment_date,
+ 'amount': self.amount,
+ 'payment_type': 'outbound',
+ 'partner_type': 'supplier',
+ 'partner_id': self.partner_id.id,
+ 'journal_id': self.journal_id.id,
+ 'currency_id': self.currency_id.id,
+ 'payment_method_line_id': self.payment_method_line_id.id,
+ 'ref': self.expense_sheet_id.name,
+ 'destination_account_id': uang_muka_account.id,
+ }
+
+ payment = self.env['account.payment'].create(payment_vals)
+ payment.action_post()
+
+ # Link the payment's move to the expense sheet
+ payment.move_id.write({'expense_sheet_id': self.expense_sheet_id.id})
+
+ # Update sheet status to Paid
+ self.expense_sheet_id.write({
+ 'state': 'done',
+ 'amount_residual': 0.0,
+ 'payment_state': 'paid'
+ })
+ # Our custom logic will push it to 'wait_post' if realization is pending
+ self.expense_sheet_id.action_recompute_state()
+
+ return {'type': 'ir.actions.act_window_close'}
diff --git a/models/hr_expense_sheet.py b/models/hr_expense_sheet.py
index 0d13bd6..eb97e75 100644
--- a/models/hr_expense_sheet.py
+++ b/models/hr_expense_sheet.py
@@ -264,3 +264,17 @@ class HrExpenseSheet(models.Model):
""" Public wrapper to allow triggering recompute from a button. """
self._compute_state()
self._compute_from_account_move_ids()
+
+ def action_open_payment_wizard(self):
+ self.ensure_one()
+ return {
+ 'name': _('Register Payment'),
+ 'type': 'ir.actions.act_window',
+ 'res_model': 'hr.expense.payment.wizard',
+ 'view_mode': 'form',
+ 'target': 'new',
+ 'context': {
+ 'default_expense_sheet_id': self.id,
+ 'default_amount': self.total_amount,
+ }
+ }
diff --git a/views/hr_expense_payment_wizard_views.xml b/views/hr_expense_payment_wizard_views.xml
new file mode 100644
index 0000000..bef2c48
--- /dev/null
+++ b/views/hr_expense_payment_wizard_views.xml
@@ -0,0 +1,29 @@
+
+
+
+ hr.expense.payment.wizard.form
+ hr.expense.payment.wizard
+
+
+
+
+
diff --git a/views/hr_expense_views.xml b/views/hr_expense_views.xml
index cee25a8..17f3f18 100644
--- a/views/hr_expense_views.xml
+++ b/views/hr_expense_views.xml
@@ -143,6 +143,18 @@
state not in ['submit', 'approve', 'post', 'wait_post']
+
+ state != 'approve' or payment_mode == 'company_account'
+
+
+
+
draft,submit,approve,post,wait_post,done