summaryrefslogtreecommitdiff
path: root/indoteknik_custom/models/sale_order.py
diff options
context:
space:
mode:
authorit-fixcomart <it@fixcomart.co.id>2025-03-10 09:53:52 +0700
committerit-fixcomart <it@fixcomart.co.id>2025-03-10 09:53:52 +0700
commit07de307dde57f475c59e8bb01ee065f6f9ba48df (patch)
tree8e6be546a1efaea314457172f2511e4506c2487a /indoteknik_custom/models/sale_order.py
parent92b1ec69af1fb5b062307c7c7a00c3e0fb0e9e01 (diff)
parentefdf162216dceff9b456b967d6ccd38da56fd1d5 (diff)
Merge branch 'odoo-backup' into CR/renca-tempo
Diffstat (limited to 'indoteknik_custom/models/sale_order.py')
-rwxr-xr-xindoteknik_custom/models/sale_order.py152
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