From 63243a7b70292e9c48a21e2badbb07c398bc4166 Mon Sep 17 00:00:00 2001 From: "Indoteknik ." Date: Mon, 19 May 2025 16:07:03 +0700 Subject: (andri) add field langitude & longitude pada customer & perbaikan biteship --- indoteknik_custom/models/sale_order.py | 90 ++++++++++++++++++--------------- indoteknik_custom/views/res_partner.xml | 4 ++ 2 files changed, 53 insertions(+), 41 deletions(-) (limited to 'indoteknik_custom') diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py index 4ee82100..f09869da 100755 --- a/indoteknik_custom/models/sale_order.py +++ b/indoteknik_custom/models/sale_order.py @@ -258,7 +258,6 @@ class SaleOrder(models.Model): def _onchange_shipping_option_id(self): if self.shipping_option_id: self.delivery_amt = self.shipping_option_id.price - self.note_ekspedisi = f"Pengiriman: {self.shipping_option_id.name} - Rp {self.shipping_option_id.price:,.0f} ({self.shipping_option_id.etd})" def _get_biteship_courier_codes(self): return [ @@ -271,29 +270,25 @@ class SaleOrder(models.Model): self.carrier_id = False self.delivery_amt = 0 - biteship_courier_codes = self._get_biteship_courier_codes() - - # Cari carrier yang namanya mengandung kode Biteship + # Dapatkan semua ID carrier untuk Biteship biteship_carrier_ids = [] - for code in biteship_courier_codes: - carriers = self.env['delivery.carrier'].search([ - ('name', 'ilike', code) - ]) - if carriers: - biteship_carrier_ids.extend(carriers.ids) - # Hapus duplikat - biteship_carrier_ids = list(set(biteship_carrier_ids)) + # Gunakan SQL langsung untuk menghindari masalah ORM + self.env.cr.execute(""" + SELECT delivery_carrier_id + FROM rajaongkir_kurir + WHERE name IN %s + """, (tuple(self._get_biteship_courier_codes()),)) - if self.select_shipping_option == 'custom': - # Tampilkan carrier yang bukan dari Biteship - domain = [('id', 'not in', biteship_carrier_ids)] if biteship_carrier_ids else [] - return {'domain': {'carrier_id': domain}} + # Ambil ID numerik hasil query + biteship_carrier_ids = [row[0] for row in self.env.cr.fetchall() if row[0]] - elif self.select_shipping_option == 'biteship': - # Tampilkan hanya carrier dari Biteship + if self.select_shipping_option == 'biteship': domain = [('id', 'in', biteship_carrier_ids)] if biteship_carrier_ids else [] - return {'domain': {'carrier_id': domain}} + else: # 'custom' + domain = [('id', 'not in', biteship_carrier_ids)] if biteship_carrier_ids else [] + + return {'domain': {'carrier_id': domain}} @api.constrains('fee_third_party', 'delivery_amt', 'biaya_lain_lain') def _check_total_margin_excl_third_party(self): @@ -490,6 +485,7 @@ class SaleOrder(models.Model): return total_weight def action_estimate_shipping_biteship(self): + total_weight = self._validate_for_shipping_estimate() # Konversi berat ke gram untuk Biteship @@ -509,6 +505,10 @@ class SaleOrder(models.Model): "length": 10 }] + # Coba dapatkan data koordinat dari alamat pengiriman + shipping_address = self.real_shipping_id + _logger.info(f"Shipping Address: {shipping_address}") + # Data asal (tetap gudang Bandengan) origin_data = { "origin_latitude": -6.3031123, @@ -519,37 +519,41 @@ class SaleOrder(models.Model): destination_data = {} use_coordinate = False - shipping_address = self.real_shipping_id - # Cek apakah latitude dan longitude tersedia dan valid - if hasattr(shipping_address, 'latitude') and hasattr(shipping_address, 'longitude'): - if shipping_address.latitude and shipping_address.longitude: + if hasattr(shipping_address, 'latitude') and hasattr(shipping_address, 'longtitude'): + if shipping_address.latitude and shipping_address.longtitude: try: + # Validasi format koordinat lat = float(shipping_address.latitude) - lng = float(shipping_address.longitude) + lng = float(shipping_address.longtitude) destination_data = { "destination_latitude": lat, "destination_longitude": lng } use_coordinate = True + _logger.info(f"Using coordinates: lat={lat}, lng={lng}") except (ValueError, TypeError): + _logger.warning(f"Invalid coordinates, falling back to postal code") use_coordinate = False - # Jika koordinat tidak tersedia, gunakan kode pos + # Jika koordinat tidak tersedia atau tidak valid, gunakan kode pos if not use_coordinate: if shipping_address.zip: - origin_data = {"origin_postal_code": 14440} + origin_data = {"origin_postal_code": 14440} # Reset origin untuk mode kode pos destination_data = { "destination_postal_code": shipping_address.zip } + _logger.info(f"Using postal code: {shipping_address.zip}") else: raise UserError("Tidak dapat mengestimasikan ongkir: Kode pos tujuan tidak tersedia.") - # Filter kurir berdasarkan shipping method jika dipilih - couriers = self.carrier_id.name.lower() if self.carrier_id else ','.join(self._get_biteship_courier_codes()) + # Siapkan daftar kurir + couriers = ','.join(self._get_biteship_courier_codes()) - # Panggil API Biteship + # Panggil API Biteship dengan format yang benar api_mode = "koordinat" if use_coordinate else "kode_pos" + _logger.info(f"Calling Biteship API with mode: {api_mode}") + result = self._call_biteship_api(origin_data, destination_data, items, couriers) if not result: @@ -562,14 +566,19 @@ class SaleOrder(models.Model): shipping_options = [] shipping_services = result.get('pricing', []) + _logger.info(f"Ditemukan {len(shipping_services)} layanan pengiriman") + for service in shipping_services: courier_code = service.get('courier_code', '').lower() courier_name = service.get('courier_name', '') service_name = service.get('courier_service_name', '') price = service.get('price', 0) + _logger.info(f"Layanan: {courier_name} - {service_name}, Harga: {price}") + # Lewati layanan dengan harga 0 if not price: + _logger.warning(f"Melewati layanan dengan harga 0: {courier_name} - {service_name}") continue # Format estimasi waktu @@ -577,12 +586,13 @@ class SaleOrder(models.Model): shipment_range = service.get('shipment_duration_range', '') shipment_unit = service.get('shipment_duration_unit', 'days') + # Gunakan duration jika tersedia, jika tidak, buat dari range if duration: etd = duration elif shipment_range: etd = f"{shipment_range} {shipment_unit}" else: - etd = "1-3 days" + etd = "1-3 days" # Default fallback # Buat shipping option try: @@ -595,18 +605,19 @@ class SaleOrder(models.Model): }) shipping_options.append(shipping_option) + _logger.info(f"Berhasil membuat opsi pengiriman: {courier_name} - {service_name}") except Exception as e: _logger.error(f"Gagal membuat opsi pengiriman: {str(e)}") # Jika tidak ada opsi pengiriman if not shipping_options: - raise UserError(f"Tidak ada layanan pengiriman ditemukan untuk kode pos {destination_data}.") + raise UserError(f"Tidak ada layanan pengiriman ditemukan untuk kode pos {destination_data}. Mohon periksa kembali kode pos atau gunakan metode pengiriman lain.") # Set opsi pertama sebagai default self.shipping_option_id = shipping_options[0].id self.delivery_amt = shipping_options[0].price - # Tampilkan lokasi pengiriman dengan format yang lebih baik + # Format pesan untuk log yang lebih informatif if use_coordinate: origin_info = f"Koordinat ({origin_data.get('origin_latitude')}, {origin_data.get('origin_longitude')})" destination_info = f"Koordinat ({destination_data.get('destination_latitude')}, {destination_data.get('destination_longitude')})" @@ -620,17 +631,14 @@ class SaleOrder(models.Model): for opt in shipping_options ]) - # Tampilkan informasi tentang kurir yang dipilih - selected_option = shipping_options[0] - shipping_method_info = f"Metode Pengiriman: {self.carrier_id.name}" if self.carrier_id else "" - - # Log hasil estimasi dengan format yang lebih baik dan informasi kurir + # Log hasil estimasi dengan format yang lebih baik self.message_post( - body=f"Estimasi Ongkir Biteship ({origin_info} → {destination_info}):
{shipping_method_info}
{option_list}", + body=f"Estimasi Ongkir Biteship ({origin_info} → {destination_info}):
{option_list}", message_type="comment" ) # Simpan informasi untuk note ekspedisi + selected_option = shipping_options[0] # Opsi pertama dipilih sebagai default self.note_ekspedisi = f"Pengiriman: {selected_option.name} - Rp {selected_option.price:,.0f} ({selected_option.etd}) [via {api_mode}]" return { @@ -1435,7 +1443,7 @@ class SaleOrder(models.Model): raise UserError("This order not yet approved by customer procurement or director") if not order.client_order_ref and order.create_date > datetime(2024, 6, 27): - raise UserError("Customer Reference kosong, di isi dengan NO PO jika PO tidak ada mohon ditulis Tanpa PO") + raise UserError("Customer Reference kosong, di isi dengan NO PO jika PO tidak ada mohon ditulis Tanpa PO") if not order.commitment_date and order.create_date > datetime(2024, 9, 12): raise UserError("Expected Delivery Date kosong, wajib diisi") @@ -1462,7 +1470,7 @@ class SaleOrder(models.Model): if (partner.customer_type == 'pkp' or order.customer_type == 'pkp') and order.sppkp != partner.sppkp: raise UserError("SPPKP berbeda pada Master Data Customer") if not order.client_order_ref and order.create_date > datetime(2024, 6, 27): - raise UserError("Customer Reference kosong, di isi dengan NO PO jika PO tidak ada mohon ditulis Tanpa PO") + raise UserError("Customer Reference kosong, di isi dengan NO PO jika PO tidak ada mohon ditulis Tanpa PO") if not order.user_id.active: raise UserError("Salesperson sudah tidak aktif, mohon diisi yang benar pada data SO dan Contact") @@ -1673,7 +1681,7 @@ class SaleOrder(models.Model): raise UserError("This order not yet approved by customer procurement or director") if not order.client_order_ref and order.create_date > datetime(2024, 6, 27): - raise UserError("Customer Reference kosong, di isi dengan NO PO jika PO tidak ada mohon ditulis Tanpa PO") + raise UserError("Customer Reference kosong, di isi dengan NO PO jika PO tidak ada mohon ditulis Tanpa PO") if not order.commitment_date and order.create_date > datetime(2024, 9, 12): raise UserError("Expected Delivery Date kosong, wajib diisi") diff --git a/indoteknik_custom/views/res_partner.xml b/indoteknik_custom/views/res_partner.xml index cb9fa3ac..9fb6530c 100644 --- a/indoteknik_custom/views/res_partner.xml +++ b/indoteknik_custom/views/res_partner.xml @@ -65,6 +65,10 @@ + + + + -- cgit v1.2.3