updates
This commit is contained in:
376
fusion_claims/models/ltc_repair.py
Normal file
376
fusion_claims/models/ltc_repair.py
Normal file
@@ -0,0 +1,376 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2024-2026 Nexa Systems Inc.
|
||||
# License OPL-1 (Odoo Proprietary License v1.0)
|
||||
|
||||
from odoo import models, fields, api, _
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class FusionLTCRepairStage(models.Model):
|
||||
_name = 'fusion.ltc.repair.stage'
|
||||
_description = 'LTC Repair Stage'
|
||||
_order = 'sequence, id'
|
||||
|
||||
name = fields.Char(string='Stage Name', required=True, translate=True)
|
||||
sequence = fields.Integer(string='Sequence', default=10)
|
||||
fold = fields.Boolean(
|
||||
string='Folded in Kanban',
|
||||
help='Folded stages are hidden by default in the kanban view',
|
||||
)
|
||||
color = fields.Char(
|
||||
string='Stage Color',
|
||||
help='CSS color class for stage badge (e.g. info, success, warning, danger)',
|
||||
default='secondary',
|
||||
)
|
||||
description = fields.Text(string='Description')
|
||||
|
||||
|
||||
class FusionLTCRepair(models.Model):
|
||||
_name = 'fusion.ltc.repair'
|
||||
_description = 'LTC Repair Request'
|
||||
_inherit = ['mail.thread', 'mail.activity.mixin']
|
||||
_order = 'issue_reported_date desc, id desc'
|
||||
|
||||
name = fields.Char(
|
||||
string='Reference',
|
||||
required=True,
|
||||
copy=False,
|
||||
readonly=True,
|
||||
default=lambda self: _('New'),
|
||||
)
|
||||
facility_id = fields.Many2one(
|
||||
'fusion.ltc.facility',
|
||||
string='LTC Facility',
|
||||
required=True,
|
||||
tracking=True,
|
||||
index=True,
|
||||
)
|
||||
client_id = fields.Many2one(
|
||||
'res.partner',
|
||||
string='Client/Resident',
|
||||
tracking=True,
|
||||
help='Link to the resident contact record',
|
||||
)
|
||||
client_name = fields.Char(
|
||||
string='Client Name',
|
||||
help='Quick entry name when no contact record exists',
|
||||
)
|
||||
display_client_name = fields.Char(
|
||||
compute='_compute_display_client_name',
|
||||
string='Client',
|
||||
store=True,
|
||||
)
|
||||
room_number = fields.Char(string='Room Number')
|
||||
|
||||
stage_id = fields.Many2one(
|
||||
'fusion.ltc.repair.stage',
|
||||
string='Stage',
|
||||
tracking=True,
|
||||
group_expand='_read_group_stage_ids',
|
||||
default=lambda self: self._default_stage_id(),
|
||||
index=True,
|
||||
)
|
||||
kanban_state = fields.Selection([
|
||||
('normal', 'In Progress'),
|
||||
('done', 'Ready'),
|
||||
('blocked', 'Blocked'),
|
||||
], string='Kanban State', default='normal', tracking=True)
|
||||
color = fields.Integer(string='Color Index')
|
||||
|
||||
is_emergency = fields.Boolean(
|
||||
string='Emergency Repair',
|
||||
tracking=True,
|
||||
help='Emergency visits may be chargeable at an extra rate',
|
||||
)
|
||||
priority = fields.Selection([
|
||||
('0', 'Normal'),
|
||||
('1', 'High'),
|
||||
], string='Priority', default='0')
|
||||
|
||||
product_serial = fields.Char(string='Product Serial #')
|
||||
product_id = fields.Many2one(
|
||||
'product.product',
|
||||
string='Product',
|
||||
help='Link to product record if applicable',
|
||||
)
|
||||
issue_description = fields.Text(
|
||||
string='Issue Description',
|
||||
required=True,
|
||||
)
|
||||
issue_reported_date = fields.Date(
|
||||
string='Issue Reported Date',
|
||||
required=True,
|
||||
default=fields.Date.context_today,
|
||||
tracking=True,
|
||||
)
|
||||
issue_fixed_date = fields.Date(
|
||||
string='Issue Fixed Date',
|
||||
tracking=True,
|
||||
)
|
||||
resolution_description = fields.Text(string='Resolution Description')
|
||||
|
||||
assigned_technician_id = fields.Many2one(
|
||||
'res.users',
|
||||
string='Assigned Technician',
|
||||
tracking=True,
|
||||
)
|
||||
task_id = fields.Many2one(
|
||||
'fusion.technician.task',
|
||||
string='Field Service Task',
|
||||
tracking=True,
|
||||
)
|
||||
sale_order_id = fields.Many2one(
|
||||
'sale.order',
|
||||
string='Sale Order',
|
||||
tracking=True,
|
||||
help='Sale order created for this repair if applicable',
|
||||
)
|
||||
sale_order_name = fields.Char(
|
||||
related='sale_order_id.name',
|
||||
string='SO Reference',
|
||||
)
|
||||
|
||||
poa_name = fields.Char(string='Family/POA Name')
|
||||
poa_phone = fields.Char(string='Family/POA Phone')
|
||||
|
||||
company_id = fields.Many2one(
|
||||
'res.company',
|
||||
string='Company',
|
||||
default=lambda self: self.env.company,
|
||||
)
|
||||
currency_id = fields.Many2one(
|
||||
'res.currency',
|
||||
related='company_id.currency_id',
|
||||
)
|
||||
repair_value = fields.Monetary(
|
||||
string='Repair Value',
|
||||
currency_field='currency_id',
|
||||
)
|
||||
|
||||
photo_ids = fields.Many2many(
|
||||
'ir.attachment',
|
||||
'ltc_repair_photo_rel',
|
||||
'repair_id',
|
||||
'attachment_id',
|
||||
string='Photos (Legacy)',
|
||||
)
|
||||
before_photo_ids = fields.Many2many(
|
||||
'ir.attachment',
|
||||
'ltc_repair_before_photo_rel',
|
||||
'repair_id',
|
||||
'attachment_id',
|
||||
string='Before Photos',
|
||||
)
|
||||
after_photo_ids = fields.Many2many(
|
||||
'ir.attachment',
|
||||
'ltc_repair_after_photo_rel',
|
||||
'repair_id',
|
||||
'attachment_id',
|
||||
string='After Photos',
|
||||
)
|
||||
notes = fields.Text(string='Internal Notes')
|
||||
|
||||
source = fields.Selection([
|
||||
('portal_form', 'Portal Form'),
|
||||
('manual', 'Manual Entry'),
|
||||
('phone', 'Phone Call'),
|
||||
('migrated', 'Migrated'),
|
||||
], string='Source', default='manual', tracking=True)
|
||||
|
||||
stage_color = fields.Char(
|
||||
related='stage_id.color',
|
||||
string='Stage Color',
|
||||
store=True,
|
||||
)
|
||||
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
if vals.get('name', _('New')) == _('New'):
|
||||
vals['name'] = self.env['ir.sequence'].next_by_code('fusion.ltc.repair') or _('New')
|
||||
records = super().create(vals_list)
|
||||
for record in records:
|
||||
record._post_creation_message()
|
||||
return records
|
||||
|
||||
def _post_creation_message(self):
|
||||
body = _(
|
||||
"Repair request submitted for <b>%(client)s</b> in Room <b>%(room)s</b>"
|
||||
" at <b>%(facility)s</b>.<br/>"
|
||||
"Issue: %(issue)s",
|
||||
client=self.display_client_name or 'N/A',
|
||||
room=self.room_number or 'N/A',
|
||||
facility=self.facility_id.name,
|
||||
issue=self.issue_description or '',
|
||||
)
|
||||
self.message_post(body=body, message_type='comment')
|
||||
|
||||
def _default_stage_id(self):
|
||||
return self.env['fusion.ltc.repair.stage'].search([], order='sequence', limit=1).id
|
||||
|
||||
@api.model
|
||||
def _read_group_stage_ids(self, stages, domain):
|
||||
return self.env['fusion.ltc.repair.stage'].search([], order='sequence')
|
||||
|
||||
@api.depends('client_id', 'client_name')
|
||||
def _compute_display_client_name(self):
|
||||
for repair in self:
|
||||
if repair.client_id:
|
||||
repair.display_client_name = repair.client_id.name
|
||||
else:
|
||||
repair.display_client_name = repair.client_name or ''
|
||||
|
||||
@api.onchange('client_id')
|
||||
def _onchange_client_id(self):
|
||||
if self.client_id:
|
||||
self.client_name = self.client_id.name
|
||||
if hasattr(self.client_id, 'x_fc_ltc_room_number') and self.client_id.x_fc_ltc_room_number:
|
||||
self.room_number = self.client_id.x_fc_ltc_room_number
|
||||
if hasattr(self.client_id, 'x_fc_ltc_facility_id') and self.client_id.x_fc_ltc_facility_id:
|
||||
self.facility_id = self.client_id.x_fc_ltc_facility_id
|
||||
|
||||
def action_view_sale_order(self):
|
||||
self.ensure_one()
|
||||
if not self.sale_order_id:
|
||||
return
|
||||
return {
|
||||
'name': self.sale_order_id.name,
|
||||
'type': 'ir.actions.act_window',
|
||||
'res_model': 'sale.order',
|
||||
'view_mode': 'form',
|
||||
'res_id': self.sale_order_id.id,
|
||||
}
|
||||
|
||||
def action_view_task(self):
|
||||
self.ensure_one()
|
||||
if not self.task_id:
|
||||
return
|
||||
return {
|
||||
'name': self.task_id.name,
|
||||
'type': 'ir.actions.act_window',
|
||||
'res_model': 'fusion.technician.task',
|
||||
'view_mode': 'form',
|
||||
'res_id': self.task_id.id,
|
||||
}
|
||||
|
||||
def action_create_sale_order(self):
|
||||
self.ensure_one()
|
||||
if self.sale_order_id:
|
||||
raise UserError(_('A sale order already exists for this repair.'))
|
||||
|
||||
if not self.client_id and self.client_name:
|
||||
return {
|
||||
'name': _('Link Contact'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'res_model': 'fusion.ltc.repair.create.so.wizard',
|
||||
'view_mode': 'form',
|
||||
'target': 'new',
|
||||
'context': {
|
||||
'default_repair_id': self.id,
|
||||
'default_client_name': self.client_name,
|
||||
},
|
||||
}
|
||||
|
||||
if not self.client_id:
|
||||
raise UserError(_('Please set a client before creating a sale order.'))
|
||||
|
||||
return self._create_linked_sale_order()
|
||||
|
||||
def _create_linked_sale_order(self):
|
||||
self.ensure_one()
|
||||
SaleOrder = self.env['sale.order']
|
||||
OrderLine = self.env['sale.order.line']
|
||||
|
||||
so_vals = {
|
||||
'partner_id': self.client_id.id,
|
||||
'x_fc_ltc_repair_id': self.id,
|
||||
}
|
||||
sale_order = SaleOrder.create(so_vals)
|
||||
|
||||
seq = 10
|
||||
OrderLine.create({
|
||||
'order_id': sale_order.id,
|
||||
'display_type': 'line_section',
|
||||
'name': 'PRODUCTS & REPAIRS',
|
||||
'sequence': seq,
|
||||
})
|
||||
seq += 10
|
||||
|
||||
repair_tmpl = self.env.ref(
|
||||
'fusion_claims.product_ltc_repair_service', raise_if_not_found=False
|
||||
)
|
||||
repair_product = (
|
||||
repair_tmpl.product_variant_id if repair_tmpl else False
|
||||
)
|
||||
line_vals = {
|
||||
'order_id': sale_order.id,
|
||||
'sequence': seq,
|
||||
'name': 'Repairs at LTC Home - %s' % (self.facility_id.name or ''),
|
||||
}
|
||||
if repair_product:
|
||||
line_vals['product_id'] = repair_product.id
|
||||
else:
|
||||
line_vals['display_type'] = 'line_note'
|
||||
OrderLine.create(line_vals)
|
||||
seq += 10
|
||||
|
||||
OrderLine.create({
|
||||
'order_id': sale_order.id,
|
||||
'display_type': 'line_section',
|
||||
'name': 'REPORTED ISSUES',
|
||||
'sequence': seq,
|
||||
})
|
||||
seq += 10
|
||||
|
||||
if self.issue_description:
|
||||
OrderLine.create({
|
||||
'order_id': sale_order.id,
|
||||
'display_type': 'line_note',
|
||||
'name': self.issue_description,
|
||||
'sequence': seq,
|
||||
})
|
||||
seq += 10
|
||||
|
||||
if self.issue_reported_date:
|
||||
OrderLine.create({
|
||||
'order_id': sale_order.id,
|
||||
'display_type': 'line_note',
|
||||
'name': 'Reported Date: %s' % self.issue_reported_date,
|
||||
'sequence': seq,
|
||||
})
|
||||
seq += 10
|
||||
|
||||
OrderLine.create({
|
||||
'order_id': sale_order.id,
|
||||
'display_type': 'line_section',
|
||||
'name': 'PROPOSED RESOLUTION',
|
||||
'sequence': seq,
|
||||
})
|
||||
seq += 10
|
||||
|
||||
if self.resolution_description:
|
||||
OrderLine.create({
|
||||
'order_id': sale_order.id,
|
||||
'display_type': 'line_note',
|
||||
'name': self.resolution_description,
|
||||
'sequence': seq,
|
||||
})
|
||||
seq += 10
|
||||
|
||||
if self.product_serial:
|
||||
OrderLine.create({
|
||||
'order_id': sale_order.id,
|
||||
'display_type': 'line_note',
|
||||
'name': 'Serial Number: %s' % self.product_serial,
|
||||
'sequence': seq,
|
||||
})
|
||||
|
||||
self.sale_order_id = sale_order.id
|
||||
|
||||
return {
|
||||
'name': sale_order.name,
|
||||
'type': 'ir.actions.act_window',
|
||||
'res_model': 'sale.order',
|
||||
'view_mode': 'form',
|
||||
'res_id': sale_order.id,
|
||||
}
|
||||
Reference in New Issue
Block a user