From c652ee3e1f652d23e37833f01e3fdd7aa8e52021 Mon Sep 17 00:00:00 2001 From: "Indoteknik ." Date: Sat, 31 May 2025 11:03:06 +0700 Subject: (andri) add tracking biteship pada BU OUT & fix delivery departure & arrival date --- indoteknik_custom/models/stock_picking.py | 55 ++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) (limited to 'indoteknik_custom/models/stock_picking.py') diff --git a/indoteknik_custom/models/stock_picking.py b/indoteknik_custom/models/stock_picking.py index 54da700b..4d38e5b3 100644 --- a/indoteknik_custom/models/stock_picking.py +++ b/indoteknik_custom/models/stock_picking.py @@ -1551,7 +1551,60 @@ class StockPicking(models.Model): except Exception as e : _logger.error(f"Error fetching Biteship order for picking {self.id}: {str(e)}") return { 'error': str(e) } - + + def action_sync_biteship_tracking(self): + for picking in self: + if not picking.biteship_id: + raise UserError("Tracking Biteship tidak tersedia.") + + histori = picking.get_manifest_biteship() + updated_fields = {} + seen_logs = set() + + manifests = sorted(histori.get("manifests", []), key=lambda m: m.get("datetime") or "") + + for manifest in manifests: + status = manifest.get("status", "").lower() + dt_str = manifest.get("datetime") + desc = manifest.get("description") + dt = False + + try: + local_dt_str = picking._convert_to_local_time(dt_str) + dt = fields.Datetime.from_string(local_dt_str) + except Exception as e: + _logger.warning(f"[Biteship Sync] Gagal parse datetime: {e}") + continue + + # Update tanggal ke field + if status == "picked" and dt and not picking.driver_departure_date: + updated_fields["driver_departure_date"] = dt + + if status == "delivered" and dt and not picking.driver_arrival_date: + updated_fields["driver_arrival_date"] = dt + + # Buat log unik + if dt and desc: + desc_clean = ' '.join(desc.strip().split()) + log_line = f"[TRACKING] {status} - {dt.strftime('%d %b %Y %H:%M')}: {desc_clean}" + if not picking._has_existing_log(log_line): + picking.message_post(body=log_line) + seen_logs.add(log_line) + + if updated_fields: + picking.write(updated_fields) + + def _has_existing_log(self, log_line): + self.ensure_one() + self.env.cr.execute(""" + SELECT 1 FROM mail_message + WHERE model = %s AND res_id = %s + AND subtype_id IS NOT NULL + AND body ILIKE %s + LIMIT 1 + """, (self._name, self.id, f"%{log_line}%")) + return self.env.cr.fetchone() is not None + def _convert_to_local_time(self, iso_date): try: dt_with_tz = waktu.fromisoformat(iso_date) -- cgit v1.2.3 From b6928c9bffc486b471d4c335c2550cbc1bf7d841 Mon Sep 17 00:00:00 2001 From: "Indoteknik ." Date: Sat, 31 May 2025 12:32:45 +0700 Subject: (andri) fix bug datetime departure&arrival --- indoteknik_custom/models/stock_picking.py | 34 ++++++++++++++++++------------- 1 file changed, 20 insertions(+), 14 deletions(-) (limited to 'indoteknik_custom/models/stock_picking.py') diff --git a/indoteknik_custom/models/stock_picking.py b/indoteknik_custom/models/stock_picking.py index 4d38e5b3..4517a941 100644 --- a/indoteknik_custom/models/stock_picking.py +++ b/indoteknik_custom/models/stock_picking.py @@ -1570,23 +1570,23 @@ class StockPicking(models.Model): dt = False try: - local_dt_str = picking._convert_to_local_time(dt_str) - dt = fields.Datetime.from_string(local_dt_str) + dt = picking._convert_to_local_time(dt_str) except Exception as e: _logger.warning(f"[Biteship Sync] Gagal parse datetime: {e}") continue - # Update tanggal ke field + # Update tanggal ke field (pastikan naive datetime UTC) if status == "picked" and dt and not picking.driver_departure_date: - updated_fields["driver_departure_date"] = dt + updated_fields["driver_departure_date"] = fields.Datetime.to_string(dt) if status == "delivered" and dt and not picking.driver_arrival_date: - updated_fields["driver_arrival_date"] = dt + updated_fields["driver_arrival_date"] = fields.Datetime.to_string(dt) - # Buat log unik + # Buat log unik dengan waktu lokal Asia/Jakarta if dt and desc: + dt_local = pytz.utc.localize(dt).astimezone(pytz.timezone("Asia/Jakarta")) desc_clean = ' '.join(desc.strip().split()) - log_line = f"[TRACKING] {status} - {dt.strftime('%d %b %Y %H:%M')}: {desc_clean}" + log_line = f"[TRACKING] {status} - {dt_local.strftime('%d %b %Y %H:%M')}: {desc_clean}" if not picking._has_existing_log(log_line): picking.message_post(body=log_line) seen_logs.add(log_line) @@ -1607,15 +1607,21 @@ class StockPicking(models.Model): def _convert_to_local_time(self, iso_date): try: - dt_with_tz = waktu.fromisoformat(iso_date) - utc_dt = dt_with_tz.astimezone(pytz.utc) - + from dateutil import parser + import pytz + if isinstance(iso_date, str): + waktu = parser.parse(iso_date) + else: + waktu = iso_date + if waktu.tzinfo is None: + waktu = waktu.replace(tzinfo=pytz.utc) local_tz = pytz.timezone("Asia/Jakarta") - local_dt = utc_dt.astimezone(local_tz) - - return local_dt.strftime("%Y-%m-%d %H:%M:%S") + local_dt = waktu.astimezone(local_tz) + utc_dt = local_dt.astimezone(pytz.utc).replace(tzinfo=None) + return utc_dt except Exception as e: - return str(e) + _logger.warning(f"[Biteship] Gagal konversi waktu lokal: {e}") + return False def _map_status_biteship(self, status): status_mapping = { -- cgit v1.2.3