125 lines
6.0 KiB
Python
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')
|