diff options
| author | it-fixcomart <it@fixcomart.co.id> | 2025-03-10 09:53:52 +0700 |
|---|---|---|
| committer | it-fixcomart <it@fixcomart.co.id> | 2025-03-10 09:53:52 +0700 |
| commit | 07de307dde57f475c59e8bb01ee065f6f9ba48df (patch) | |
| tree | 8e6be546a1efaea314457172f2511e4506c2487a /indoteknik_custom/models/sale_order.py | |
| parent | 92b1ec69af1fb5b062307c7c7a00c3e0fb0e9e01 (diff) | |
| parent | efdf162216dceff9b456b967d6ccd38da56fd1d5 (diff) | |
Merge branch 'odoo-backup' into CR/renca-tempo
Diffstat (limited to 'indoteknik_custom/models/sale_order.py')
| -rwxr-xr-x | indoteknik_custom/models/sale_order.py | 152 |
1 files changed, 138 insertions, 14 deletions
diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py index 8a983479..aee19ec7 100755 --- a/indoteknik_custom/models/sale_order.py +++ b/indoteknik_custom/models/sale_order.py @@ -137,11 +137,13 @@ class SaleOrder(models.Model): applied_voucher_shipping_id = fields.Many2one(comodel_name='voucher', string='Applied Voucher', copy=False) amount_voucher_shipping_disc = fields.Float(string='Voucher Discount') source_id = fields.Many2one('utm.source', 'Source', domain="[('id', 'in', [32, 59, 60, 61])]", required=True) - estimated_arrival_days = fields.Integer('Estimated Arrival Days', default=0) + estimated_arrival_days = fields.Integer('Estimated Arrival To', default=0) + estimated_arrival_days_start = fields.Integer('Estimated Arrival From', default=0) email = fields.Char(string='Email') picking_iu_id = fields.Many2one('stock.picking', 'Picking IU') helper_by_id = fields.Many2one('res.users', 'Helper By') - eta_date = fields.Datetime(string='ETA Date', copy=False, compute='_compute_eta_date') + eta_date_start = fields.Datetime(string='ETA Date start', copy=False, compute='_compute_eta_date') + eta_date = fields.Datetime(string='ETA Date end', copy=False, compute='_compute_eta_date') flash_sale = fields.Boolean(string='Flash Sale', help='Data dari web') is_continue_transaction = fields.Boolean(string='Button Transaction', help='Data dari web') web_approval = fields.Selection([ @@ -188,7 +190,17 @@ class SaleOrder(models.Model): ('PNR', 'Pareto Non Repeating'), ('NP', 'Non Pareto') ]) + estimated_ready_ship_date = fields.Datetime( + string='ET Ready to Ship compute', + compute='_compute_etrts_date' + ) + expected_ready_to_ship = fields.Datetime( + string='ET Ready to Ship', + copy=False, + store=True + ) shipping_method_picking = fields.Char(string='Shipping Method Picking', compute='_compute_shipping_method_picking') + reason_cancel = fields.Selection([ ('harga_terlalu_mahal', 'Harga barang terlalu mahal'), ('harga_web_tidak_valid', 'Harga web tidak valid'), @@ -202,6 +214,7 @@ class SaleOrder(models.Model): ('dokumen_tidak_support', 'Indoteknik tidak bisa support document yang dibutuhkan (Ex: TKDN, COO, SNI)'), ('ganti_quotation', 'Ganti Quotation'), ('testing_internal', 'Testing Internal'), + ('revisi_data', 'Revisi Data'), ], string='Reason for Cancel', copy=False, index=True, tracking=3) attachment_bukti = fields.Many2one( 'ir.attachment', @@ -435,19 +448,125 @@ class SaleOrder(models.Model): rec.compute_fullfillment = True + @api.depends('date_order', 'estimated_arrival_days', 'state', 'estimated_arrival_days_start') def _compute_eta_date(self): - max_leadtime = 0 + for rec in self: + if rec.date_order and rec.state not in ['cancel'] and rec.estimated_arrival_days and rec.estimated_arrival_days_start: + rec.eta_date = rec.date_order + timedelta(days=rec.estimated_arrival_days) + rec.eta_date_start = rec.date_order + timedelta(days=rec.estimated_arrival_days_start) + else: + rec.eta_date = False + rec.eta_date_start = False + + + def get_days_until_next_business_day(self,start_date=None, *args, **kwargs): + today = start_date or datetime.today().date() + offset = 0 # Counter jumlah hari yang ditambahkan + holiday = self.env['hr.public.holiday'] + + while True : + today += timedelta(days=1) + offset += 1 + + if today.weekday() >= 5: + continue - for line in self.order_line: - leadtime = line.vendor_id.leadtime - max_leadtime = max(max_leadtime, leadtime) + is_holiday = holiday.search([("start_date", "=", today)]) + if is_holiday: + continue + + break + return offset + + # def calculate_sla_by_vendor(self, products): + # slatime = 15 + # for line in products: + # product_sla = self.env['product.sla'].search([('product_variant_id', '=', line.product_id.id)], limit=1) + # slatime = int(product_sla.sla) if product_sla and product_sla.sla and product_sla.sla != 'Indent' and "hari" in product_sla.sla.lower() else 15 + + # return { + # 'slatime' : slatime + # } + + def calculate_sla_by_vendor(self, products): + product_ids = products.mapped('product_id.id') # Kumpulkan semua ID produk + include_instant = True # Default True, tetapi bisa menjadi False + + # Cek apakah SEMUA produk memiliki qty_free_bandengan >= qty_needed + all_fast_products = all(product.product_id.qty_free_bandengan >= product.product_uom_qty for product in products) + if all_fast_products: + return {'slatime': 1, 'include_instant': include_instant} + + + # Cari semua vendor pemenang untuk produk yang diberikan + vendors = self.env['purchase.pricelist'].search([ + ('product_id', 'in', product_ids), + ('is_winner', '=', True) + ]) + + max_slatime = 1 + + for vendor in vendors: + vendor_sla = self.env['vendor.sla'].search([('id_vendor', '=', vendor.vendor_id.id)], limit=1) + slatime = 15 + if vendor_sla: + if vendor_sla.unit == 'hari': + vendor_duration = vendor_sla.duration * 24 * 60 + else : + vendor_duration = vendor_sla.duration * 60 + include_instant = True + + estimation_sla = (1 * 24 * 60) + vendor_duration + estimation_sla_days = estimation_sla / (24 * 60) + slatime = math.ceil(estimation_sla_days) + + max_slatime = max(max_slatime, slatime) + + return {'slatime': max_slatime, 'include_instant': include_instant} + + @api.depends("order_line.product_id") + def _compute_etrts_date(self): #Function to calculate Estimated Ready To Ship Date for rec in self: - if rec.date_order and rec.state not in ['cancel', 'draft']: - eta_date = datetime.now() + timedelta(days=max_leadtime) - rec.eta_date = eta_date - else: - rec.eta_date = False + max_slatime = 1 # Default SLA jika tidak ada + slatime = self.calculate_sla_by_vendor(rec.order_line) + max_slatime = max(max_slatime, slatime['slatime']) + + if rec.date_order: + sum_days = max_slatime + self.get_days_until_next_business_day(rec.date_order) - 1 + if not rec.estimated_arrival_days: + rec.estimated_arrival_days = sum_days + + eta_date = rec.date_order + timedelta(days=sum_days) + rec.estimated_ready_ship_date = eta_date + rec.commitment_date = eta_date + # Jika expected_ready_to_ship kosong, set nilai default + if not rec.expected_ready_to_ship: + rec.expected_ready_to_ship = eta_date + + + + @api.onchange('expected_ready_to_ship') #Hangle Onchange form Expected Ready to Ship + def _onchange_expected_ready_ship_date(self): + for rec in self: + if rec.expected_ready_to_ship and rec.estimated_ready_ship_date: + # Hanya membandingkan tanggal saja, tanpa jam + expected_date = rec.expected_ready_to_ship.date() + estimated_date = rec.estimated_ready_ship_date.date() + + if expected_date < estimated_date: + rec.expected_ready_to_ship = rec.estimated_ready_ship_date + rec.commitment_date = rec.estimated_ready_ship_date + raise ValidationError( + "Tanggal 'Expected Ready to Ship' tidak boleh lebih kecil dari {}. Mohon pilih tanggal minimal {}." + .format(estimated_date.strftime('%d-%m-%Y'), estimated_date.strftime('%d-%m-%Y')) + ) + + def _set_etrts_date(self): + for order in self: + if order.state in ('done', 'cancel', 'sale'): + raise UserError(_("You cannot change the Estimated Ready To Ship Date on a done, sale or cancelled order.")) + # order.move_lines.write({'estimated_ready_ship_date': order.estimated_ready_ship_date}) def _prepare_invoice(self): """ @@ -642,15 +761,16 @@ class SaleOrder(models.Model): if line.product_id.type == 'product': line_no += 1 line.line_no = line_no + def write(self, vals): res = super(SaleOrder, self).write(vals) - + # self._compute_etrts_date() if 'carrier_id' in vals: for picking in self.picking_ids: if picking.state == 'assigned': picking.carrier_id = self.carrier_id - + return res def calculate_so_status(self): @@ -1108,6 +1228,7 @@ class SaleOrder(models.Model): order._set_sppkp_npwp_contact() order.calculate_line_no() order.send_notif_to_salesperson() + order._compute_etrts_date() # order.order_line.get_reserved_from() res = super(SaleOrder, self).action_confirm() @@ -1503,13 +1624,14 @@ class SaleOrder(models.Model): def create(self, vals): # Ensure partner details are updated when a sale order is created order = super(SaleOrder, self).create(vals) + order._compute_etrts_date() # order._update_partner_details() return order def write(self, vals): # Call the super method to handle the write operation res = super(SaleOrder, self).write(vals) - + # self._compute_etrts_date() # Check if the update is coming from a save operation # if any(field in vals for field in ['sppkp', 'npwp', 'email', 'customer_type']): # self._update_partner_details() @@ -1544,4 +1666,6 @@ class SaleOrder(models.Model): raise UserError( "SO tidak dapat ditambahkan produk baru karena SO sudah menjadi sale order.") res = super(SaleOrder, self).write(vals) + if 'order_line' in vals: + self._compute_etrts_date() return res
\ No newline at end of file |
