This commit is contained in:
gsinghpal
2026-02-24 01:18:44 -05:00
parent e8e554de95
commit f85658c03a
41 changed files with 4440 additions and 119 deletions

View File

@@ -0,0 +1,314 @@
# -*- coding: utf-8 -*-
# Copyright 2024-2026 Nexa Systems Inc.
# License OPL-1 (Odoo Proprietary License v1.0)
from dateutil.relativedelta import relativedelta
from odoo import models, fields, api, _
class FusionLTCFacility(models.Model):
_name = 'fusion.ltc.facility'
_description = 'LTC Facility'
_inherit = ['mail.thread', 'mail.activity.mixin']
_order = 'name'
name = fields.Char(
string='Facility Name',
required=True,
tracking=True,
)
code = fields.Char(
string='Code',
copy=False,
readonly=True,
default=lambda self: _('New'),
)
active = fields.Boolean(default=True)
image_1920 = fields.Image(string='Image', max_width=1920, max_height=1920)
partner_id = fields.Many2one(
'res.partner',
string='Contact Record',
help='The facility as a contact in the system',
tracking=True,
)
# Address
street = fields.Char(string='Street')
street2 = fields.Char(string='Street2')
city = fields.Char(string='City')
state_id = fields.Many2one(
'res.country.state',
string='Province',
domain="[('country_id', '=', country_id)]",
)
zip = fields.Char(string='Postal Code')
country_id = fields.Many2one('res.country', string='Country')
phone = fields.Char(string='Phone')
email = fields.Char(string='Email')
website = fields.Char(string='Website')
# Key contacts
director_of_care_id = fields.Many2one(
'res.partner',
string='Director of Care',
tracking=True,
)
service_supervisor_id = fields.Many2one(
'res.partner',
string='Service Supervisor',
tracking=True,
)
physiotherapist_ids = fields.Many2many(
'res.partner',
'ltc_facility_physiotherapist_rel',
'facility_id',
'partner_id',
string='Physiotherapists',
help='Primary contacts for equipment recommendations and communication',
)
# Structure
number_of_floors = fields.Integer(string='Number of Floors')
floor_ids = fields.One2many(
'fusion.ltc.floor',
'facility_id',
string='Floors',
)
# Contract
contract_start_date = fields.Date(string='Contract Start Date', tracking=True)
contract_end_date = fields.Date(string='Contract End Date', tracking=True)
contract_file = fields.Binary(
string='Contract Document',
attachment=True,
)
contract_file_filename = fields.Char(string='Contract Filename')
contract_notes = fields.Text(string='Contract Notes')
# Cleanup scheduling
cleanup_frequency = fields.Selection([
('quarterly', 'Quarterly (Every 3 Months)'),
('semi_annual', 'Semi-Annual (Every 6 Months)'),
('annual', 'Annual (Yearly)'),
('custom', 'Custom Interval'),
], string='Cleanup Frequency', default='quarterly')
cleanup_interval_days = fields.Integer(
string='Custom Interval (Days)',
help='Number of days between cleanups when using custom interval',
)
next_cleanup_date = fields.Date(
string='Next Cleanup Date',
compute='_compute_next_cleanup_date',
store=True,
readonly=False,
tracking=True,
)
# Related records
repair_ids = fields.One2many('fusion.ltc.repair', 'facility_id', string='Repairs')
cleanup_ids = fields.One2many('fusion.ltc.cleanup', 'facility_id', string='Cleanups')
# Computed counts
repair_count = fields.Integer(compute='_compute_repair_count', string='Total Repairs')
active_repair_count = fields.Integer(compute='_compute_repair_count', string='Active Repairs')
cleanup_count = fields.Integer(compute='_compute_cleanup_count', string='Cleanups')
notes = fields.Html(string='Notes')
@api.model_create_multi
def create(self, vals_list):
for vals in vals_list:
if vals.get('code', _('New')) == _('New'):
vals['code'] = self.env['ir.sequence'].next_by_code('fusion.ltc.facility') or _('New')
return super().create(vals_list)
@api.depends('contract_start_date', 'cleanup_frequency', 'cleanup_interval_days')
def _compute_next_cleanup_date(self):
today = fields.Date.context_today(self)
for facility in self:
start = facility.contract_start_date
freq = facility.cleanup_frequency
if not start or not freq:
if not facility.next_cleanup_date:
facility.next_cleanup_date = False
continue
interval = facility._get_cleanup_interval_days()
delta = relativedelta(days=interval)
candidate = start + delta
while candidate < today:
candidate += delta
facility.next_cleanup_date = candidate
def action_preview_contract(self):
self.ensure_one()
if not self.contract_file:
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': _('No Document'),
'message': _('No contract document has been uploaded yet.'),
'type': 'warning',
'sticky': False,
},
}
attachment = self.env['ir.attachment'].search([
('res_model', '=', self._name),
('res_id', '=', self.id),
('res_field', '=', 'contract_file'),
], limit=1)
if not attachment:
attachment = self.env['ir.attachment'].search([
('res_model', '=', self._name),
('res_id', '=', self.id),
('name', '=', self.contract_file_filename or 'contract_file'),
], limit=1, order='id desc')
if attachment:
return {
'type': 'ir.actions.client',
'tag': 'fusion_claims.preview_document',
'params': {
'attachment_id': attachment.id,
'title': _('Contract - %s', self.name),
},
}
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': _('Error'),
'message': _('Could not load contract document.'),
'type': 'danger',
'sticky': False,
},
}
def _compute_repair_count(self):
for facility in self:
repairs = facility.repair_ids
facility.repair_count = len(repairs)
facility.active_repair_count = len(repairs.filtered(
lambda r: r.stage_id and not r.stage_id.fold
))
def _compute_cleanup_count(self):
for facility in self:
facility.cleanup_count = len(facility.cleanup_ids)
def action_view_repairs(self):
self.ensure_one()
return {
'name': _('Repairs - %s', self.name),
'type': 'ir.actions.act_window',
'res_model': 'fusion.ltc.repair',
'view_mode': 'kanban,list,form',
'domain': [('facility_id', '=', self.id)],
'context': {'default_facility_id': self.id},
}
def action_view_cleanups(self):
self.ensure_one()
return {
'name': _('Cleanups - %s', self.name),
'type': 'ir.actions.act_window',
'res_model': 'fusion.ltc.cleanup',
'view_mode': 'list,kanban,form',
'domain': [('facility_id', '=', self.id)],
'context': {'default_facility_id': self.id},
}
def _get_cleanup_interval_days(self):
mapping = {
'quarterly': 90,
'semi_annual': 180,
'annual': 365,
}
if self.cleanup_frequency == 'custom':
return self.cleanup_interval_days or 90
return mapping.get(self.cleanup_frequency, 90)
class FusionLTCFloor(models.Model):
_name = 'fusion.ltc.floor'
_description = 'LTC Facility Floor'
_order = 'sequence, name'
facility_id = fields.Many2one(
'fusion.ltc.facility',
string='Facility',
required=True,
ondelete='cascade',
)
name = fields.Char(string='Floor Name', required=True)
sequence = fields.Integer(string='Sequence', default=10)
station_ids = fields.One2many(
'fusion.ltc.station',
'floor_id',
string='Nursing Stations',
)
head_nurse_id = fields.Many2one(
'res.partner',
string='Head Nurse',
)
physiotherapist_id = fields.Many2one(
'res.partner',
string='Physiotherapist',
help='Floor-level physiotherapist if different from facility level',
)
class FusionLTCStation(models.Model):
_name = 'fusion.ltc.station'
_description = 'LTC Nursing Station'
_order = 'sequence, name'
floor_id = fields.Many2one(
'fusion.ltc.floor',
string='Floor',
required=True,
ondelete='cascade',
)
name = fields.Char(string='Station Name', required=True)
sequence = fields.Integer(string='Sequence', default=10)
head_nurse_id = fields.Many2one(
'res.partner',
string='Head Nurse',
)
phone = fields.Char(string='Phone')
class FusionLTCFamilyContact(models.Model):
_name = 'fusion.ltc.family.contact'
_description = 'LTC Resident Family Contact'
_order = 'is_poa desc, name'
partner_id = fields.Many2one(
'res.partner',
string='Resident',
required=True,
ondelete='cascade',
)
name = fields.Char(string='Contact Name', required=True)
relationship = fields.Selection([
('spouse', 'Spouse'),
('child', 'Child'),
('sibling', 'Sibling'),
('parent', 'Parent'),
('guardian', 'Guardian'),
('poa', 'Power of Attorney'),
('other', 'Other'),
], string='Relationship')
phone = fields.Char(string='Phone')
phone2 = fields.Char(string='Phone 2')
email = fields.Char(string='Email')
is_poa = fields.Boolean(string='Is POA', help='Is this person the Power of Attorney?')
notes = fields.Char(string='Notes')