folder rename

This commit is contained in:
gsinghpal
2026-04-16 20:53:53 -04:00
parent 3f3ddcbab4
commit 7c7ef06057
634 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright 2026 Nexa Systems Inc.
# License OPL-1 (Odoo Proprietary License v1.0)
# Part of the Fusion Plating product family.
from . import report_wo_margin

View File

@@ -0,0 +1,165 @@
# -*- coding: utf-8 -*-
# Copyright 2026 Nexa Systems Inc.
# License OPL-1 (Odoo Proprietary License v1.0)
# Part of the Fusion Plating product family.
from odoo import api, models
class ReportWoMargin(models.AbstractModel):
"""Work Order Margin Report Data.
Computes cost, revenue, and margin breakdowns for manufacturing orders
so the QWeb template can render a Steelhead-style margin report.
"""
_name = 'report.fusion_plating_reports.report_wo_margin'
_description = 'WO Margin Report Data'
# ------------------------------------------------------------------
# helpers
# ------------------------------------------------------------------
def _get_station_costs(self, mo):
"""Return a list of dicts with per-station cost breakdown."""
station_costs = []
for wo in mo.workorder_ids:
wc = wo.workcenter_id
labour_rate = wc.costs_hour if wc else 0.0
# Sum tracked time from productivity records (minutes)
time_minutes = sum(wo.time_ids.mapped('duration'))
time_hours = time_minutes / 60.0
labour_cost = time_hours * labour_rate
# Operation cost uses the same rate & dwell for now
operation_rate = labour_rate
dwell_minutes = time_minutes
dwell_hours = dwell_minutes / 60.0
operation_cost = dwell_hours * operation_rate
total = labour_cost + operation_cost
station_costs.append({
'station': wc.name if wc else 'Unknown',
'labour_rate': labour_rate,
'labour_time': time_minutes,
'labour_hours': time_hours,
'labour_cost': labour_cost,
'operation_rate': operation_rate,
'dwell_time': dwell_minutes,
'dwell_hours': dwell_hours,
'operation_cost': operation_cost,
'total_cost': total,
})
return station_costs
def _get_part_margins(self, mo, revenue):
"""Return margin breakdown per unique product (part number)."""
parts = {}
for wo in mo.workorder_ids:
product = wo.product_id or mo.product_id
key = product.id
if key not in parts:
parts[key] = {
'product': product,
'part_number': product.default_code or product.name,
'count': 0,
'labour_cost': 0.0,
'station_labour_cost': 0.0,
'station_operation_cost': 0.0,
'outsourcing_cost': 0.0,
}
entry = parts[key]
entry['count'] += 1
time_hours = sum(wo.time_ids.mapped('duration')) / 60.0
rate = wo.workcenter_id.costs_hour if wo.workcenter_id else 0.0
cost = time_hours * rate
entry['labour_cost'] += cost
entry['station_labour_cost'] += cost
entry['station_operation_cost'] += cost
# Distribute revenue equally across parts for per-part metrics
part_list = list(parts.values())
total_parts = sum(p['count'] for p in part_list) or 1
for p in part_list:
p['so_total'] = revenue * (p['count'] / total_parts)
p['so_per_part'] = p['so_total'] / p['count'] if p['count'] else 0
p['unit_labour'] = p['labour_cost'] / p['count'] if p['count'] else 0
total_cost = (
p['labour_cost'] + p['station_labour_cost']
+ p['station_operation_cost'] + p['outsourcing_cost']
)
p['margin_pct'] = (
(p['so_total'] - total_cost) / p['so_total'] * 100
) if p['so_total'] else 0
return part_list
# ------------------------------------------------------------------
# Report entry point
# ------------------------------------------------------------------
@api.model
def _get_report_values(self, docids, data=None):
productions = self.env['mrp.production'].browse(docids)
docs = []
for mo in productions:
# Revenue from linked sale order
revenue = 0.0
if hasattr(mo, 'sale_order_id') and mo.sale_order_id:
revenue = sum(
mo.sale_order_id.order_line.mapped('price_subtotal')
)
# Station costs
station_costs = self._get_station_costs(mo)
part_labour_cost = sum(s['labour_cost'] for s in station_costs)
station_labour_cost = part_labour_cost # same pool
station_operation_cost = sum(
s['operation_cost'] for s in station_costs
)
# Inventory cost (raw materials)
inventory_cost = sum(
m.product_id.standard_price * m.quantity
for m in mo.move_raw_ids
)
# Outsourcing cost placeholder
outsourcing_cost = 0.0
total_cost = (
part_labour_cost + station_labour_cost
+ station_operation_cost + inventory_cost
+ outsourcing_cost
)
gross_profit = revenue - total_cost
margin_pct = (
(gross_profit / revenue * 100) if revenue else 0.0
)
# Station cost percentages
total_station_cost = sum(s['total_cost'] for s in station_costs)
for s in station_costs:
s['percentage'] = (
(s['total_cost'] / total_station_cost * 100)
if total_station_cost else 0
)
# Part margins
part_margins = self._get_part_margins(mo, revenue)
docs.append({
'mo': mo,
'revenue': revenue,
'part_labour_cost': part_labour_cost,
'station_labour_cost': station_labour_cost,
'station_operation_cost': station_operation_cost,
'inventory_cost': inventory_cost,
'outsourcing_cost': outsourcing_cost,
'total_cost': total_cost,
'gross_profit': gross_profit,
'margin_pct': margin_pct,
'station_costs': station_costs,
'part_margins': part_margins,
})
return {
'doc_ids': docids,
'docs': docs,
}