Garment_ERP/addons/garment_erp/models/garment_dashboard.py

91 lines
5.5 KiB
Python

# -*- coding: utf-8 -*-
from odoo import models, fields, api, _
class GarmentDashboard(models.Model):
_name = 'garment.dashboard'
_description = 'Garment Manufacturing Real-Time KPI Dashboard'
name = fields.Char(string='Dashboard', default='Tiruppur Factory Control Room')
# Executive KPIs
total_sales_orders = fields.Integer(string='Active Garment Orders', compute='_compute_kpis')
total_ordered_pieces = fields.Integer(string='Total Booked Pieces', compute='_compute_kpis')
active_production_plans = fields.Integer(string='Production Orders in Progress', compute='_compute_kpis')
avg_production_progress = fields.Float(string='Average Production Progress %', compute='_compute_kpis')
# Shop Floor & Sewing KPIs
total_sewing_lines = fields.Integer(string='Active Sewing Lines', compute='_compute_kpis')
today_target_pieces = fields.Integer(string="Today's Sewing Target", compute='_compute_kpis')
today_actual_pieces = fields.Integer(string="Today's Actual Output", compute='_compute_kpis')
avg_line_efficiency = fields.Float(string='Factory Efficiency %', compute='_compute_kpis')
today_defects = fields.Integer(string="Today's Alteration Count", compute='_compute_kpis')
# Material & Inventory KPIs
total_fabric_stock_kg = fields.Float(string='Fabric Rolls in Stock (Kg)', compute='_compute_kpis')
total_approved_rolls = fields.Integer(string='QC Approved Rolls', compute='_compute_kpis')
total_finished_goods_pcs = fields.Integer(string='Finished Goods Stock (Pcs)', compute='_compute_kpis')
# Operations & Subcontracting
pending_jobwork_dc = fields.Integer(string='Pending Job Work Challans', compute='_compute_kpis')
pending_quality_inspections = fields.Integer(string='Pending Quality Inspections', compute='_compute_kpis')
active_rework_orders = fields.Integer(string='Open Rework Orders', compute='_compute_kpis')
pending_dispatch_cartons = fields.Integer(string='Cartons Ready for Dispatch', compute='_compute_kpis')
# Extra Telemetry
total_styles_count = fields.Integer(string='Active Styles', compute='_compute_kpis')
total_cutting_orders = fields.Integer(string='Active Cutting Orders', compute='_compute_kpis')
total_bundles_active = fields.Integer(string='Active Bundles in Floor', compute='_compute_kpis')
output_achievement_pct = fields.Float(string='Daily Target Achievement %', compute='_compute_kpis')
def _compute_kpis(self):
for rec in self:
# Sales
orders = self.env['sale.order'].search([('is_garment_order', '=', True), ('state', 'in', ['sale', 'done'])])
rec.total_sales_orders = len(orders)
rec.total_ordered_pieces = sum(orders.mapped('total_garment_qty'))
# Styles
rec.total_styles_count = self.env['garment.style'].search_count([('active', '=', True)])
# Production
plans = self.env['garment.production.plan'].search([('state', 'in', ['planned', 'in_progress'])])
rec.active_production_plans = len(plans)
rec.avg_production_progress = round(sum(plans.mapped('progress_pct')) / (len(plans) or 1), 1)
# Cutting & Bundles
rec.total_cutting_orders = self.env['garment.cutting.plan'].search_count([('state', 'in', ['draft', 'planned', 'cutting'])])
rec.total_bundles_active = self.env['garment.bundle'].search_count([('stage', 'not in', ['completed'])])
# Sewing Lines & Today's Hourly
lines = self.env['garment.sewing.line'].search([('active', '=', True)])
rec.total_sewing_lines = len(lines)
today_logs = self.env['garment.sewing.hourly'].search([('date', '=', fields.Date.today())])
rec.today_target_pieces = sum(today_logs.mapped('total_target'))
rec.today_actual_pieces = sum(today_logs.mapped('total_actual'))
rec.today_defects = sum(today_logs.mapped('total_defects'))
if today_logs:
rec.avg_line_efficiency = round(sum(today_logs.mapped('efficiency_pct')) / len(today_logs), 1)
else:
rec.avg_line_efficiency = 0.0
if rec.today_target_pieces > 0:
rec.output_achievement_pct = min(100.0, round((rec.today_actual_pieces / rec.today_target_pieces) * 100.0, 1))
else:
rec.output_achievement_pct = 0.0
# Fabric & FG
rolls = self.env['garment.fabric.roll'].search([('status', 'in', ['received', 'inspected', 'approved', 'issued'])])
rec.total_fabric_stock_kg = round(sum(rolls.mapped('remaining_weight')), 1)
rec.total_approved_rolls = self.env['garment.fabric.roll'].search_count([('status', '=', 'approved')])
fg = self.env['garment.finished.goods'].search([])
rec.total_finished_goods_pcs = sum(fg.mapped('on_hand_qty'))
# Job Work & QC
rec.pending_jobwork_dc = self.env['garment.jobwork.order'].search_count([('state', 'in', ['sent', 'partial'])])
rec.pending_quality_inspections = self.env['garment.quality.inspection'].search_count([('verdict', '=', 'rework_needed')])
rec.active_rework_orders = self.env['garment.rework.order'].search_count([('state', 'in', ['assigned', 'in_rework', 'ready_recheck'])])
# Packing
rec.pending_dispatch_cartons = self.env['garment.carton'].search_count([('dispatch_id', '=', False)])