82 lines
4.0 KiB
Python
82 lines
4.0 KiB
Python
# -*- coding: utf-8 -*-
|
|
from odoo import models, fields, api, _
|
|
from odoo.exceptions import UserError
|
|
|
|
class GarmentDispatch(models.Model):
|
|
_name = 'garment.dispatch'
|
|
_inherit = ['mail.thread', 'mail.activity.mixin']
|
|
_description = 'Garment Dispatch & Delivery Management'
|
|
_order = 'name desc'
|
|
|
|
name = fields.Char(string='Dispatch Order No', required=True, default=lambda self: _('New'), copy=False, tracking=True)
|
|
customer_id = fields.Many2one('res.partner', string='Buyer / Consignee', required=True, tracking=True)
|
|
sale_order_id = fields.Many2one('sale.order', string='Sales Order Ref', tracking=True)
|
|
production_plan_id = fields.Many2one('garment.production.plan', string='Production Plan Ref', tracking=True)
|
|
company_id = fields.Many2one('res.company', string='Company', default=lambda self: self.env.company)
|
|
|
|
# Dates & Logistics
|
|
date_dispatch = fields.Date(string='Dispatch Date', default=fields.Date.today, tracking=True)
|
|
carrier_name = fields.Char(string='Carrier / Shipping Line')
|
|
bl_awb_no = fields.Char(string='B/L or Air Waybill No', tracking=True)
|
|
container_no = fields.Char(string='Container No (FCL)')
|
|
seal_no = fields.Char(string='Customs Seal No')
|
|
vehicle_no = fields.Char(string='Truck / Vehicle Registration No')
|
|
port_of_loading = fields.Char(string='Port of Loading', default='Tuticorin / Chennai Port')
|
|
port_of_discharge = fields.Char(string='Port of Discharge')
|
|
|
|
# Cartons & Metrics
|
|
carton_ids = fields.One2many('garment.carton', 'dispatch_id', string='Dispatched Cartons')
|
|
total_cartons = fields.Integer(string='Total Cartons', compute='_compute_totals', store=True)
|
|
total_pieces = fields.Integer(string='Total Garments Dispatched', compute='_compute_totals', store=True)
|
|
total_gross_weight = fields.Float(string='Total Gross Weight (Kg)', compute='_compute_totals', store=True)
|
|
total_cbm = fields.Float(string='Total CBM (m³)', compute='_compute_totals', store=True)
|
|
|
|
state = fields.Selection([
|
|
('draft', 'Draft Shipment'),
|
|
('packed', 'Loaded & Ready to Depart'),
|
|
('dispatched', 'Dispatched / In Transit'),
|
|
('delivered', 'Delivered to Customer'),
|
|
('cancelled', 'Cancelled'),
|
|
], string='Status', default='draft', tracking=True, required=True)
|
|
notes = fields.Text(string='Shipping Instructions / Marks & Numbers')
|
|
|
|
@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.dispatch') or _('DISP/%s') % fields.Date.today().strftime('%Y%m%d')
|
|
return super(GarmentDispatch, self).create(vals_list)
|
|
|
|
@api.depends('carton_ids.total_pieces', 'carton_ids.gross_weight_kg', 'carton_ids.cbm')
|
|
def _compute_totals(self):
|
|
for rec in self:
|
|
rec.total_cartons = len(rec.carton_ids)
|
|
rec.total_pieces = sum(rec.carton_ids.mapped('total_pieces'))
|
|
rec.total_gross_weight = round(sum(rec.carton_ids.mapped('gross_weight_kg')), 2)
|
|
rec.total_cbm = round(sum(rec.carton_ids.mapped('cbm')), 3)
|
|
|
|
def action_dispatch(self):
|
|
"""Dispatches the shipment, deducts Finished Goods inventory"""
|
|
self.ensure_one()
|
|
if not self.carton_ids:
|
|
raise UserError(_("Please attach cartons to dispatch."))
|
|
|
|
FG = self.env['garment.finished.goods']
|
|
for ctn in self.carton_ids:
|
|
for line in ctn.line_ids:
|
|
fg = FG.search([
|
|
('style_id', '=', ctn.style_id.id),
|
|
('color_id', '=', line.color_id.id),
|
|
('size_id', '=', line.size_id.id),
|
|
], limit=1)
|
|
if fg:
|
|
fg.write({
|
|
'on_hand_qty': max(0, fg.on_hand_qty - line.quantity),
|
|
'shipped_qty': fg.shipped_qty + line.quantity,
|
|
})
|
|
|
|
self.write({'state': 'dispatched'})
|
|
|
|
def action_mark_delivered(self):
|
|
self.write({'state': 'delivered'})
|