From 6d222cdfb56df09e61cd3add3c3fb328bd9adc7b Mon Sep 17 00:00:00 2001 From: "Indoteknik ." Date: Fri, 20 Jun 2025 14:20:57 +0700 Subject: (andri) patch json agar odoo menerima response kosong dari biteship --- indoteknik_api/controllers/api_v1/stock_picking.py | 58 ++++++++++++++-------- indoteknik_custom/models/__init__.py | 1 + indoteknik_custom/models/patch/__init__.py | 1 + indoteknik_custom/models/patch/http_override.py | 46 +++++++++++++++++ 4 files changed, 85 insertions(+), 21 deletions(-) create mode 100644 indoteknik_custom/models/patch/__init__.py create mode 100644 indoteknik_custom/models/patch/http_override.py diff --git a/indoteknik_api/controllers/api_v1/stock_picking.py b/indoteknik_api/controllers/api_v1/stock_picking.py index c5a4f7ed..0926bd26 100644 --- a/indoteknik_api/controllers/api_v1/stock_picking.py +++ b/indoteknik_api/controllers/api_v1/stock_picking.py @@ -1,10 +1,12 @@ 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__) class StockPicking(controller.Controller): prefix = '/api/v1/' @@ -143,26 +145,40 @@ class StockPicking(controller.Controller): 'name': picking_data.name }) - # @http.route(prefix + 'webhook/biteship', type='json', auth='public', methods=['POST'], csrf=False) - # def udpate_status_from_bitehsip(self, **kw): - # try: - # if not request.jsonrequest: - # return "ok" - - # data = request.jsonrequest # Ambil data JSON dari request - # event = data.get('event') - - # # 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) - - # return {'success': True, 'message': f'Webhook {event} received'} - # except Exception as e: - # return {'success': False, 'message': str(e)} + + @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: + # Karena type='json', Odoo secara otomatis akan mem-parsing JSON untuk Anda. + # 'data' akan berisi dictionary Python dari payload JSON Biteship. + data = request.jsonrequest + + # 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)}") + + 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'} + + except Exception as 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)} # @http.route(prefix + 'webhook/biteship', auth='public', methods=['POST'], csrf=False) # def udpate_status_from_bitehsip(self, **kw): diff --git a/indoteknik_custom/models/__init__.py b/indoteknik_custom/models/__init__.py index 605d1016..094ac69e 100755 --- a/indoteknik_custom/models/__init__.py +++ b/indoteknik_custom/models/__init__.py @@ -151,3 +151,4 @@ from . import account_payment_register from . import stock_inventory from . import sale_order_delay from . import approval_invoice_date +from . import patch diff --git a/indoteknik_custom/models/patch/__init__.py b/indoteknik_custom/models/patch/__init__.py new file mode 100644 index 00000000..051b6537 --- /dev/null +++ b/indoteknik_custom/models/patch/__init__.py @@ -0,0 +1 @@ +from . import http_override \ No newline at end of file diff --git a/indoteknik_custom/models/patch/http_override.py b/indoteknik_custom/models/patch/http_override.py new file mode 100644 index 00000000..e1978edb --- /dev/null +++ b/indoteknik_custom/models/patch/http_override.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +import odoo.http +import json +import logging +from werkzeug.exceptions import BadRequest +import functools + +_logger = logging.getLogger(__name__) + +class CustomJsonRequest(odoo.http.JsonRequest): + def __init__(self, httprequest): + super(odoo.http.JsonRequest, self).__init__(httprequest) + + self.params = {} + request_data_raw = self.httprequest.get_data().decode(self.httprequest.charset) + + self.jsonrequest = {} + if request_data_raw.strip(): + try: + self.jsonrequest = json.loads(request_data_raw) + except ValueError: + msg = 'Invalid JSON data: %r' % (request_data_raw,) + _logger.info('%s: %s (Handled by CustomJsonRequest)', self.httprequest.path, msg) + raise BadRequest(msg) + else: + _logger.info("CustomJsonRequest: Received empty or whitespace-only JSON body. Treating as empty JSON for webhook.") + + self.params = dict(self.jsonrequest.get("params", {})) + self.context = self.params.pop('context', dict(self.session.context)) + + +_original_get_request = odoo.http.Root.get_request + +@functools.wraps(_original_get_request) +def _get_request_override(self, httprequest): + _logger.info("--- DEBUG: !!! _get_request_override IS CALLED !!! ---") + _logger.info(f"--- DEBUG: Request Mimetype: {httprequest.mimetype}, Path: {httprequest.path} ---") + + if httprequest.mimetype in ("application/json", "application/json-rpc"): + _logger.debug("Odoo HTTP: Using CustomJsonRequest for mimetype: %s", httprequest.mimetype) + return CustomJsonRequest(httprequest) + else: + _logger.debug("Odoo HTTP: Using original get_request for mimetype: %s", httprequest.mimetype) + return _original_get_request(self, httprequest) + +odoo.http.Root.get_request = _get_request_override \ No newline at end of file -- cgit v1.2.3