Garment_ERP/addons/garment_erp/models/quality_control.py
2026-09-21 16:43:23 +05:30

125 lines
6.0 KiB
Python

# -*- coding: utf-8 -*-
from odoo import models, fields, api, _
class GarmentDefectType(models.Model):
_name = 'garment.defect.type'
_description = 'Garment Quality Defect Category'
_order = 'category, name'
name = fields.Char(string='Defect Name', required=True)
code = fields.Char(string='Defect Code', required=True)
category = fields.Selection([
('stitching', 'Stitching / Sewing Defect'),
('fabric', 'Fabric / Yarn Flaw'),
('measurement', 'Measurement / Spec Variance'),
('print_embroidery', 'Print / Embroidery Defect'),
('finishing_packing', 'Finishing / Staining / Packing'),
], string='Category', default='stitching', required=True)
severity = fields.Selection([
('minor', 'Minor Defect'),
('major', 'Major Defect'),
('critical', 'Critical (Must Reject)'),
], string='Defect Severity', default='major')
active = fields.Boolean(default=True)
class GarmentQualityInspection(models.Model):
_name = 'garment.quality.inspection'
_inherit = ['mail.thread', 'mail.activity.mixin']
_description = 'Garment Quality Control Inspection'
_order = 'name desc'
name = fields.Char(string='Inspection Number', required=True, default=lambda self: _('New'), copy=False, tracking=True)
inspection_stage = fields.Selection([
('fabric', '1. Fabric Inspection'),
('cutting', '2. Cutting Section QC'),
('sewing_inline', '3. Sewing Inline Roaming QC'),
('sewing_endline', '4. Sewing Endline 100% Checking'),
('jobwork', '5. Job Work Inward QC'),
('final_aql', '6. Final AQL 2.5 Pre-Shipment Audit'),
], string='Inspection Stage', default='sewing_endline', required=True, tracking=True)
production_plan_id = fields.Many2one('garment.production.plan', string='Production Order', tracking=True)
style_id = fields.Many2one('garment.style', string='Garment Style', tracking=True)
color_id = fields.Many2one('garment.color', string='Color')
size_id = fields.Many2one('garment.size', string='Size')
bundle_id = fields.Many2one('garment.bundle', string='Bundle Ref')
sewing_line_id = fields.Many2one('garment.sewing.line', string='Sewing Line')
inspector_id = fields.Many2one('res.users', string='QA Inspector', default=lambda self: self.env.user, tracking=True)
date_inspected = fields.Date(string='Inspection Date', default=fields.Date.today, tracking=True)
# Quantities & AQL
total_lot_qty = fields.Integer(string='Lot / Batch Quantity', default=100)
sample_size = fields.Integer(string='Sample Quantity Checked', default=20, required=True)
passed_qty = fields.Integer(string='Passed Quantity', default=0, tracking=True)
failed_qty = fields.Integer(string='Defective Quantity', default=0, tracking=True)
rework_qty = fields.Integer(string='Sent for Rework', default=0)
scrapped_qty = fields.Integer(string='Permanently Scrapped', default=0)
defect_line_ids = fields.One2many('garment.quality.defect.line', 'inspection_id', string='Defect Details')
verdict = fields.Selection([
('passed', 'Quality Approved (Pass)'),
('rework_needed', 'Rework Required'),
('rejected', 'Completely Rejected / Scrapped'),
], string='Final Verdict', default='passed', tracking=True, required=True)
rework_order_ids = fields.One2many('garment.rework.order', 'inspection_id', string='Linked Rework Orders')
rework_count = fields.Integer(string='Rework Orders', compute='_compute_rework_count')
remarks = fields.Text(string='Inspector Notes')
@api.model_create_multi
def create(self, vals_list):
for vals in vals_list:
if vals.get('name', _('New')) == _('New'):
vals['name'] = self.env['ir.sequence'].next_by_code('garment.quality.inspection') or _('QC/%s') % fields.Date.today().strftime('%Y%m%d')
return super(GarmentQualityInspection, self).create(vals_list)
@api.depends('rework_order_ids')
def _compute_rework_count(self):
for rec in self:
rec.rework_count = len(rec.rework_order_ids)
def action_pass(self):
self.write({'verdict': 'passed'})
def action_trigger_rework(self):
"""Creates an automatic Rework Order for failed pieces"""
self.ensure_one()
rework_qty = self.rework_qty or self.failed_qty or 1
rework = self.env['garment.rework.order'].create({
'inspection_id': self.id,
'production_plan_id': self.production_plan_id.id if self.production_plan_id else False,
'style_id': self.style_id.id if self.style_id else False,
'color_id': self.color_id.id if self.color_id else False,
'size_id': self.size_id.id if self.size_id else False,
'bundle_id': self.bundle_id.id if self.bundle_id else False,
'rework_qty': rework_qty,
'defect_description': self.remarks or 'Defects identified during quality inspection',
'assigned_dept': 'sewing',
})
self.write({'verdict': 'rework_needed', 'rework_qty': rework_qty})
return {
'name': _('Rework Order'),
'type': 'ir.actions.act_window',
'res_model': 'garment.rework.order',
'res_id': rework.id,
'view_mode': 'form',
}
class GarmentQualityDefectLine(models.Model):
_name = 'garment.quality.defect.line'
_description = 'Quality Defect Occurrence Line'
inspection_id = fields.Many2one('garment.quality.inspection', string='Inspection', required=True, ondelete='cascade')
defect_type_id = fields.Many2one('garment.defect.type', string='Defect Type', required=True)
category = fields.Selection(related='defect_type_id.category', readonly=True)
defect_count = fields.Integer(string='Defect Count', default=1, required=True)
action_type = fields.Selection([
('rework', 'Alteration / Rework'),
('scrap', 'Permanent Rejection / Scrap'),
], string='Action Required', default='rework')
notes = fields.Char(string='Defect Location / Remarks')