summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIT Fixcomart <it@fixcomart.co.id>2025-06-09 04:48:12 +0000
committerIT Fixcomart <it@fixcomart.co.id>2025-06-09 04:48:12 +0000
commitf43855aa55265794c7774af79089258e830b0df4 (patch)
treeec0c4595d5c6eed250648613c7d46d6b583a33c7
parent9228e331a2b4c3f80eb22ec824a14633b6235972 (diff)
parentde747091235c844d33bcf62b4d98af0d03251826 (diff)
Merged in parsial-biteship (pull request #324)
Parsial biteship
-rwxr-xr-xindoteknik_custom/models/sale_order.py53
-rw-r--r--indoteknik_custom/models/stock_picking.py109
-rw-r--r--indoteknik_custom/views/stock_picking.xml2
3 files changed, 95 insertions, 69 deletions
diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py
index 3e340c60..80a552fe 100755
--- a/indoteknik_custom/models/sale_order.py
+++ b/indoteknik_custom/models/sale_order.py
@@ -256,6 +256,20 @@ class SaleOrder(models.Model):
('custom', 'Custom'),
], string='Shipping Option', help="Select shipping option for delivery", tracking=True)
+ @api.onchange('shipping_cost_covered')
+ def _onchange_shipping_cost_covered(self):
+ if self.shipping_cost_covered == 'indoteknik' and self.select_shipping_option == 'biteship':
+ self.shipping_cost_covered = 'customer'
+ return {
+ 'warning': {
+ 'title': "Biteship Tidak Diizinkan",
+ 'message': (
+ "Biaya pengiriman ditanggung Indoteknik, sehingga tidak diizinkan menggunakan metode Biteship. "
+ "Pilihan penanggung biaya akan dikembalikan sebelumnya"
+ )
+ }
+ }
+
def get_biteship_carrier_ids(self):
courier_codes = tuple(self._get_biteship_courier_codes() or [])
if not courier_codes:
@@ -277,20 +291,29 @@ class SaleOrder(models.Model):
if view_type == 'form':
doc = etree.XML(res['arch'])
- carrier_ids = self.get_biteship_carrier_ids()
- if carrier_ids:
- carrier_ids_str = '(' + ','.join(str(x) for x in carrier_ids) + ')'
- else:
- carrier_ids_str = '(-1,)' # aman kalau kosong
+ # Ambil semua delivery_carrier_id dari mapping rajaongkir_kurir
+ biteship_ids = self.env['rajaongkir.kurir'].search([]).mapped('delivery_carrier_id.id')
+ biteship_ids = list(set(filter(None, biteship_ids))) # pastikan unik dan bukan None
+
+ all_ids = self.env['delivery.carrier'].search([]).ids
+ custom_ids = list(set(all_ids) - set(biteship_ids))
- # ✅ Tambahkan log di sini
- _logger.info("🛰️ Biteship Carrier IDs: %s", carrier_ids)
- _logger.info("📦 Domain string to apply: [('id', 'in', %s)]", carrier_ids_str)
+ # Format sebagai string Python list
+ biteship_ids_str = ','.join(str(i) for i in biteship_ids) or '-1'
+ custom_ids_str = ','.join(str(i) for i in custom_ids) or '-1'
+ # Terapkan domain ke field carrier_id
for node in doc.xpath("//field[@name='carrier_id']"):
- node.set('domain', "[('id', 'in', %s)]" % carrier_ids_str)
+ # Domain tergantung select_shipping_option
+ node.set(
+ 'domain',
+ "[('id', 'in', [%s]) if select_shipping_option == 'biteship' else ('id', 'in', [%s])]" %
+ (biteship_ids_str, custom_ids_str)
+ )
+ # Simpan kembali hasil XML ke arsitektur form
res['arch'] = etree.tostring(doc, encoding='unicode')
+
return res
# @api.onchange('shipping_option_id')
@@ -470,6 +493,18 @@ class SaleOrder(models.Model):
@api.onchange('select_shipping_option')
def _onchange_select_shipping_option(self):
+ if self.select_shipping_option == 'biteship' and self.shipping_cost_covered == 'indoteknik':
+ self.select_shipping_option = self._origin.select_shipping_option if self._origin else 'custom'
+ return {
+ 'warning': {
+ 'title': "Biteship Tidak Diizinkan",
+ 'message': (
+ "Biaya pengiriman ditanggung Indoteknik. Tidak diizinkan memilih metode Biteship. "
+ "Opsi pengiriman dikembalikan ke sebelumnya."
+ )
+ }
+ }
+
self.shipping_option_id = False
self.carrier_id = False
self.delivery_amt = 0
diff --git a/indoteknik_custom/models/stock_picking.py b/indoteknik_custom/models/stock_picking.py
index a2935a07..d04b3d27 100644
--- a/indoteknik_custom/models/stock_picking.py
+++ b/indoteknik_custom/models/stock_picking.py
@@ -244,6 +244,11 @@ class StockPicking(models.Model):
biteship_waybill_id = fields.Char(string="Biteship Waybill ID")
final_seq = fields.Float(string='Remaining Time')
shipping_method_so_id = fields.Many2one('delivery.carrier', string='Shipping Method SO', related='sale_id.carrier_id')
+ shipping_option_so_id = fields.Many2one('shipping.option', string='Shipping Option SO', related='sale_id.shipping_option_id')
+ select_shipping_option_so = fields.Selection([
+ ('biteship', 'Biteship'),
+ ('custom', 'Custom'),
+ ], string='Shipping Type SO', related='sale_id.select_shipping_option')
state_packing = fields.Selection([('not_packing', 'Belum Packing'), ('packing_done', 'Sudah Packing')], string='Packing Status')
approval_invoice_date_id = fields.Many2one('approval.invoice.date', string='Approval Invoice Date')
last_update_date_doc_kirim = fields.Datetime(string='Last Update Tanggal Kirim')
@@ -526,7 +531,6 @@ class StockPicking(models.Model):
if self.biteship_tracking_id:
raise UserError(f"Order ini sudah dikirim ke Biteship. Dengan Tracking Id: {self.biteship_tracking_id}")
- # Fungsi bantu: menentukan apakah kurir perlu koordinat
def is_courier_need_coordinates(service_code):
return service_code in [
"instant", "same_day", "instant_car",
@@ -534,47 +538,42 @@ class StockPicking(models.Model):
"cdd_bak", "cdd_box", "engkel_box", "engkel_bak"
]
- # Ambil order line
- products = self.env['sale.order.line'].search([('order_id', '=', self.sale_id.id)])
-
- # Bangun data items untuk standard
- def build_items_data(lines):
- return [{
- "name": line.product_id.name,
- "description": line.name,
- "value": line.price_unit,
- "quantity": line.product_uom_qty,
- "weight": line.weight*1000
- } for line in lines]
-
- items_data_standard = build_items_data(products)
+ # ✅ Ambil item dari move_line_ids_with_package (qty_done > 0)
+ items = []
+ for ml in self.move_line_ids_without_package:
+ if ml.qty_done <= 0:
+ continue
- # Bangun data items untuk pengiriman instant
- items_data_instant = []
- for move_line in self.move_line_ids_without_package:
- order_line = self.env['sale.order.line'].search([
+ product = ml.product_id
+ weight = product.weight or 0.1 # default minimal
+ line = ml.move_id.sale_line_id or self.env['sale.order.line'].search([
('order_id', '=', self.sale_id.id),
- ('product_id', '=', move_line.product_id.id)
+ ('product_id', '=', ml.product_id.id)
], limit=1)
- if order_line:
- items_data_instant.append({
- "name": order_line.product_id.name,
- "description": order_line.name,
- "value": order_line.price_unit,
- "quantity": move_line.qty_done,
- "weight": order_line.weight*1000
- })
+ value = line.price_unit if line else 0
+ description = line.name if line else product.name
+
+ items.append({
+ "name": product.name,
+ "description": description,
+ "value": value,
+ "quantity": ml.qty_done,
+ "weight": int(weight * 1000),
+ })
+
+ if not items:
+ raise UserError("Pengiriman tidak dapat dilakukan karena tidak ada barang yang divalidasi (qty_done = 0).")
+
+ shipping_partner = self.real_shipping_id
+ courier_service_code = self.sale_id.delivery_service_type or "reg"
- _logger.info(f"Items data standard: {items_data_standard}")
- _logger.info(f"Items data instant: {items_data_instant}")
- # Bangun payload dasar
payload = {
"origin_coordinate": {
"latitude": -6.3031123,
"longitude": 106.7794934999
},
- "reference_id": self.sale_id.name,
+ "reference_id": self.name,
"shipper_contact_name": self.carrier_id.pic_name or '',
"shipper_contact_phone": self.carrier_id.pic_phone or '',
"shipper_organization": self.carrier_id.name,
@@ -582,37 +581,27 @@ class StockPicking(models.Model):
"origin_contact_phone": "081717181922",
"origin_address": "Jl. Bandengan Utara Komp A & BRT. Penjaringan, Kec. Penjaringan, Jakarta (BELAKANG INDOMARET) KOTA JAKARTA UTARA PENJARINGAN",
"origin_postal_code": 14440,
- "destination_contact_name": self.real_shipping_id.name,
- "destination_contact_phone": self.real_shipping_id.phone or self.real_shipping_id.mobile,
- "destination_address": self.real_shipping_id.street,
- "destination_postal_code": self.real_shipping_id.zip,
+ "destination_contact_name": shipping_partner.name,
+ "destination_contact_phone": shipping_partner.phone or shipping_partner.mobile,
+ "destination_address": shipping_partner.street,
+ "destination_postal_code": shipping_partner.zip,
"origin_note": "BELAKANG INDOMARET",
- "courier_type": self.sale_id.delivery_service_type or "reg",
+ "destination_note": f"SO: {self.sale_id.name}",
+ "order_note": f"SO: {self.sale_id.name}",
+ "courier_type": courier_service_code,
"courier_company": self.carrier_id.name.lower(),
"delivery_type": "now",
- "items": items_data_standard
+ "items": items
}
- _logger.info(f"Delivery service type: {self.sale_id.delivery_service_type}")
- _logger.info(f"Carrier: {self.carrier_id.name}")
- _logger.info(f"Payload awal: {payload}")
-
- # Tambahkan destination_coordinate jika diperlukan
- if is_courier_need_coordinates(self.sale_id.delivery_service_type):
- if not self.real_shipping_id.latitude or not self.real_shipping_id.longtitude:
+ if is_courier_need_coordinates(courier_service_code):
+ if not shipping_partner.latitude or not shipping_partner.longtitude:
raise UserError("Alamat tujuan tidak memiliki koordinat (latitude/longitude).")
- # items_to_use = items_data_instant if items_data_instant else items_data_standard
- if not items_data_instant:
- raise UserError("Pengiriman instant membutuhkan produk yang sudah diproses (qty_done > 0). Harap lakukan validasi picking terlebih dahulu.")
-
- payload.update({
- "destination_coordinate": {
- "latitude": self.real_shipping_id.latitude,
- "longitude": self.real_shipping_id.longtitude,
- },
- "items": items_data_instant
- })
+ payload["destination_coordinate"] = {
+ "latitude": shipping_partner.latitude,
+ "longitude": shipping_partner.longtitude,
+ }
_logger.info(f"Payload untuk Biteship: {payload}")
@@ -632,7 +621,7 @@ class StockPicking(models.Model):
self.biteship_id = data.get("id", "")
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", "")
+ self.delivery_tracking_no = self.biteship_waybill_id
waybill_id = self.biteship_waybill_id
@@ -640,7 +629,9 @@ class StockPicking(models.Model):
body=f"Biteship berhasil dilakukan.<br/>"
f"Kurir: {self.carrier_id.name}<br/>"
f"Tracking ID: {self.biteship_tracking_id or '-'}<br/>"
- f"Resi: {waybill_id or '-'}",
+ f"Resi: {waybill_id or '-'}<br/>"
+ f"Reference: {self.name}<br/>"
+ f"SO: {self.sale_id.name}",
message_type="comment"
)
@@ -653,13 +644,11 @@ class StockPicking(models.Model):
'type': 'rainbow_man',
}
}
-
else:
error_data = response.json()
error_message = error_data.get("error", "Unknown error")
error_code = error_data.get("code", "No code provided")
raise UserError(f"Error saat mengirim ke Biteship: {error_message} (Code: {error_code})")
-
@api.constrains('driver_departure_date')
def constrains_driver_departure_date(self):
diff --git a/indoteknik_custom/views/stock_picking.xml b/indoteknik_custom/views/stock_picking.xml
index 9b16639c..b0d55104 100644
--- a/indoteknik_custom/views/stock_picking.xml
+++ b/indoteknik_custom/views/stock_picking.xml
@@ -91,7 +91,9 @@
/>
</button>
<field name="backorder_id" position="after">
+ <field name="select_shipping_option_so"/>
<field name="shipping_method_so_id"/>
+ <field name="shipping_option_so_id"/>
<field name="summary_qty_detail"/>
<field name="count_line_detail"/>
<field name="dokumen_tanda_terima"/>