feat: separate fusion field service and LTC into standalone modules, update core modules

- fusion_claims: separated field service logic, updated controllers/views
- fusion_tasks: updated task views and map integration
- fusion_authorizer_portal: added page 11 signing, schedule booking, migrations
- fusion_shipping: new standalone shipping module (Canada Post, FedEx, DHL, Purolator)
- fusion_ltc_management: new standalone LTC management module
This commit is contained in:
2026-03-11 16:19:52 +00:00
parent 1f79cdcaaf
commit 431052920e
274 changed files with 52782 additions and 7302 deletions

View File

@@ -15,7 +15,9 @@ _logger = logging.getLogger(__name__)
class SaleOrder(models.Model):
_name = 'sale.order'
_inherit = ['sale.order', 'fusion_claims.adp.posting.schedule.mixin', 'fusion.email.builder.mixin']
_rec_names_search = ['name', 'partner_id.name']
@property
def _rec_names_search(self):
return ['name', 'partner_id.name']
@api.depends('name', 'partner_id.name')
def _compute_display_name(self):
@@ -35,22 +37,6 @@ class SaleOrder(models.Model):
help='True only for ADP or ADP/ODSP sale types',
)
# ==========================================================================
# LTC REPAIR LINK
# ==========================================================================
x_fc_ltc_repair_id = fields.Many2one(
'fusion.ltc.repair',
string='LTC Repair',
tracking=True,
ondelete='set null',
index=True,
)
x_fc_is_ltc_repair_sale = fields.Boolean(
compute='_compute_is_ltc_repair_sale',
store=True,
string='Is LTC Repair Sale',
)
# ==========================================================================
# INVOICE COUNT FIELDS (Separate ADP and Client invoices)
# ==========================================================================
@@ -418,11 +404,6 @@ class SaleOrder(models.Model):
for order in self:
order.x_fc_is_adp_sale = order._is_adp_sale()
@api.depends('x_fc_ltc_repair_id')
def _compute_is_ltc_repair_sale(self):
for order in self:
order.x_fc_is_ltc_repair_sale = bool(order.x_fc_ltc_repair_id)
# ==========================================================================
# SALE TYPE AND CLIENT TYPE FIELDS
# ==========================================================================
@@ -1836,8 +1817,7 @@ class SaleOrder(models.Model):
domain, groupby=groupby, aggregates=aggregates,
having=having, offset=offset, limit=limit, order=order,
)
groupby_list = list(groupby) if not isinstance(groupby, (list, tuple)) else groupby
if groupby_list and groupby_list[0] == 'x_fc_adp_application_status':
if groupby and groupby[0] == 'x_fc_adp_application_status':
status_order = self._STATUS_ORDER
result = sorted(result, key=lambda r: status_order.get(r[0], 999))
return result
@@ -4723,48 +4703,6 @@ class SaleOrder(models.Model):
return invoice
# ==========================================================================
# PORTAL PAYMENT AMOUNT (ADP Client Portion)
# ==========================================================================
def _get_prepayment_required_amount(self):
"""Override to return client portion for ADP orders.
For ADP REG clients, the customer should only prepay their 25%
portion, not the full order amount that includes ADP's 75%.
"""
self.ensure_one()
if self._is_adp_sale() and self.x_fc_client_type == 'REG':
client_portion = self.x_fc_client_portion_total or 0
if client_portion > 0:
return self.currency_id.round(client_portion * self.prepayment_percent)
return super()._get_prepayment_required_amount()
def _has_to_be_paid(self):
"""Override to use client portion for ADP payment threshold check.
Standard Odoo checks amount_total > 0. For ADP orders where
the client type is not REG (100% ADP funded), the customer
has nothing to pay and the quotation should auto-confirm.
"""
self.ensure_one()
if self._is_adp_sale():
client_type = self.x_fc_client_type or ''
if client_type and client_type != 'REG':
return False
if client_type == 'REG':
client_portion = self.x_fc_client_portion_total or 0
if client_portion <= 0:
return False
return (
self.state in ['draft', 'sent']
and not self.is_expired
and self.require_payment
and client_portion > 0
and not self._is_confirmation_amount_reached()
)
return super()._has_to_be_paid()
# ==========================================================================
# OVERRIDE _get_invoiceable_lines TO INCLUDE ALL SECTIONS AND NOTES
# ==========================================================================