98 lines
3.9 KiB
Python
98 lines
3.9 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
from odoo import api, fields, models, _
|
|
|
|
|
|
class WheelchairAssessmentLine(models.Model):
|
|
_name = 'fusion.wc.assessment.line'
|
|
_description = 'Wheelchair Assessment Line Item'
|
|
_order = 'section_sequence, sequence, id'
|
|
|
|
assessment_id = fields.Many2one('fusion.wc.assessment', string='Assessment',
|
|
required=True, ondelete='cascade', index=True)
|
|
section_id = fields.Many2one('fusion.wc.section', string='Section', index=True)
|
|
section_sequence = fields.Integer(
|
|
related='section_id.sequence', store=True, string='Section Order')
|
|
sequence = fields.Integer(string='Sequence', default=10)
|
|
|
|
# Product
|
|
product_id = fields.Many2one('product.product', string='Product', index=True)
|
|
product_name = fields.Char(string='Description',
|
|
help='Can override product name with custom description')
|
|
quantity = fields.Float(string='Quantity', default=1.0)
|
|
|
|
# ADP info
|
|
adp_device_code = fields.Char(string='ADP Code')
|
|
adp_price = fields.Float(string='ADP Price', digits='Product Price')
|
|
unit_price = fields.Float(string='Selling Price', digits='Product Price')
|
|
|
|
# Build type (for seating items)
|
|
build_type = fields.Selection([
|
|
('modular', 'Modular'),
|
|
('custom_fabricated', 'Custom Fabricated'),
|
|
], string='Build Type')
|
|
|
|
# Clinical rationale (required for certain items)
|
|
clinical_rationale = fields.Text(string='Clinical Rationale')
|
|
|
|
# Computed pricing
|
|
subtotal = fields.Float(string='Subtotal',
|
|
compute='_compute_subtotal', store=True, digits='Product Price')
|
|
adp_portion = fields.Float(string='ADP Portion',
|
|
compute='_compute_portions', store=True, digits='Product Price')
|
|
client_portion = fields.Float(string='Client Portion',
|
|
compute='_compute_portions', store=True, digits='Product Price')
|
|
|
|
# Upcharge tracking
|
|
is_upcharge = fields.Boolean(string='Auto-Applied Upcharge', default=False)
|
|
upcharge_rule_id = fields.Many2one('fusion.wc.upcharge.rule',
|
|
string='Triggered By Rule')
|
|
upcharge_reason = fields.Char(string='Upcharge Reason')
|
|
|
|
# Section-specific measurements
|
|
width = fields.Float(string='Width', digits=(10, 2))
|
|
depth = fields.Float(string='Depth', digits=(10, 2))
|
|
height = fields.Float(string='Height', digits=(10, 2))
|
|
|
|
notes = fields.Text(string='Notes')
|
|
|
|
@api.depends('unit_price', 'quantity')
|
|
def _compute_subtotal(self):
|
|
for line in self:
|
|
line.subtotal = line.unit_price * line.quantity
|
|
|
|
@api.depends('subtotal', 'adp_price', 'quantity', 'assessment_id.client_type')
|
|
def _compute_portions(self):
|
|
"""Estimate ADP and client portions based on client type and ADP price."""
|
|
for line in self:
|
|
if not line.adp_price or not line.subtotal:
|
|
line.adp_portion = 0.0
|
|
line.client_portion = line.subtotal
|
|
continue
|
|
|
|
client_type = line.assessment_id.client_type or 'reg'
|
|
adp_base = line.adp_price * line.quantity
|
|
|
|
# Determine ADP coverage percentage
|
|
if client_type == 'reg':
|
|
# REG: 75% ADP, 25% client
|
|
adp_amount = adp_base * 0.75
|
|
else:
|
|
# ODS, ACS, OWP, etc.: 100% ADP
|
|
adp_amount = adp_base
|
|
|
|
# Client pays the rest (including anything above ADP price)
|
|
line.adp_portion = min(adp_amount, line.subtotal)
|
|
line.client_portion = line.subtotal - line.adp_portion
|
|
|
|
@api.onchange('product_id')
|
|
def _onchange_product_id(self):
|
|
"""Auto-fill ADP code and pricing from product."""
|
|
if self.product_id:
|
|
tmpl = self.product_id.product_tmpl_id
|
|
self.adp_device_code = tmpl.x_fc_adp_device_code or ''
|
|
self.adp_price = tmpl.x_fc_adp_price or 0.0
|
|
self.unit_price = self.product_id.lst_price
|
|
if not self.product_name:
|
|
self.product_name = self.product_id.display_name
|