summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indoteknik_api/controllers/api_v1/product.py96
-rw-r--r--indoteknik_api/controllers/api_v1/sale_order.py2
-rwxr-xr-xindoteknik_custom/models/sale_order.py105
-rw-r--r--indoteknik_custom/models/stock_picking.py17
4 files changed, 120 insertions, 100 deletions
diff --git a/indoteknik_api/controllers/api_v1/product.py b/indoteknik_api/controllers/api_v1/product.py
index 557215ea..a88c3368 100644
--- a/indoteknik_api/controllers/api_v1/product.py
+++ b/indoteknik_api/controllers/api_v1/product.py
@@ -34,60 +34,66 @@ class Product(controller.Controller):
categories.reverse()
return self.response(categories, headers=[('Cache-Control', 'max-age=3600, public')])
- @http.route(prefix + 'product/variants/sla', auth='public', methods=['GET', 'OPTIONS'])
+ @http.route(prefix + 'product/variants/sla', auth='public', methods=['POST', 'OPTIONS'] , csrf=False)
@controller.Controller.must_authorized()
def get_product_template_sla_by_id(self, **kwargs):
- body_params = kwargs.get('ids')
- if not body_params:
- return self.response('Failed', code=400, description='id is required')
+ raw_data = kwargs.get('products', '[]')
+ product_data = json.loads(raw_data)
- ids = [int(id.strip()) for id in body_params.split(',') if id.strip().isdigit()]
-
- sla_duration = 0
- sla_unit = 'Hari'
- include_instant = True
- products = request.env['product.product'].search([('id', 'in', ids)])
- if len(products) < 1:
- return self.response(
- 'Failed',
- code=400,
- description='Produk Tidak Di Temukan.'
- )
+ product_ids = [int(item["id"]) for item in product_data]
+ products = request.env['purchase.pricelist'].search([
+ ('product_id', 'in', product_ids),
+ ('is_winner', '=', True)
+ ])
- product_slas = request.env['product.sla'].search([('product_variant_id', 'in', ids)])
- if len(product_slas) < 1:
- return self.response(
- 'Failed',
- code=400,
- description='SLA Tidak Di Temukan.'
- )
-
- # Mapping SLA untuk mempermudah lookup
- sla_map = {sla.product_variant_id.id: sla for sla in product_slas}
-
- for product in products:
- product_sla = sla_map.get(product.id)
- if product_sla:
- sla_duration = max(sla_duration, int(product_sla.sla))
- sla_unit = product_sla.sla_vendor_id.unit
- if product.qty_free_bandengan < 1 :
- if product_sla.sla_vendor_id.unit != 'jam':
- include_instant = False
- break
-
start_date = datetime.today().date()
additional_days = request.env['sale.order'].get_days_until_next_business_day(start_date)
+ include_instant = True
+
+ if(len(products) != len(product_ids)):
+ products_data_params = {product["id"] : product for product in product_data }
+
+ all_fast_products = all(
+ product.product_id.qty_free_bandengan >= products_data_params.get(product.product_id.id, {}).get("quantity", 0)
+ for product in products
+ )
- # Jika semua loop selesai tanpa include_instant menjadi False
+ if all_fast_products:
+ return self.response({
+ 'include_instant': include_instant,
+ 'sla_duration': 1,
+ 'sla_additional_days': additional_days,
+ 'sla_total' : int(1) + int(additional_days),
+ 'sla_unit': 'Hari'
+ })
+
+ max_slatime = 1
+
+ for vendor in products:
+ vendor_sla = request.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
+ include_instant = False
+ 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 self.response({
- 'include_instant': include_instant,
- 'sla_duration': sla_duration,
- 'sla_additional_days': additional_days,
- 'sla_total' : int(sla_duration) + int(additional_days),
- 'sla_unit': 'Hari' if additional_days > 0 else sla_unit
- }
- )
+ 'include_instant': include_instant,
+ 'sla_duration': max_slatime,
+ 'sla_additional_days': additional_days,
+ 'sla_total' : int(max_slatime) + int(additional_days),
+ 'sla_unit': 'Hari'
+ })
@http.route(prefix + 'product_variant/<id>/stock', auth='public', methods=['GET', 'OPTIONS'])
@controller.Controller.must_authorized()
diff --git a/indoteknik_api/controllers/api_v1/sale_order.py b/indoteknik_api/controllers/api_v1/sale_order.py
index 6815bf6c..98b13cad 100644
--- a/indoteknik_api/controllers/api_v1/sale_order.py
+++ b/indoteknik_api/controllers/api_v1/sale_order.py
@@ -466,6 +466,8 @@ class SaleOrder(controller.Controller):
'program_line_id': cart['id'],
'quantity': cart['quantity']
})
+
+ sale_order._compute_etrts_date()
request.env['sale.order.promotion'].create(promotions)
diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py
index 67434105..b17df045 100755
--- a/indoteknik_custom/models/sale_order.py
+++ b/indoteknik_custom/models/sale_order.py
@@ -202,10 +202,10 @@ 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'
- )
+ # 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
@@ -480,10 +480,11 @@ class SaleOrder(models.Model):
@api.depends('date_order', 'estimated_arrival_days', 'state', 'estimated_arrival_days_start')
def _compute_eta_date(self):
+ current_date = datetime.now().date()
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)
+ rec.eta_date = current_date + timedelta(days=rec.estimated_arrival_days)
+ rec.eta_date_start = current_date + timedelta(days=rec.estimated_arrival_days_start)
else:
rec.eta_date = False
rec.eta_date_start = False
@@ -508,16 +509,6 @@ class SaleOrder(models.Model):
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
@@ -528,7 +519,6 @@ class SaleOrder(models.Model):
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),
@@ -555,43 +545,58 @@ class SaleOrder(models.Model):
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
+
+ def _calculate_etrts_date(self):
for rec in self:
+ if not rec.date_order:
+ rec.expected_ready_to_ship = False
+ return
+
+ current_date = datetime.now().date()
+
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):
+ sum_days = max_slatime + self.get_days_until_next_business_day(current_date) - 1
+ if not rec.estimated_arrival_days:
+ rec.estimated_arrival_days = sum_days
+
+ eta_date = current_date + timedelta(days=sum_days)
+ rec.commitment_date = eta_date
+ rec.expected_ready_to_ship = eta_date
+
+ @api.depends("order_line.product_id", "date_order")
+ def _compute_etrts_date(self): #Function to calculate Estimated Ready To Ship Date
+ self._calculate_etrts_date()
+
+
+ def _validate_expected_ready_ship_date(self):
for rec in self:
- if rec.expected_ready_to_ship and rec.estimated_ready_ship_date:
+ if rec.expected_ready_to_ship and rec.commitment_date:
+ current_date = datetime.now().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
+ max_slatime = 1 # Default SLA jika tidak ada
+ slatime = self.calculate_sla_by_vendor(rec.order_line)
+ max_slatime = max(max_slatime, slatime['slatime'])
+ sum_days = max_slatime + self.get_days_until_next_business_day(current_date) - 1
+ eta_minimum = current_date + timedelta(days=sum_days)
+
+ if expected_date < eta_minimum:
+ rec.expected_ready_to_ship = eta_minimum
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'))
+ .format(eta_minimum.strftime('%d-%m-%Y'), eta_minimum.strftime('%d-%m-%Y'))
)
+ else:
+ rec.commitment_date = rec.expected_ready_to_ship
+
+
+ @api.onchange('expected_ready_to_ship') #Hangle Onchange form Expected Ready to Ship
+ def _onchange_expected_ready_ship_date(self):
+ self._validate_expected_ready_ship_date()
def _set_etrts_date(self):
for order in self:
@@ -795,14 +800,10 @@ class SaleOrder(models.Model):
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):
so_state = ['sale']
@@ -1670,18 +1671,19 @@ class SaleOrder(models.Model):
# Ensure partner details are updated when a sale order is created
order = super(SaleOrder, self).create(vals)
order._compute_etrts_date()
+ order._validate_expected_ready_ship_date()
# order._update_partner_details()
return order
- def write(self, vals):
+ # def write(self, vals):
# Call the super method to handle the write operation
- res = super(SaleOrder, self).write(vals)
+ # 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()
- return res
+ # return res
def _update_partner_details(self):
for order in self:
@@ -1710,7 +1712,8 @@ class SaleOrder(models.Model):
if command[0] == 0: # A new line is being added
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()
+ if any(field in vals for field in ["order_line", "client_order_ref"]):
+ self._calculate_etrts_date()
return res \ No newline at end of file
diff --git a/indoteknik_custom/models/stock_picking.py b/indoteknik_custom/models/stock_picking.py
index 41f2e138..9e5fca66 100644
--- a/indoteknik_custom/models/stock_picking.py
+++ b/indoteknik_custom/models/stock_picking.py
@@ -13,11 +13,11 @@ import requests
import time
import logging
import re
-from deep_translator import GoogleTranslator
_logger = logging.getLogger(__name__)
_biteship_url = "https://api.biteship.com/v1"
-_biteship_api_key = "biteship_live.eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiaW5kb3Rla25payIsInVzZXJJZCI6IjY3MTViYTJkYzVkMjdkMDAxMjRjODk2MiIsImlhdCI6MTc0MTE1NTU4M30.pbFCai9QJv8iWhgdosf8ScVmEeP3e5blrn33CHe7Hgo"
+_biteship_api_key = "biteship_test.eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSW5kb3Rla25payIsInVzZXJJZCI6IjY3MTViYTJkYzVkMjdkMDAxMjRjODk2MiIsImlhdCI6MTcyOTQ5ODAwMX0.L6C73couP4-cgVEfhKI2g7eMCMo3YOFSRZhS-KSuHNA"
+# _biteship_api_key = "biteship_live.eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiaW5kb3Rla25payIsInVzZXJJZCI6IjY3MTViYTJkYzVkMjdkMDAxMjRjODk2MiIsImlhdCI6MTc0MTE1NTU4M30.pbFCai9QJv8iWhgdosf8ScVmEeP3e5blrn33CHe7Hgo"
@@ -502,8 +502,18 @@ class StockPicking(models.Model):
self.biteship_tracking_id = data.get("courier", {}).get("tracking_id", "")
self.biteship_waybill_id = data.get("courier", {}).get("waybill_id", "")
self.delivery_tracking_no = data.get("courier", {}).get("waybill_id", "")
+
+ waybill_id = data.get("courier", {}).get("waybill_id", "")
+
+ message = f"✅ Berhasil Order ke Biteship! Resi: {waybill_id}" if waybill_id else "⚠️ Order berhasil, tetapi tidak ada nomor resi."
- return data
+ return {
+ 'effect': {
+ 'fadeout': 'slow', # Efek menghilang perlahan
+ 'message': message, # Pesan sukses
+ 'type': 'rainbow_man', # Efek animasi lucu Odoo
+ }
+ }
else:
error_data = response.json()
error_message = error_data.get("error", "Unknown error")
@@ -1244,7 +1254,6 @@ class StockPicking(models.Model):
manifests.append({
"status": re.sub(r'[^a-zA-Z0-9\s]', ' ', entry["status"]).lower().capitalize(),
"datetime": self._convert_to_local_time(entry["updated_at"]),
- # "description": GoogleTranslator(source='auto', target='id').translate(entry["note"]),
"description": description[entry["status"]],
})