diff options
| author | Rafi Zadanly <zadanlyr@gmail.com> | 2023-07-28 11:36:33 +0700 |
|---|---|---|
| committer | Rafi Zadanly <zadanlyr@gmail.com> | 2023-07-28 11:36:33 +0700 |
| commit | 71bdce1310997736f84a6d65d423fca801bfe655 (patch) | |
| tree | 9001ee9f97d5abcd3214ea61ef12f78ff2b26f95 | |
| parent | eacf53b314861bc797e1222d4b8d7ae9ef677040 (diff) | |
| parent | f26b2447f4f233a838e8990a800d975ab27a1557 (diff) | |
Merge branch 'aiway-bill' into development
| -rw-r--r-- | indoteknik_api/controllers/api_v1/sale_order.py | 32 | ||||
| -rwxr-xr-x | indoteknik_custom/__manifest__.py | 1 | ||||
| -rwxr-xr-x | indoteknik_custom/models/__init__.py | 2 | ||||
| -rw-r--r-- | indoteknik_custom/models/airway_bill.py | 197 | ||||
| -rw-r--r-- | indoteknik_custom/models/airway_bill_manifest.py | 33 | ||||
| -rw-r--r-- | indoteknik_custom/models/stock_picking.py | 1 | ||||
| -rwxr-xr-x | indoteknik_custom/security/ir.model.access.csv | 4 | ||||
| -rw-r--r-- | indoteknik_custom/views/airway_bill.xml | 105 |
8 files changed, 374 insertions, 1 deletions
diff --git a/indoteknik_api/controllers/api_v1/sale_order.py b/indoteknik_api/controllers/api_v1/sale_order.py index a8b2fd11..cc7fd48f 100644 --- a/indoteknik_api/controllers/api_v1/sale_order.py +++ b/indoteknik_api/controllers/api_v1/sale_order.py @@ -372,7 +372,38 @@ class SaleOrder(controller.Controller): 'id': sale_order.id, 'name': sale_order.name }) + + @http.route(PREFIX_PARTNER + 'sale-order/<id>/awb', auth='public', methods=['GET', 'OPTIONS']) + @controller.Controller.must_authorized(private=True, private_key='partner_id') + def get_airway_bill_by_sale_order_id(self, **kw): + id = int(kw.get('id', 0)) + response = {'airways': None} + airway_bills = request.env['airway.bill'].search([('so_id', '=', id)]) + + if not airway_bills: + return self.response(response) + + airways = [] + for airway_bill in airway_bills: + data = airway_bill.decode_response() + delivery_order = airway_bill.do_id + result = data['rajaongkir']['result'] + airways.append({ + 'delivery_order': { + 'name': delivery_order.name, + 'carrier': delivery_order.carrier_id.name, + 'receiver_name': airway_bill.receiver_name, + 'receiver_city': airway_bill.receiver_city, + }, + 'delivered': result['delivered'], + 'waybill_number': result['summary']['waybill_number'], + 'delivery_status': result['delivery_status'], + 'manifests': result['manifest'] + }) + response = {'airways': airways} + return self.response(response) + @http.route('/api/sale_order/invoiced', auth='public', methods=['GET']) def get_sale_order_invoiced_by_partner_id(self, **kw): if not self.authenticate(): @@ -481,3 +512,4 @@ class SaleOrder(controller.Controller): } return self.response(data) +
\ No newline at end of file diff --git a/indoteknik_custom/__manifest__.py b/indoteknik_custom/__manifest__.py index dfe22fd2..91eb4166 100755 --- a/indoteknik_custom/__manifest__.py +++ b/indoteknik_custom/__manifest__.py @@ -85,6 +85,7 @@ 'views/voucher.xml', 'views/bill_receipt.xml', 'views/account_move_multi_update.xml', + 'views/airway_bill.xml', 'report/report.xml', 'report/report_banner_banner.xml', 'report/report_banner_banner2.xml', diff --git a/indoteknik_custom/models/__init__.py b/indoteknik_custom/models/__init__.py index 5b8fcc54..54e24563 100755 --- a/indoteknik_custom/models/__init__.py +++ b/indoteknik_custom/models/__init__.py @@ -69,6 +69,8 @@ from . import manufacturing from . import requisition from . import token_storage from . import product_sla +from . import airway_bill +from . import airway_bill_manifest from . import account_move_due_extension from . import voucher from . import bill_receipt diff --git a/indoteknik_custom/models/airway_bill.py b/indoteknik_custom/models/airway_bill.py new file mode 100644 index 00000000..463272b4 --- /dev/null +++ b/indoteknik_custom/models/airway_bill.py @@ -0,0 +1,197 @@ +from odoo import models, fields +from datetime import datetime, timedelta +import logging +import requests +import json + +_logger = logging.getLogger(__name__) + +_key = '7ac9883688da043b50cc32f0e3070bb6' +_url = 'https://pro.rajaongkir.com/api/waybill' + +class AirwayBill(models.Model): + _name = 'airway.bill' + _rec_name = 'number' + + do_id = fields.Many2one('stock.picking', string='DO') + so_id = fields.Many2one('sale.order', string='SO') + number = fields.Char(string='Resi', help='Nomor Resi') + manifest_ids = fields.One2many('airway.bill.manifest', 'waybill_id', string='Airway Bill Lines', auto_join=True) + delivered = fields.Boolean(string='Delivered', help='terkirim atau belum / true or false') + response = fields.Char(string='Response', help='hasil history tracking dalam format json') + way_bill_date = fields.Char(string='Way Bill Date', compute='_compute_way_bill_datetime') + weight = fields.Char(string='Weight ', compute='_compute_way_bill_weight') + origin = fields.Char(string='Origin', compute='_compute_way_bill_origin') + destination = fields.Char(string='Destination', compute='_compute_way_bill_destination') + shipper_name = fields.Char(string='Shipper Name', compute='_compute_way_bill_shipper_name') + shipper_address1 = fields.Char(string='Shipper Address 1', compute='_compute_way_bill_shipper_address1') + shipper_address2 = fields.Char(string='Shipper Address 2', compute='_compute_way_bill_shipper_address2') + shipper_address3 = fields.Char(string='Shipper Address 3', compute='_compute_way_bill_shipper_address3') + shipper_city = fields.Char(string='Shipper City', compute='_compute_way_bill_shipper_city') + receiver_name = fields.Char(string='Receiver Name', compute='_compute_way_bill_receiver_name') + receiver_address1 = fields.Char(string='Receiver Address 1', compute='_compute_way_bill_receiver_address1') + receiver_address2 = fields.Char(string='Receiver Address 2', compute='_compute_way_bill_receiver_address2') + receiver_address3 = fields.Char(string='Receiver Address 3', compute='_compute_way_bill_receiver_address3') + receiver_city = fields.Char(string='Receiver City', compute='_compute_way_bill_receiver_city') + status = fields.Char(string='Status', compute='_compute_way_bill_status') + pod_receiver = fields.Char(string='Pod Receiver', compute='_compute_way_bill_pod_receiver') + pod_datetime = fields.Char(string='Pod Date', compute='_compute_way_bill_pod_datetime') + + def decode_response(self): + self.ensure_one() + return self._json_decode(self.response) + + def _fetch(self): + # jne, pos, tiki, wahana, jnt, rpx, sap, sicepat, jet, dse, dan first + carrier_ids = [51, 53, 54, 7, 57, 55, 59, 59, 27, 60, 62, 64] + + delta_time = datetime.now() - timedelta(days=30) # Last 30 days + delta_time = delta_time.strftime('%Y-%m-%d %H:%M:%S') + query = [ + '|', + ('waybill_id.delivered', '=', False), + ('date_done', '>', delta_time), + ('delivery_tracking_no', '!=', False), + ('delivery_tracking_no', 'not ilike', '-'), + ('carrier_id', 'in', carrier_ids), + ] + outs = self.env['stock.picking'].search(query, order='id') + for out in outs: + rajaongkir = self.env['rajaongkir.kurir'].search([('delivery_carrier_id', '=', out.carrier_id.id)]) + history = self._get_waybill_history(out.delivery_tracking_no, rajaongkir.name) + if not history: + continue + delivered = history['rajaongkir']['result']['delivered'] + values = { + 'do_id': out.id, + 'so_id': out.sale_id.id, + 'number': out.delivery_tracking_no, + 'delivered': delivered, + 'response': history, + } + waybill = out.waybill_id + if not waybill: + waybill = self.create(values) + + waybill.response = json.dumps(history, indent=2, ensure_ascii=False) + waybill.manifest_ids.unlink() + self.env['airway.bill.manifest'].generate_airway_bill_line(waybill) + + def _get_waybill_history(self, way_bill_number=0, shipper=0): + headers = { + 'content-type': 'application/x-www-form-urlencoded', + 'key': _key, + } + + data = { + 'waybill': way_bill_number, + 'courier': shipper, + } + + response = requests.post(_url, headers=headers, data=data) + return self._json_decode(response.text) + + def _json_decode(self, content): + try: + response = json.loads(content) + return response + except: + return False + + def _get_history(self, key): + response = self.decode_response() + if not response: + return response + + if response.get('raja_ongkir', {}): + raja_ongkir = response.get('raja_ongkir', {}) + elif response.get('rajaongkir', {}): + raja_ongkir = response.get('rajaongkir', {}) + result = raja_ongkir.get('result', {}) + return result.get(key) + + def _compute_way_bill(self, airway, key, attribute): + details = airway._get_history('details') + delivery_status = airway._get_history('delivery_status') + value = None + if details and key in details: + value = details.get(key) + elif delivery_status and key in delivery_status: + value = delivery_status.get(key) + setattr(airway, attribute, value if value else '-') + + def _compute_way_bill_datetime(self): + for airway in self: + self._compute_way_bill(airway, 'waybill_date', 'way_bill_date') + + def _compute_way_bill_weight(self): + for airway in self: + self._compute_way_bill(airway, 'weight', 'weight') + + def _compute_way_bill_origin(self): + for airway in self: + self._compute_way_bill(airway, 'origin', 'origin') + + def _compute_way_bill_destination(self): + for airway in self: + self._compute_way_bill(airway, 'destination', 'destination') + + def _compute_way_bill_shipper_name(self): + for airway in self: + self._compute_way_bill(airway, 'shippper_name', 'shipper_name') + + def _compute_way_bill_shipper_address1(self): + for airway in self: + self._compute_way_bill(airway, 'shipper_address1', 'shipper_address1') + + def _compute_way_bill_shipper_address2(self): + for airway in self: + self._compute_way_bill(airway, 'shipper_address2', 'shipper_address2') + + def _compute_way_bill_shipper_address3(self): + for airway in self: + self._compute_way_bill(airway, 'shipper_address3', 'shipper_address3') + + def _compute_way_bill_shipper_city(self): + for airway in self: + self._compute_way_bill(airway, 'shipper_city', 'shipper_city') + + def _compute_way_bill_receiver_name(self): + for airway in self: + self._compute_way_bill(airway, 'receiver_name', 'receiver_name') + + def _compute_way_bill_receiver_address1(self): + for airway in self: + self._compute_way_bill(airway, 'receiver_address1', 'receiver_address1') + + def _compute_way_bill_receiver_address2(self): + for airway in self: + self._compute_way_bill(airway, 'receiver_address2', 'receiver_address2') + + def _compute_way_bill_receiver_address3(self): + for airway in self: + self._compute_way_bill(airway, 'receiver_address3', 'receiver_address3') + + def _compute_way_bill_receiver_city(self): + for airway in self: + self._compute_way_bill(airway, 'receiver_city', 'receiver_city') + + def _compute_way_bill_status(self): + for airway in self: + self._compute_way_bill(airway, 'status', 'status') + + def _compute_way_bill_pod_receiver(self): + for airway in self: + self._compute_way_bill(airway, 'pod_receiver', 'pod_receiver') + + def _compute_way_bill_pod_datetime(self): + for airway in self: + details = airway._get_history('delivery_status') + if details: + pod_date = details['pod_date'] + pod_time = details['pod_time'] + airway.pod_datetime = pod_date+' '+pod_time + else: + airway.pod_datetime = '-' + +
\ No newline at end of file diff --git a/indoteknik_custom/models/airway_bill_manifest.py b/indoteknik_custom/models/airway_bill_manifest.py new file mode 100644 index 00000000..2e16be2c --- /dev/null +++ b/indoteknik_custom/models/airway_bill_manifest.py @@ -0,0 +1,33 @@ +from odoo import models, fields +import logging + +_logger = logging.getLogger(__name__) + +class AirwayBillManifest(models.Model): + _name = 'airway.bill.manifest' + _description = 'Airway B ill Line' + _order = 'waybill_id, id' + + waybill_id = fields.Many2one('airway.bill', string='Airway Ref', required=True, ondelete='cascade', index=True, copy=False) + code = fields.Char('Code') + description = fields.Char('Description') + datetime = fields.Datetime('Datetime') + city = fields.Char('City') + + + def generate_airway_bill_line(self, waybill): + history = waybill.decode_response() + manifests = history['rajaongkir']['result']['manifest'] or [] + for manifest in manifests: + code = manifest['manifest_code'] + description = manifest['manifest_description'] + date = manifest['manifest_date'] + time = manifest['manifest_time'] + city = manifest['city_name'] + self.create({ + 'waybill_id': waybill.id, + 'code': code, + 'description': description, + 'datetime': date+' '+time, + 'city': city, + })
\ No newline at end of file diff --git a/indoteknik_custom/models/stock_picking.py b/indoteknik_custom/models/stock_picking.py index 2ddb5f75..4d1df7ee 100644 --- a/indoteknik_custom/models/stock_picking.py +++ b/indoteknik_custom/models/stock_picking.py @@ -68,6 +68,7 @@ class StockPicking(models.Model): ('hold', 'Hold by Sales'), ('not_paid', 'Customer belum bayar') ], string='Note', help='jika field ini diisi maka tidak akan dihitung ke lead time') + waybill_id = fields.One2many(comodel_name='airway.bill', inverse_name='do_id', string='Airway Bill') def action_create_invoice_from_mr(self): """Create the invoice associated to the PO. diff --git a/indoteknik_custom/security/ir.model.access.csv b/indoteknik_custom/security/ir.model.access.csv index 6e11bc5b..b3dce428 100755 --- a/indoteknik_custom/security/ir.model.access.csv +++ b/indoteknik_custom/security/ir.model.access.csv @@ -63,4 +63,6 @@ access_product_sla,access.product_sla,model_product_sla,,1,1,1,1 access_voucher,access.voucher,model_voucher,,1,1,1,1 access_bill_receipt,access.bill.receipt,model_bill_receipt,,1,1,1,1 access_bill_receipt_line,access.bill.receipt.line,model_bill_receipt_line,,1,1,1,1 -access_account_move_multi_update,access.account.move.multi_update,model_account_move_multi_update,,1,1,1,1
\ No newline at end of file +access_account_move_multi_update,access.account.move.multi_update,model_account_move_multi_update,,1,1,1,1 +access_airway_bill,access.airway.bill,model_airway_bill,,1,1,1,1 +access_airway_bill_manifest,access.airway.bill.manifest,model_airway_bill_manifest,,1,1,1,1 diff --git a/indoteknik_custom/views/airway_bill.xml b/indoteknik_custom/views/airway_bill.xml new file mode 100644 index 00000000..bbfd3991 --- /dev/null +++ b/indoteknik_custom/views/airway_bill.xml @@ -0,0 +1,105 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<odoo> + <record id="airway_bill_tree" model="ir.ui.view"> + <field name="name">airway.bill.tree</field> + <field name="model">airway.bill</field> + <field name="arch" type="xml"> + <tree> + <field name="number" /> + <field name="so_id" /> + <field name="do_id" /> + <field name="delivered" /> + </tree> + </field> + </record> + + <record id="airway_bill_form" model="ir.ui.view"> + <field name="name">airway.bill.form</field> + <field name="model">airway.bill</field> + <field name="arch" type="xml"> + <form> + <sheet> + <group> + <group> + <field name="number" /> + <field name="so_id" /> + <field name="do_id" /> + <field name="delivered" /> + </group> + </group> + <notebook> + <page string="Airway Bill"> + <field name="manifest_ids" readonly='1'> + <tree> + <field name="code"/> + <field name="description"/> + <field name="datetime"/> + <field name="city"/> + </tree> + </field> + </page> + <page string="Details"> + <group> + <group string="Shipper"> + <field name="shipper_name"/> + <field name="shipper_city"/> + <field name="shipper_address1"/> + <field name="shipper_address2"/> + <field name="shipper_address3"/> + </group> + <group string="Receiver"> + <field name="receiver_name"/> + <field name="receiver_city"/> + <field name="receiver_address1"/> + <field name="receiver_address2"/> + <field name="receiver_address3"/> + </group> + <group string="Other Info"> + <field name="way_bill_date"/> + <field name="weight"/> + <field name="origin"/> + <field name="destination"/> + </group> + </group> + </page> + <page string="Delivery Status"> + <group> + <group> + <field name="status"/> + <field name="pod_receiver"/> + <field name="pod_datetime"/> + </group> + </group> + </page> + </notebook> + </sheet> + </form> + </field> + </record> + + <record id="airway_bill_action" model="ir.actions.act_window"> + <field name="name">Airway Bill</field> + <field name="type">ir.actions.act_window</field> + <field name="res_model">airway.bill</field> + <field name="view_mode">tree,form</field> + </record> + + <record id="cron_airway_bill_fetch" model="ir.cron"> + <field name="name">Airway Bill: Fetch</field> + <field name="interval_number">1</field> + <field name="interval_type">days</field> + <field name="numbercall">-1</field> + <field name="doall" eval="False"/> + <field name="model_id" ref="model_airway_bill"/> + <field name="code">model._fetch()</field> + <field name="state">code</field> + <field name="priority">75</field> + <field name="active">True</field> + </record> + + <menuitem id="menu_airway_bill" + name="Airway Bill" + action="airway_bill_action" + parent="stock.menu_stock_warehouse_mgmt" + sequence="200"/> +</odoo>
\ No newline at end of file |
