changes
This commit is contained in:
2
fusion_rental/wizard/__init__.py
Normal file
2
fusion_rental/wizard/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from . import manual_renewal_wizard
|
||||
from . import deposit_deduction_wizard
|
||||
64
fusion_rental/wizard/deposit_deduction_wizard.py
Normal file
64
fusion_rental/wizard/deposit_deduction_wizard.py
Normal file
@@ -0,0 +1,64 @@
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class DepositDeductionWizard(models.TransientModel):
|
||||
_name = 'deposit.deduction.wizard'
|
||||
_description = 'Security Deposit Deduction'
|
||||
|
||||
order_id = fields.Many2one(
|
||||
'sale.order',
|
||||
string="Rental Order",
|
||||
required=True,
|
||||
readonly=True,
|
||||
)
|
||||
deposit_total = fields.Float(
|
||||
string="Deposit Amount",
|
||||
readonly=True,
|
||||
)
|
||||
deduction_amount = fields.Float(
|
||||
string="Deduction Amount",
|
||||
required=True,
|
||||
help="Amount to deduct from the security deposit for damages.",
|
||||
)
|
||||
reason = fields.Text(
|
||||
string="Reason for Deduction",
|
||||
required=True,
|
||||
)
|
||||
remaining_preview = fields.Float(
|
||||
string="Remaining to Refund",
|
||||
compute='_compute_remaining_preview',
|
||||
)
|
||||
overage_preview = fields.Float(
|
||||
string="Additional Invoice Amount",
|
||||
compute='_compute_remaining_preview',
|
||||
help="Amount exceeding the deposit that will be invoiced to the customer.",
|
||||
)
|
||||
|
||||
@api.depends('deposit_total', 'deduction_amount')
|
||||
def _compute_remaining_preview(self):
|
||||
for wizard in self:
|
||||
diff = wizard.deposit_total - wizard.deduction_amount
|
||||
if diff >= 0:
|
||||
wizard.remaining_preview = diff
|
||||
wizard.overage_preview = 0.0
|
||||
else:
|
||||
wizard.remaining_preview = 0.0
|
||||
wizard.overage_preview = abs(diff)
|
||||
|
||||
def action_confirm_deduction(self):
|
||||
self.ensure_one()
|
||||
if self.deduction_amount <= 0:
|
||||
raise UserError(_("Deduction amount must be greater than zero."))
|
||||
|
||||
order = self.order_id
|
||||
order._deduct_security_deposit(self.deduction_amount)
|
||||
order.message_post(body=_(
|
||||
"Security deposit deduction of %s processed.\nReason: %s",
|
||||
self.env['ir.qweb.field.monetary'].value_to_html(
|
||||
self.deduction_amount,
|
||||
{'display_currency': order.currency_id},
|
||||
),
|
||||
self.reason,
|
||||
))
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
36
fusion_rental/wizard/deposit_deduction_wizard_views.xml
Normal file
36
fusion_rental/wizard/deposit_deduction_wizard_views.xml
Normal file
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="deposit_deduction_wizard_form" model="ir.ui.view">
|
||||
<field name="name">deposit.deduction.wizard.form</field>
|
||||
<field name="model">deposit.deduction.wizard</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Deduct Security Deposit">
|
||||
<group>
|
||||
<group>
|
||||
<field name="order_id"/>
|
||||
<field name="deposit_total" widget="monetary"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="deduction_amount" widget="monetary"/>
|
||||
<field name="remaining_preview" widget="monetary"/>
|
||||
<field name="overage_preview" widget="monetary"
|
||||
decoration-danger="overage_preview > 0"/>
|
||||
</group>
|
||||
</group>
|
||||
<group>
|
||||
<field name="reason" placeholder="Describe the damages or reason for deduction..."/>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="action_confirm_deduction"
|
||||
string="Confirm Deduction"
|
||||
type="object"
|
||||
class="btn-primary"
|
||||
icon="fa-check"/>
|
||||
<button string="Cancel" class="btn-secondary" special="cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
101
fusion_rental/wizard/manual_renewal_wizard.py
Normal file
101
fusion_rental/wizard/manual_renewal_wizard.py
Normal file
@@ -0,0 +1,101 @@
|
||||
import logging
|
||||
from datetime import timedelta
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ManualRenewalWizard(models.TransientModel):
|
||||
_name = 'manual.renewal.wizard'
|
||||
_description = 'Manual Rental Renewal Wizard'
|
||||
|
||||
order_id = fields.Many2one(
|
||||
'sale.order',
|
||||
string="Rental Order",
|
||||
required=True,
|
||||
readonly=True,
|
||||
)
|
||||
partner_id = fields.Many2one(
|
||||
related='order_id.partner_id',
|
||||
string="Customer",
|
||||
)
|
||||
current_start_date = fields.Datetime(
|
||||
string="Current Start Date",
|
||||
readonly=True,
|
||||
)
|
||||
current_return_date = fields.Datetime(
|
||||
string="Current Return Date",
|
||||
readonly=True,
|
||||
)
|
||||
new_start_date = fields.Datetime(
|
||||
string="New Start Date",
|
||||
required=True,
|
||||
)
|
||||
new_return_date = fields.Datetime(
|
||||
string="New Return Date",
|
||||
required=True,
|
||||
)
|
||||
amount_preview = fields.Float(
|
||||
string="Estimated Renewal Amount",
|
||||
compute='_compute_amount_preview',
|
||||
)
|
||||
|
||||
@api.depends('order_id', 'new_start_date', 'new_return_date')
|
||||
def _compute_amount_preview(self):
|
||||
for wizard in self:
|
||||
if wizard.order_id:
|
||||
wizard.amount_preview = wizard.order_id._get_renewal_amount()
|
||||
else:
|
||||
wizard.amount_preview = 0.0
|
||||
|
||||
def action_confirm_renewal(self):
|
||||
"""Confirm the manual renewal: extend dates, invoice, and collect payment."""
|
||||
self.ensure_one()
|
||||
order = self.order_id
|
||||
|
||||
if not order.is_rental_order:
|
||||
raise UserError(_("This is not a rental order."))
|
||||
|
||||
if self.new_return_date <= self.new_start_date:
|
||||
raise UserError(_("New return date must be after the new start date."))
|
||||
|
||||
old_start = order.rental_start_date
|
||||
old_return = order.rental_return_date
|
||||
|
||||
order.write({
|
||||
'rental_start_date': self.new_start_date,
|
||||
'rental_return_date': self.new_return_date,
|
||||
})
|
||||
order._recompute_rental_prices()
|
||||
|
||||
invoice = order._create_renewal_invoice()
|
||||
if invoice:
|
||||
invoice.action_post()
|
||||
|
||||
renewal_log = self.env['rental.renewal.log'].create({
|
||||
'order_id': order.id,
|
||||
'renewal_number': order.rental_renewal_count + 1,
|
||||
'previous_start_date': old_start,
|
||||
'previous_return_date': old_return,
|
||||
'new_start_date': self.new_start_date,
|
||||
'new_return_date': self.new_return_date,
|
||||
'invoice_id': invoice.id if invoice else False,
|
||||
'renewal_type': 'manual',
|
||||
'state': 'done',
|
||||
'payment_status': 'pending',
|
||||
})
|
||||
|
||||
order.write({
|
||||
'rental_renewal_count': order.rental_renewal_count + 1,
|
||||
'rental_reminder_sent': False,
|
||||
})
|
||||
|
||||
order._send_renewal_confirmation_email(renewal_log, False)
|
||||
|
||||
if invoice:
|
||||
inv = invoice.with_user(self.env.uid)
|
||||
return inv.action_open_poynt_payment_wizard()
|
||||
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
46
fusion_rental/wizard/manual_renewal_wizard_views.xml
Normal file
46
fusion_rental/wizard/manual_renewal_wizard_views.xml
Normal file
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- Manual Renewal Wizard Form -->
|
||||
<record id="manual_renewal_wizard_view_form" model="ir.ui.view">
|
||||
<field name="name">manual.renewal.wizard.form</field>
|
||||
<field name="model">manual.renewal.wizard</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Renew Rental">
|
||||
<group>
|
||||
<field name="order_id" readonly="1"/>
|
||||
<field name="partner_id" readonly="1"/>
|
||||
</group>
|
||||
<separator string="Current Rental Period"/>
|
||||
<group>
|
||||
<group>
|
||||
<field name="current_start_date" readonly="1"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="current_return_date" readonly="1"/>
|
||||
</group>
|
||||
</group>
|
||||
<separator string="New Rental Period"/>
|
||||
<group>
|
||||
<group>
|
||||
<field name="new_start_date"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="new_return_date"/>
|
||||
</group>
|
||||
</group>
|
||||
<group>
|
||||
<field name="amount_preview" widget="monetary"/>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="action_confirm_renewal"
|
||||
type="object"
|
||||
string="Confirm Renewal & Collect Payment"
|
||||
class="btn-primary"/>
|
||||
<button string="Cancel" class="btn-secondary" special="cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user