summaryrefslogtreecommitdiff
path: root/indoteknik_api/controllers/api_v1/stock_picking.py
diff options
context:
space:
mode:
Diffstat (limited to 'indoteknik_api/controllers/api_v1/stock_picking.py')
-rw-r--r--indoteknik_api/controllers/api_v1/stock_picking.py174
1 files changed, 118 insertions, 56 deletions
diff --git a/indoteknik_api/controllers/api_v1/stock_picking.py b/indoteknik_api/controllers/api_v1/stock_picking.py
index 31706b99..85b0fbba 100644
--- a/indoteknik_api/controllers/api_v1/stock_picking.py
+++ b/indoteknik_api/controllers/api_v1/stock_picking.py
@@ -1,9 +1,14 @@
from .. import controller
from odoo import http
-from odoo.http import request
+from odoo.http import request, Response
from pytz import timezone
from datetime import datetime
+import json
+import logging
+_logger = logging.getLogger(__name__)
+
+_logger = logging.getLogger(__name__)
class StockPicking(controller.Controller):
prefix = '/api/v1/'
@@ -22,42 +27,44 @@ class StockPicking(controller.Controller):
if not get_params['valid']:
return self.response(code=400, description=get_params)
-
+
params = get_params['value']
partner_id = params['partner_id']
limit = params['limit']
offset = params['offset']
-
+
child_ids = request.env['res.partner'].browse(partner_id).get_child_ids()
pending_domain = [('driver_departure_date', '=', False), ('driver_arrival_date', '=', False)]
shipment_domain = [('driver_departure_date', '!=', False), ('driver_arrival_date', '=', False)]
shipment_domain2 = [('driver_departure_date', '!=', False), ('sj_return_date', '=', False)]
- completed_domain = [('driver_departure_date', '!=', False),'|', ('driver_arrival_date', '!=', False), ('sj_return_date', '!=', False)]
+ completed_domain = [('driver_departure_date', '!=', False), '|', ('driver_arrival_date', '!=', False),
+ ('sj_return_date', '!=', False)]
completed_domain2 = [('driver_departure_date', '!=', False), ('sj_return_date', '!=', False)]
picking_model = request.env['stock.picking']
domain = [
- ('partner_id', 'in', child_ids),
- ('sale_id', '!=', False),
- ('origin', 'ilike', 'SO%'),
- ('state', '!=', 'cancel')
+ ('partner_id', 'in', child_ids),
+ ('sale_id', '!=', False),
+ ('origin', 'ilike', 'SO%'),
+ ('state', '!=', 'cancel'),
+ ('name', 'ilike', 'BU/OUT%')
]
-
+
if params['q']:
query_like = '%' + params['q'].replace(' ', '%') + '%'
- domain += ['|', '|',
- ('name', 'ilike', query_like),
- ('sale_id.client_order_ref', 'ilike', query_like),
- ('delivery_tracking_no', 'ilike', query_like)
- ]
+ domain += ['|', '|',
+ ('name', 'ilike', query_like),
+ ('sale_id.client_order_ref', 'ilike', query_like),
+ ('delivery_tracking_no', 'ilike', query_like)
+ ]
default_domain = domain.copy()
-
+
if params['status'] == 'pending':
domain += pending_domain
elif params['status'] == 'shipment':
- domain += shipment_domain + shipment_domain2
+ domain += shipment_domain + shipment_domain2
elif params['status'] == 'completed':
domain += completed_domain
@@ -65,7 +72,7 @@ class StockPicking(controller.Controller):
res_pickings = []
for picking in stock_pickings:
manifests = picking.get_manifests()
-
+
res_pickings.append({
'id': picking.id,
'name': picking.name,
@@ -86,12 +93,12 @@ class StockPicking(controller.Controller):
'summary': {
'pending_count': picking_model.search_count(default_domain + pending_domain),
'shipment_count': picking_model.search_count(default_domain + shipment_domain + shipment_domain2),
- 'completed_count': picking_model.search_count(default_domain + completed_domain )
+ 'completed_count': picking_model.search_count(default_domain + completed_domain)
},
'picking_total': picking_model.search_count(domain),
'pickings': res_pickings
})
-
+
@http.route(PREFIX_PARTNER + 'stock-picking/<id>/tracking', auth='public', method=['GET', 'OPTIONS'])
@controller.Controller.must_authorized(private=True, private_key='partner_id')
def get_partner_stock_picking_detail_tracking(self, **kw):
@@ -101,7 +108,6 @@ class StockPicking(controller.Controller):
picking = picking_model.browse(id)
if not picking:
return self.response(None)
- hostori = picking.get_tracking_detail()
return self.response(picking.get_tracking_detail())
@http.route(prefix + 'stock-picking/<id>/tracking', auth='public', method=['GET', 'OPTIONS'])
@@ -140,49 +146,105 @@ class StockPicking(controller.Controller):
return self.response({
'name': picking_data.name
})
-
- @http.route(prefix + 'webhook/biteship', type='json', auth='public', methods=['POST'], csrf=False)
- def udpate_status_from_bitehsip(self, **kw):
+
+ @http.route(prefix + 'webhook/biteship', type='json', auth='public', methods=['POST'], csrf=False)
+ def update_status_from_biteship(self, **kw):
+ _logger.info("Biteship Webhook: Request received at controller start (type='json').")
+
try:
- if not request.jsonrequest:
- return "ok"
+ # Karena type='json', Odoo secara otomatis akan mem-parsing JSON untuk Anda.
+ # 'data' akan berisi dictionary Python dari payload JSON Biteship.
+ data = request.jsonrequest
- data = request.jsonrequest # Ambil data JSON dari request
- event = data.get('event')
+ # Log ini akan menunjukkan payload yang diterima (sudah dalam bentuk dict)
+ _logger.info(f"Biteship Webhook: Parsed JSON data from request.jsonrequest: {json.dumps(data)}")
- # Handle Event Berdasarkan Jenisnya
- if event == "order.status":
- self.process_order_status(data)
- elif event == "order.price":
- self.process_order_price(data)
- elif event == "order.waybill_id":
- self.process_order_waybill(data)
+ event = data.get('event')
+ if event:
+ _logger.info(f"Biteship Webhook: Processing event: {event}")
+ if event == "order.status":
+ self.process_order_status(data)
+ elif event == "order.price":
+ self.process_order_price(data)
+ elif event == "order.waybill_id":
+ self.process_order_waybill(data)
+ # Tambahkan logika untuk event lain jika ada
+ else:
+ _logger.info("Biteship Webhook: No specific event in payload. Likely an installation/verification ping or unknown event type.")
+
+ # Untuk route type='json', Anda cukup mengembalikan dictionary Python.
+ # Odoo akan secara otomatis mengonversinya menjadi respons JSON yang valid.
+ return {'status': 'ok'}
- return {'success': True, 'message': f'Webhook {event} received'}
except Exception as e:
- return {'success': False, 'message': str(e)}
+ _logger.error(f"Biteship Webhook: Unhandled error during processing: {e}", exc_info=True)
+ # Untuk error, kembalikan dictionary error juga, Odoo akan mengonversinya ke JSON
+ return {'status': 'error', 'message': str(e)}
def process_order_status(self, data):
- picking_model = request.env['stock.picking'].sudo().search([('biteship_id', '=', data.get('order_id'))], limit=1)
- if data.get('status') == 'picked':
- picking_model.write({'driver_departure_date': datetime.utcnow()})
- elif data.get('status') == 'delivered':
- picking_model.write({'driver_arrival_date': datetime.utcnow()})
-
+ picking = request.env['stock.picking'].sudo().search([
+ ('biteship_id', '=', data.get('order_id'))
+ ], limit=1)
+
+ if not picking:
+ _logger.warning(f"[Webhook] Tidak ditemukan picking untuk order_id {data.get('order_id')}")
+ return
+
+ status = data.get('status')
+ timestamp = data.get('updated_at') or datetime.utcnow().isoformat()
+
+ description = picking._get_biteship_status_description(status, {
+ "courier": {"company": data.get("courier_company", "")},
+ "destination": {"contact_name": picking.partner_id.name or ""}
+ })
+
+ # Tambahkan extra data dari webhook
+ extra_data = {
+ "courier_driver_name": data.get("courier_driver_name"),
+ "courier_driver_phone": data.get("courier_driver_phone"),
+ "courier_driver_plate_number": data.get("courier_driver_plate_number"),
+ "courier_link": data.get("courier_link"),
+ "order_price": data.get("order_price"),
+ "status": data.get("status"),
+ }
+
+ picking.log_biteship_event_from_webhook(status, timestamp, description, extra_data=extra_data)
+
+
+
def process_order_price(self, data):
- picking_model = request.env['stock.picking'].sudo().search([('biteship_id', '=', data.get('order_id'))], limit=1)
- order = request.env['sale.order'].sudo().search([('name', '=', picking_model.sale_id.name)], limit=1)
- if order:
- order.write({
- 'delivery_amt': data.get('price')
- })
+ picking = request.env['stock.picking'].sudo().search([('biteship_id', '=', data.get('order_id'))], limit=1)
+
+ if not picking:
+ _logger.warning(f"Tidak ditemukan picking untuk order_id {data.get('order_id')}")
+ return
+
+ picking.log_biteship_event_from_webhook(
+ status='order.price',
+ timestamp=data.get('updated_at') or datetime.utcnow().isoformat(),
+ description='Biaya pengiriman telah diperbarui berdasarkan informasi terbaru dari Biteship.',
+ extra_data={
+ "order_price": data.get("price")
+ }
+ )
+
def process_order_waybill(self, data):
- picking_model = request.env['stock.picking'].sudo().search([('biteship_id', '=', data.get('order_id'))], limit=1)
- if picking_model:
- picking_model.write({
- 'biteship_waybill_id': data.get('courier_waybill_id'),
- 'delivery_tracking_no': data.get('courier_waybill_id'),
- 'biteship_tracking_id':data.get('courier_tracking_id')
- })
- \ No newline at end of file
+ picking = request.env['stock.picking'].sudo().search([
+ ('biteship_id', '=', data.get('order_id'))
+ ], limit=1)
+
+ if not picking:
+ _logger.warning(f"Tidak ditemukan picking untuk order_id {data.get('order_id')}")
+ return
+
+ picking.log_biteship_event_from_webhook(
+ status='order.waybill_id',
+ timestamp=data.get('updated_at') or datetime.utcnow().isoformat(),
+ description="Nomor waybill dan tracking diperbarui melalui Biteship.",
+ extra_data={
+ "tracking_id": data.get("courier_tracking_id"),
+ "waybill_id": data.get("courier_waybill_id")
+ }
+ )
+