This commit is contained in:
gsinghpal
2026-02-25 09:40:41 -05:00
parent 0e1aebe60b
commit e71bc503f9
69 changed files with 7537 additions and 82 deletions

View File

@@ -61,6 +61,61 @@ class ProductTemplate(models.Model):
help='Rental price per month if loaner converts to rental',
)
# ==========================================================================
# LOANER EQUIPMENT FIELDS
# ==========================================================================
x_fc_equipment_type = fields.Selection([
('type_1_walker', 'Type 1 Walker'),
('type_2_mw', 'Type 2 MW'),
('type_2_pw', 'Type 2 PW'),
('type_2_walker', 'Type 2 Walker'),
('type_3_mw', 'Type 3 MW'),
('type_3_pw', 'Type 3 PW'),
('type_3_walker', 'Type 3 Walker'),
('type_4_mw', 'Type 4 MW'),
('type_5_mw', 'Type 5 MW'),
('ceiling_lift', 'Ceiling Lift'),
('mobility_scooter', 'Mobility Scooter'),
('patient_lift', 'Patient Lift'),
('transport_wheelchair', 'Transport Wheelchair'),
('standard_wheelchair', 'Standard Wheelchair'),
('power_wheelchair', 'Power Wheelchair'),
('cushion', 'Cushion'),
('backrest', 'Backrest'),
('stairlift', 'Stairlift'),
('others', 'Others'),
], string='Equipment Type')
x_fc_wheelchair_category = fields.Selection([
('type_1', 'Type 1'),
('type_2', 'Type 2'),
('type_3', 'Type 3'),
('type_4', 'Type 4'),
('type_5', 'Type 5'),
], string='Wheelchair Category')
x_fc_seat_width = fields.Char(string='Seat Width')
x_fc_seat_depth = fields.Char(string='Seat Depth')
x_fc_seat_height = fields.Char(string='Seat Height')
x_fc_storage_location = fields.Selection([
('warehouse', 'Warehouse'),
('westin_brampton', 'Westin Brampton'),
('mobility_etobicoke', 'Mobility Etobicoke'),
('scarborough_storage', 'Scarborough Storage'),
('client_loaned', 'Client/Loaned'),
('rented_out', 'Rented Out'),
], string='Storage Location')
x_fc_listing_type = fields.Selection([
('owned', 'Owned'),
('borrowed', 'Borrowed'),
], string='Listing Type')
x_fc_asset_number = fields.Char(string='Asset Number')
x_fc_package_info = fields.Text(string='Package Information')
# ==========================================================================
# COMPUTED FIELDS
# ==========================================================================
@@ -107,3 +162,25 @@ class ProductTemplate(models.Model):
return self.default_code or ''
# ==========================================================================
# SECURITY DEPOSIT (added by fusion_rental)
# ==========================================================================
x_fc_security_deposit_type = fields.Selection(
[
('fixed', 'Fixed Amount'),
('percentage', 'Percentage of Rental Price'),
],
string='Security Deposit Type',
help='How the security deposit is calculated for this rental product.',
)
x_fc_security_deposit_amount = fields.Float(
string='Security Deposit Amount',
digits='Product Price',
help='Fixed dollar amount for the security deposit.',
)
x_fc_security_deposit_percent = fields.Float(
string='Security Deposit (%)',
help='Percentage of the rental line price to charge as deposit.',
)

View File

@@ -388,6 +388,30 @@ class FusionTechnicianTask(models.Model):
string='Notified At',
)
# ------------------------------------------------------------------
# RENTAL INSPECTION (added by fusion_rental)
# ------------------------------------------------------------------
rental_inspection_condition = fields.Selection([
('excellent', 'Excellent'),
('good', 'Good'),
('fair', 'Fair'),
('damaged', 'Damaged'),
], string='Inspection Condition')
rental_inspection_notes = fields.Text(
string='Inspection Notes',
)
rental_inspection_photo_ids = fields.Many2many(
'ir.attachment',
'technician_task_inspection_photo_rel',
'task_id',
'attachment_id',
string='Inspection Photos',
)
rental_inspection_completed = fields.Boolean(
string='Inspection Completed',
default=False,
)
# ------------------------------------------------------------------
# COMPUTED FIELDS
# ------------------------------------------------------------------
@@ -1608,22 +1632,37 @@ class FusionTechnicianTask(models.Model):
'res_id': self.purchase_order_id.id,
}
def _is_rental_pickup_task(self):
"""Check if this is a pickup task for a rental order."""
self.ensure_one()
return (
self.task_type == 'pickup'
and self.sale_order_id
and self.sale_order_id.is_rental_order
)
def action_complete_task(self):
"""Mark task as Completed."""
for task in self:
if task.status not in ('in_progress', 'en_route', 'scheduled'):
raise UserError(_("Task must be in progress to complete."))
if task._is_rental_pickup_task() and not task.rental_inspection_completed:
raise UserError(_(
"Rental pickup tasks require a security inspection before "
"completion. Please complete the inspection from the "
"technician portal first."
))
task.with_context(skip_travel_recalc=True).write({
'status': 'completed',
'completion_datetime': fields.Datetime.now(),
})
task._post_status_message('completed')
# Post completion notes to linked order chatter
if task.completion_notes and (task.sale_order_id or task.purchase_order_id):
task._post_completion_to_linked_order()
# Notify the person who scheduled the task
task._notify_scheduler_on_completion()
# Auto-advance ODSP status for delivery tasks
if (task.task_type == 'delivery'
and task.sale_order_id
and task.sale_order_id.x_fc_is_odsp_sale
@@ -1633,6 +1672,44 @@ class FusionTechnicianTask(models.Model):
"Delivery task completed by technician. Order marked as delivered.",
)
if task._is_rental_pickup_task():
task._apply_rental_inspection_results()
def _apply_rental_inspection_results(self):
"""Write inspection results from the task back to the rental order."""
self.ensure_one()
order = self.sale_order_id
if not order or not order.is_rental_order:
return
inspection_status = 'passed'
if self.rental_inspection_condition in ('fair', 'damaged'):
inspection_status = 'flagged'
vals = {
'rental_inspection_status': inspection_status,
'rental_inspection_notes': self.rental_inspection_notes or '',
}
if self.rental_inspection_photo_ids:
vals['rental_inspection_photo_ids'] = [(6, 0, self.rental_inspection_photo_ids.ids)]
order.write(vals)
if inspection_status == 'passed':
order._refund_security_deposit()
elif inspection_status == 'flagged':
order.activity_schedule(
'mail.mail_activity_data_todo',
date_deadline=fields.Date.today(),
summary=_("Review rental inspection: %s", order.name),
note=_(
"Technician flagged rental pickup for %s. "
"Condition: %s. Please review inspection photos and notes.",
order.partner_id.name,
self.rental_inspection_condition or 'Unknown',
),
user_id=order.user_id.id or self.env.uid,
)
def action_cancel_task(self):
"""Cancel the task. Sends cancellation email and reverts sale order if delivery."""
for task in self: