From 3286de7f2d48f913ad1aa477b49155047ebb742c Mon Sep 17 00:00:00 2001 From: Miqdad Date: Wed, 27 Aug 2025 13:11:17 +0700 Subject: Regenerate midtrans via website --- indoteknik_api/controllers/api_v1/sale_order.py | 128 +++++++++--------------- 1 file changed, 49 insertions(+), 79 deletions(-) (limited to 'indoteknik_api') diff --git a/indoteknik_api/controllers/api_v1/sale_order.py b/indoteknik_api/controllers/api_v1/sale_order.py index 374b49a2..d4038a64 100644 --- a/indoteknik_api/controllers/api_v1/sale_order.py +++ b/indoteknik_api/controllers/api_v1/sale_order.py @@ -116,14 +116,12 @@ class SaleOrder(controller.Controller): if not params['valid']: return self.response(code=400, description=params) - partner_child_ids = self.get_partner_child_ids( - params['value']['partner_id']) + partner_child_ids = self.get_partner_child_ids(params['value']['partner_id']) domain = [('partner_id', 'in', partner_child_ids)] context = params['value']['context'] if context == 'quotation': - domain += ["|", "|", ("state", "=", "draft"), - ("state", "=", "sent"), ("state", "=", "cancel")] + domain += ["|", "|", ("state", "=", "draft"), ("state", "=", "sent"), ("state", "=", "cancel")] if not context: domain += ["|", ("state", "=", "sale"), ("state", "=", "done")] @@ -135,39 +133,28 @@ class SaleOrder(controller.Controller): ('product_id.name', 'ilike', name), ('product_id.default_code', 'ilike', name), ]) - sale_order_ids_from_lines = order_lines.mapped('order_id.id') - domain += ['|', '|', ('name', 'ilike', name), ('partner_purchase_order_name', 'ilike', name), ('id', 'in', sale_order_ids_from_lines) ] - + if params['value']['site']: site = params['value']['site'].replace(' ', '%') - domain += [ - ('partner_id.site_id.name', 'ilike', '%' + site + '%') - ] + domain += [('partner_id.site_id.name', 'ilike', '%' + site + '%')] status = params['value'].get('status') if status: if status == 'quotation': domain += [('state', '=', 'draft')] domain += [('approval_status', '=', False)] - elif status == 'cancel': domain += [('state', '=', 'cancel')] - elif status == 'diproses': - domain += [ - ('state', '=', 'draft'), - ('approval_status', 'in', ['pengajuan1', 'pengajuan2']), - ] - + domain += [('state', '=', 'draft'), ('approval_status', 'in', ['pengajuan1', 'pengajuan2'])] elif status in ['dikemas', 'dikirim', 'selesai', 'partial']: domain += [('state', '=', 'sale')] - elif status == 'all': domain += [] @@ -179,7 +166,7 @@ class SaleOrder(controller.Controller): elif params['value']['sort'] == 'desc': order = 'amount_total desc' - # Filter berdasarkan tanggal order + # Filter tanggal try: if params['value']['startDate'] and params['value']['endDate']: start_date = datetime.strptime(params['value']['startDate'], '%d/%m/%Y').strftime('%Y-%m-%d 00:00:00') @@ -190,22 +177,17 @@ class SaleOrder(controller.Controller): domain.append(('date_order', '>=', start_date)) domain.append(('date_order', '<=', end_date)) - except ValueError: return self.response(code=400, description="Invalid date format. Use 'DD/MM/YYYY'.") + sale_orders = request.env['sale.order'].search(domain, order=order) - - sale_orders = request.env['sale.order'].search( - domain, order=order) + # Filter status pengiriman (tetap sama) status = params['value'].get('status') if status in ['dikemas', 'dikirim', 'selesai', 'partial']: filtered_orders = [] for sale_order in sale_orders: - bu_pickings = [ - p for p in sale_order.picking_ids - if p.picking_type_id and p.picking_type_id.id == 29 - ] + bu_pickings = [p for p in sale_order.picking_ids if p.picking_type_id and p.picking_type_id.id == 29] total = len(bu_pickings) done_pickings = [p for p in bu_pickings if p.state == 'done'] done_with_driver = [p for p in done_pickings if p.sj_return_date] @@ -217,69 +199,57 @@ class SaleOrder(controller.Controller): filtered_orders.append(sale_order) elif status == 'selesai' and len(done_pickings) == total and len(done_pickings) > 0 and len(done_with_driver) == total: filtered_orders.append(sale_order) - elif status == 'partial' and ( - len(done_pickings) != total or - (done_with_driver and done_without_driver) - ): + elif status == 'partial' and (len(done_pickings) != total or (done_with_driver and done_without_driver)): filtered_orders.append(sale_order) else: filtered_orders = sale_orders filtered_orders_paginated = filtered_orders[offset: offset + limit] + # === Tambahan: payment summary per SO === + CBD_PAYMENT_TERM_ID = 26 + ALLOWED_UNSETTLED = {'', 'expire', 'pending', 'challenge', 'cancel'} # belum settlement + def _is_website_order(so): + # Sesuaikan kalau perlu spesifik id + # return bool(so.source_id and so.source_id.id == 59) + name = (so.source_id and so.source_id.name or '').lower() + return 'web' in name or 'site' in name or bool(so.source_id) + + sale_orders_payload = [] + for so in filtered_orders_paginated: + item = request.env['sale.order'].api_v1_single_response(so) + + so_state = so.state or '' + pay_term_id = so.payment_term_id.id if so.payment_term_id else None + pay_status = (getattr(so, 'payment_status', '') or '').strip().lower() + from_web = _is_website_order(so) + + is_quotation = so_state in ('draft', 'sent') + is_cbd = (pay_term_id == CBD_PAYMENT_TERM_ID) + ok_status = (pay_status in ALLOWED_UNSETTLED) + + eligible = bool(is_quotation and is_cbd and ok_status and from_web) + + # tambahkan field baru (camelCase biar enak dipakai di Next) + item.update({ + 'eligibleContinue': eligible, + 'paymentSummary': { + 'eligible': eligible, + 'soState': so_state, + 'paymentTermId': pay_term_id, + 'paymentStatus': pay_status, + 'sourceId': so.source_id.id if so.source_id else None, + 'redirectUrl': getattr(so, 'payment_link_midtrans', '') or '', + } + }) + sale_orders_payload.append(item) + data = { 'sale_order_total': len(filtered_orders), - 'sale_orders': [request.env['sale.order'].api_v1_single_response(x) for x in filtered_orders_paginated] + 'sale_orders': sale_orders_payload } - return self.response(data) - @http.route(PREFIX_PARTNER + 'sale_order/', auth='public', method=['GET', 'OPTIONS']) - @controller.Controller.must_authorized() - def partner_get_sale_order_detail(self, **kw): - params = self.get_request_params(kw, { - 'partner_id': ['number'], - 'id': ['number'], - }) - if not params['valid']: - return self.response(code=400, description=params) - - partner_child_ids = self.get_partner_child_ids(params['value']['partner_id']) - domain = [('id', '=', params['value']['id']), ('partner_id', 'in', partner_child_ids)] - data = {} - sale_order = request.env['sale.order'].search(domain) - if sale_order: - data = request.env['sale.order'].api_v1_single_response(sale_order, context='with_detail') - if sale_order.expected_ready_to_ship: - bulan_id = [ - "Januari", "Februari", "Maret", "April", "Mei", "Juni", - "Juli", "Agustus", "September", "Oktober", "November", "Desember" - ] - tanggal = sale_order.expected_ready_to_ship.day - bulan = bulan_id[sale_order.expected_ready_to_ship.month - 1] - tahun = sale_order.expected_ready_to_ship.year - data['expected_ready_to_ship'] = f"{tanggal} {bulan} {tahun}" - if sale_order.eta_date_start: - bulan_id = [ - "Januari", "Februari", "Maret", "April", "Mei", "Juni", - "Juli", "Agustus", "September", "Oktober", "November", "Desember" - ] - tanggal = sale_order.eta_date_start.day - bulan = bulan_id[sale_order.eta_date_start.month - 1] - tahun = sale_order.eta_date_start.year - data['eta_date_start'] = f"{tanggal} {bulan} {tahun}" - - if sale_order.eta_date: - bulan_id = [ - "Januari", "Februari", "Maret", "April", "Mei", "Juni", - "Juli", "Agustus", "September", "Oktober", "November", "Desember" - ] - tanggal = sale_order.eta_date.day - bulan = bulan_id[sale_order.eta_date.month - 1] - tahun = sale_order.eta_date.year - data['eta_date_end'] = f"{tanggal} {bulan} {tahun}" - - return self.response(data) @http.route(PREFIX_PARTNER + 'sale_order//checkout', auth='public', method=['POST', 'OPTIONS'], csrf=False) @controller.Controller.must_authorized(private=True, private_key='partner_id') -- cgit v1.2.3 From 3a1c84158be32915ab9a30877e26c6e48733ba2b Mon Sep 17 00:00:00 2001 From: Miqdad Date: Thu, 28 Aug 2025 10:02:36 +0700 Subject: push --- indoteknik_api/controllers/api_v1/sale_order.py | 44 +++++++++++++++---------- 1 file changed, 26 insertions(+), 18 deletions(-) (limited to 'indoteknik_api') diff --git a/indoteknik_api/controllers/api_v1/sale_order.py b/indoteknik_api/controllers/api_v1/sale_order.py index d4038a64..fbbb9479 100644 --- a/indoteknik_api/controllers/api_v1/sale_order.py +++ b/indoteknik_api/controllers/api_v1/sale_order.py @@ -206,40 +206,47 @@ class SaleOrder(controller.Controller): filtered_orders_paginated = filtered_orders[offset: offset + limit] - # === Tambahan: payment summary per SO === + # === Tambahan ringkasan + (opsional) auto-regenerate link Midtrans === CBD_PAYMENT_TERM_ID = 26 - ALLOWED_UNSETTLED = {'', 'expire', 'pending', 'challenge', 'cancel'} # belum settlement + ALLOWED_UNSETTLED = {'', 'expire', 'cancel', 'null', '[null]'} # sesuai syaratmu + def _is_website_order(so): - # Sesuaikan kalau perlu spesifik id - # return bool(so.source_id and so.source_id.id == 59) - name = (so.source_id and so.source_id.name or '').lower() - return 'web' in name or 'site' in name or bool(so.source_id) + # kalau source website fix id=59, ini paling aman + return bool(so.source_id and so.source_id.id == 59) sale_orders_payload = [] for so in filtered_orders_paginated: item = request.env['sale.order'].api_v1_single_response(so) - so_state = so.state or '' - pay_term_id = so.payment_term_id.id if so.payment_term_id else None - pay_status = (getattr(so, 'payment_status', '') or '').strip().lower() - from_web = _is_website_order(so) + # ---- 4 syarat kamu ---- + approval_ok = (so.approval_status in ('pengajuan1', 'pengajuan2')) + source_ok = _is_website_order(so) + term_ok = bool(so.payment_term_id and so.payment_term_id.id == CBD_PAYMENT_TERM_ID) + pay_status = (getattr(so, 'payment_status', '') or '').strip().lower() + payment_ok = (pay_status in ALLOWED_UNSETTLED) - is_quotation = so_state in ('draft', 'sent') - is_cbd = (pay_term_id == CBD_PAYMENT_TERM_ID) - ok_status = (pay_status in ALLOWED_UNSETTLED) + eligible = bool(approval_ok and source_ok and term_ok and payment_ok) - eligible = bool(is_quotation and is_cbd and ok_status and from_web) + # Jika eligible & link kosong, auto-generate SEKARANG (tanpa endpoint baru) + redirect_url = getattr(so, 'payment_link_midtrans', '') or '' + if eligible and not redirect_url: + try: + so.sudo().generate_payment_link_midtrans_sales_order() + redirect_url = getattr(so, 'payment_link_midtrans', '') or '' + except Exception as e: + # jangan gagalkan list; cukup lanjut tanpa link + _logger.warning(f'Autogenerate Midtrans gagal untuk SO {so.id}: {e}') - # tambahkan field baru (camelCase biar enak dipakai di Next) + # sisipkan ke payload (pakai camelCase agar enak di FE) item.update({ 'eligibleContinue': eligible, 'paymentSummary': { 'eligible': eligible, - 'soState': so_state, - 'paymentTermId': pay_term_id, + 'approvalStatus': so.approval_status or '', 'paymentStatus': pay_status, + 'paymentTermId': so.payment_term_id.id if so.payment_term_id else None, 'sourceId': so.source_id.id if so.source_id else None, - 'redirectUrl': getattr(so, 'payment_link_midtrans', '') or '', + 'redirectUrl': redirect_url, } }) sale_orders_payload.append(item) @@ -251,6 +258,7 @@ class SaleOrder(controller.Controller): return self.response(data) + @http.route(PREFIX_PARTNER + 'sale_order//checkout', auth='public', method=['POST', 'OPTIONS'], csrf=False) @controller.Controller.must_authorized(private=True, private_key='partner_id') def partner_checkout_sale_order_by_id(self, **kw): -- cgit v1.2.3 From 576c49b3260e9d34c86e2da04461dff4bb16e0de Mon Sep 17 00:00:00 2001 From: Miqdad Date: Thu, 28 Aug 2025 10:46:34 +0700 Subject: Push --- indoteknik_api/controllers/api_v1/sale_order.py | 48 ++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) (limited to 'indoteknik_api') diff --git a/indoteknik_api/controllers/api_v1/sale_order.py b/indoteknik_api/controllers/api_v1/sale_order.py index fbbb9479..b48c5a34 100644 --- a/indoteknik_api/controllers/api_v1/sale_order.py +++ b/indoteknik_api/controllers/api_v1/sale_order.py @@ -208,7 +208,7 @@ class SaleOrder(controller.Controller): # === Tambahan ringkasan + (opsional) auto-regenerate link Midtrans === CBD_PAYMENT_TERM_ID = 26 - ALLOWED_UNSETTLED = {'', 'expire', 'cancel', 'null', '[null]'} # sesuai syaratmu + ALLOWED_UNSETTLED = {'', 'expire', 'cancel'} # sesuai syaratmu def _is_website_order(so): # kalau source website fix id=59, ini paling aman @@ -256,7 +256,53 @@ class SaleOrder(controller.Controller): 'sale_orders': sale_orders_payload } return self.response(data) + + @http.route(PREFIX_PARTNER + 'sale_order/', auth='public', method=['GET', 'OPTIONS']) + @controller.Controller.must_authorized() + def partner_get_sale_order_detail(self, **kw): + params = self.get_request_params(kw, { + 'partner_id': ['number'], + 'id': ['number'], + }) + if not params['valid']: + return self.response(code=400, description=params) + partner_child_ids = self.get_partner_child_ids(params['value']['partner_id']) + domain = [('id', '=', params['value']['id']), ('partner_id', 'in', partner_child_ids)] + data = {} + sale_order = request.env['sale.order'].search(domain) + if sale_order: + data = request.env['sale.order'].api_v1_single_response(sale_order, context='with_detail') + if sale_order.expected_ready_to_ship: + bulan_id = [ + "Januari", "Februari", "Maret", "April", "Mei", "Juni", + "Juli", "Agustus", "September", "Oktober", "November", "Desember" + ] + tanggal = sale_order.expected_ready_to_ship.day + bulan = bulan_id[sale_order.expected_ready_to_ship.month - 1] + tahun = sale_order.expected_ready_to_ship.year + data['expected_ready_to_ship'] = f"{tanggal} {bulan} {tahun}" + if sale_order.eta_date_start: + bulan_id = [ + "Januari", "Februari", "Maret", "April", "Mei", "Juni", + "Juli", "Agustus", "September", "Oktober", "November", "Desember" + ] + tanggal = sale_order.eta_date_start.day + bulan = bulan_id[sale_order.eta_date_start.month - 1] + tahun = sale_order.eta_date_start.year + data['eta_date_start'] = f"{tanggal} {bulan} {tahun}" + + if sale_order.eta_date: + bulan_id = [ + "Januari", "Februari", "Maret", "April", "Mei", "Juni", + "Juli", "Agustus", "September", "Oktober", "November", "Desember" + ] + tanggal = sale_order.eta_date.day + bulan = bulan_id[sale_order.eta_date.month - 1] + tahun = sale_order.eta_date.year + data['eta_date_end'] = f"{tanggal} {bulan} {tahun}" + + return self.response(data) @http.route(PREFIX_PARTNER + 'sale_order//checkout', auth='public', method=['POST', 'OPTIONS'], csrf=False) -- cgit v1.2.3 From c6f2111d3872604c6cdd0901c1ee2fde5edb59de Mon Sep 17 00:00:00 2001 From: Miqdad Date: Thu, 28 Aug 2025 13:39:55 +0700 Subject: Done --- indoteknik_api/controllers/api_v1/sale_order.py | 13 ++++++++++++- indoteknik_api/models/sale_order.py | 14 +++++++++----- 2 files changed, 21 insertions(+), 6 deletions(-) (limited to 'indoteknik_api') diff --git a/indoteknik_api/controllers/api_v1/sale_order.py b/indoteknik_api/controllers/api_v1/sale_order.py index b48c5a34..2d697ae1 100644 --- a/indoteknik_api/controllers/api_v1/sale_order.py +++ b/indoteknik_api/controllers/api_v1/sale_order.py @@ -151,8 +151,19 @@ class SaleOrder(controller.Controller): domain += [('approval_status', '=', False)] elif status == 'cancel': domain += [('state', '=', 'cancel')] + elif status == 'belum_bayar': + domain += [ + ('state', '=', 'draft'), + ('approval_status', 'in', ['pengajuan1', 'pengajuan2']), + ('payment_status', 'in', [False, None, '', 'pending' ,'expire']) + ] elif status == 'diproses': - domain += [('state', '=', 'draft'), ('approval_status', 'in', ['pengajuan1', 'pengajuan2'])] + domain += [ + ('state', '=', 'draft'), + ('approval_status', 'in', ['pengajuan1', 'pengajuan2']), + ('payment_status', '!=', False), + ('payment_status', 'not in', ['', 'pending', 'expire']), + ] elif status in ['dikemas', 'dikirim', 'selesai', 'partial']: domain += [('state', '=', 'sale')] elif status == 'all': diff --git a/indoteknik_api/models/sale_order.py b/indoteknik_api/models/sale_order.py index 9be03927..c59dead9 100644 --- a/indoteknik_api/models/sale_order.py +++ b/indoteknik_api/models/sale_order.py @@ -60,13 +60,17 @@ class SaleOrder(models.Model): # 'tracking_number': picking.delivery_tracking_no or '', # 'delivered': picking.waybill_id.delivered or picking.driver_arrival_date != False or picking.sj_return_date != False, }) + if sale_order.state == 'cancel': data['status'] = 'cancel' - if sale_order.state == 'draft' and sale_order.approval_status == False: - data['status'] = 'draft' - if sale_order.state == 'draft' and sale_order.approval_status in ['pengajuan1', 'pengajuan2']: - data['status'] = 'waiting' - + elif sale_order.state == 'draft': + if not sale_order.approval_status: + data['status'] = 'draft' + elif sale_order.approval_status in ('pengajuan1', 'pengajuan2'): + if sale_order.payment_status in ('', 'pending', False, None, 'expire'): + data['status'] = 'belum_bayar' + elif sale_order.payment_status not in ['', 'pending', False, None, 'expire']: + data['status'] = 'waiting' if sale_order.state == 'sale': bu_pickings = [ -- cgit v1.2.3 From d672d8745f5157d4cf3ff17907a3ca0881b68901 Mon Sep 17 00:00:00 2001 From: Miqdad Date: Thu, 28 Aug 2025 14:24:48 +0700 Subject: Show bayar sekarang in detail transaction --- indoteknik_api/controllers/api_v1/sale_order.py | 37 +++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'indoteknik_api') diff --git a/indoteknik_api/controllers/api_v1/sale_order.py b/indoteknik_api/controllers/api_v1/sale_order.py index 2d697ae1..16fcd449 100644 --- a/indoteknik_api/controllers/api_v1/sale_order.py +++ b/indoteknik_api/controllers/api_v1/sale_order.py @@ -284,6 +284,43 @@ class SaleOrder(controller.Controller): sale_order = request.env['sale.order'].search(domain) if sale_order: data = request.env['sale.order'].api_v1_single_response(sale_order, context='with_detail') + + CBD_PAYMENT_TERM_ID = 26 + ALLOWED_UNSETTLED = {'', 'expire', 'pending'} # kalau mau ikutkan 'pending', tinggal tambahkan di set ini + + def _is_website_order(so): + # aman kalau source website fix id=59 + return bool(so.source_id and so.source_id.id == 59) + + pay_status = (getattr(sale_order, 'payment_status', '') or '').strip().lower() + eligible = ( + sale_order.approval_status in ('pengajuan1', 'pengajuan2') and + _is_website_order(sale_order) and + sale_order.payment_term_id and sale_order.payment_term_id.id == CBD_PAYMENT_TERM_ID and + pay_status in ALLOWED_UNSETTLED + ) + + redirect_url = getattr(sale_order, 'payment_link_midtrans', '') or '' + if eligible and not redirect_url: + try: + sale_order.sudo().generate_payment_link_midtrans_sales_order() + redirect_url = getattr(sale_order, 'payment_link_midtrans', '') or '' + except Exception as e: + _logger.warning(f'Autogenerate Midtrans gagal untuk SO {sale_order.id}: {e}') + + # sisipkan ke payload (snake_case; FE kamu sudah biasa auto-camelCase) + data.update({ + 'eligible_continue': eligible, + 'payment_summary': { + 'eligible': eligible, + 'approval_status': sale_order.approval_status or '', + 'payment_status': pay_status, + 'payment_term_id': sale_order.payment_term_id.id if sale_order.payment_term_id else None, + 'source_id': sale_order.source_id.id if sale_order.source_id else None, + 'redirect_url': redirect_url, + } + }) + if sale_order.expected_ready_to_ship: bulan_id = [ "Januari", "Februari", "Maret", "April", "Mei", "Juni", -- cgit v1.2.3 From f41e635755bb8092d9a85ccc0a0cb675afc7af00 Mon Sep 17 00:00:00 2001 From: Miqdad Date: Sun, 31 Aug 2025 12:17:35 +0700 Subject: oke --- indoteknik_api/controllers/api_v1/sale_order.py | 159 ++++++++++++------------ 1 file changed, 82 insertions(+), 77 deletions(-) (limited to 'indoteknik_api') diff --git a/indoteknik_api/controllers/api_v1/sale_order.py b/indoteknik_api/controllers/api_v1/sale_order.py index 16fcd449..339fee4d 100644 --- a/indoteknik_api/controllers/api_v1/sale_order.py +++ b/indoteknik_api/controllers/api_v1/sale_order.py @@ -22,7 +22,7 @@ class SaleOrder(controller.Controller): }) sale_order_line = request.env['sale.order.line'].search([ - ('product_id', '=', product_id), + ('product_id', '=', product_id), ('order_id', '=', so_id) ], limit=1) @@ -41,7 +41,7 @@ class SaleOrder(controller.Controller): return self.response('work') else: return self.response('Sale order line not found', status=404) - + @http.route(prefix + "sale_order_number", auth='public', method=['GET', 'OPTIONS']) @controller.Controller.must_authorized() def get_number_sale_order(self, **kw): @@ -135,10 +135,10 @@ class SaleOrder(controller.Controller): ]) sale_order_ids_from_lines = order_lines.mapped('order_id.id') domain += ['|', '|', - ('name', 'ilike', name), - ('partner_purchase_order_name', 'ilike', name), - ('id', 'in', sale_order_ids_from_lines) - ] + ('name', 'ilike', name), + ('partner_purchase_order_name', 'ilike', name), + ('id', 'in', sale_order_ids_from_lines) + ] if params['value']['site']: site = params['value']['site'].replace(' ', '%') @@ -155,7 +155,7 @@ class SaleOrder(controller.Controller): domain += [ ('state', '=', 'draft'), ('approval_status', 'in', ['pengajuan1', 'pengajuan2']), - ('payment_status', 'in', [False, None, '', 'pending' ,'expire']) + ('payment_status', 'in', [False, None, '', 'pending', 'expire']) ] elif status == 'diproses': domain += [ @@ -193,7 +193,7 @@ class SaleOrder(controller.Controller): sale_orders = request.env['sale.order'].search(domain, order=order) - # Filter status pengiriman (tetap sama) + # Filter status pengiriman status = params['value'].get('status') if status in ['dikemas', 'dikirim', 'selesai', 'partial']: filtered_orders = [] @@ -206,49 +206,39 @@ class SaleOrder(controller.Controller): if status == 'dikemas' and len(done_pickings) == 0: filtered_orders.append(sale_order) - elif status == 'dikirim' and len(done_pickings) == total and len(done_pickings) > 0 and len(done_without_driver) == total: + elif status == 'dikirim' and len(done_pickings) == total and len(done_pickings) > 0 and len( + done_without_driver) == total: filtered_orders.append(sale_order) - elif status == 'selesai' and len(done_pickings) == total and len(done_pickings) > 0 and len(done_with_driver) == total: + elif status == 'selesai' and len(done_pickings) == total and len(done_pickings) > 0 and len( + done_with_driver) == total: filtered_orders.append(sale_order) - elif status == 'partial' and (len(done_pickings) != total or (done_with_driver and done_without_driver)): + elif status == 'partial' and ( + len(done_pickings) != total or (done_with_driver and done_without_driver)): filtered_orders.append(sale_order) else: filtered_orders = sale_orders filtered_orders_paginated = filtered_orders[offset: offset + limit] - # === Tambahan ringkasan + (opsional) auto-regenerate link Midtrans === + # === Ringkasan (tanpa auto-generate) === CBD_PAYMENT_TERM_ID = 26 - ALLOWED_UNSETTLED = {'', 'expire', 'cancel'} # sesuai syaratmu + ALLOWED_CONTINUE = {'', 'pending', 'capture', 'expire', 'cancel'} # boleh munculkan "Bayar Sekarang" def _is_website_order(so): - # kalau source website fix id=59, ini paling aman return bool(so.source_id and so.source_id.id == 59) sale_orders_payload = [] for so in filtered_orders_paginated: item = request.env['sale.order'].api_v1_single_response(so) - # ---- 4 syarat kamu ---- approval_ok = (so.approval_status in ('pengajuan1', 'pengajuan2')) - source_ok = _is_website_order(so) - term_ok = bool(so.payment_term_id and so.payment_term_id.id == CBD_PAYMENT_TERM_ID) - pay_status = (getattr(so, 'payment_status', '') or '').strip().lower() - payment_ok = (pay_status in ALLOWED_UNSETTLED) - - eligible = bool(approval_ok and source_ok and term_ok and payment_ok) + source_ok = _is_website_order(so) + term_ok = bool(so.payment_term_id and so.payment_term_id.id == CBD_PAYMENT_TERM_ID) + pay_status = (getattr(so, 'payment_status', '') or '').strip().lower() + eligible = bool(approval_ok and source_ok and term_ok and pay_status in ALLOWED_CONTINUE) - # Jika eligible & link kosong, auto-generate SEKARANG (tanpa endpoint baru) redirect_url = getattr(so, 'payment_link_midtrans', '') or '' - if eligible and not redirect_url: - try: - so.sudo().generate_payment_link_midtrans_sales_order() - redirect_url = getattr(so, 'payment_link_midtrans', '') or '' - except Exception as e: - # jangan gagalkan list; cukup lanjut tanpa link - _logger.warning(f'Autogenerate Midtrans gagal untuk SO {so.id}: {e}') - # sisipkan ke payload (pakai camelCase agar enak di FE) item.update({ 'eligibleContinue': eligible, 'paymentSummary': { @@ -267,13 +257,14 @@ class SaleOrder(controller.Controller): 'sale_orders': sale_orders_payload } return self.response(data) - + @http.route(PREFIX_PARTNER + 'sale_order/', auth='public', method=['GET', 'OPTIONS']) @controller.Controller.must_authorized() def partner_get_sale_order_detail(self, **kw): params = self.get_request_params(kw, { 'partner_id': ['number'], 'id': ['number'], + 'ensure_payment_link': [], # optional flag }) if not params['valid']: return self.response(code=400, description=params) @@ -281,34 +272,47 @@ class SaleOrder(controller.Controller): partner_child_ids = self.get_partner_child_ids(params['value']['partner_id']) domain = [('id', '=', params['value']['id']), ('partner_id', 'in', partner_child_ids)] data = {} + sale_order = request.env['sale.order'].search(domain) if sale_order: data = request.env['sale.order'].api_v1_single_response(sale_order, context='with_detail') CBD_PAYMENT_TERM_ID = 26 - ALLOWED_UNSETTLED = {'', 'expire', 'pending'} # kalau mau ikutkan 'pending', tinggal tambahkan di set ini + ALLOWED_CONTINUE = {'', 'pending', 'capture', 'expire', 'cancel'} def _is_website_order(so): - # aman kalau source website fix id=59 return bool(so.source_id and so.source_id.id == 59) pay_status = (getattr(sale_order, 'payment_status', '') or '').strip().lower() eligible = ( - sale_order.approval_status in ('pengajuan1', 'pengajuan2') and - _is_website_order(sale_order) and - sale_order.payment_term_id and sale_order.payment_term_id.id == CBD_PAYMENT_TERM_ID and - pay_status in ALLOWED_UNSETTLED + sale_order.approval_status in ('pengajuan1', 'pengajuan2') and + _is_website_order(sale_order) and + sale_order.payment_term_id and sale_order.payment_term_id.id == CBD_PAYMENT_TERM_ID and + pay_status in ALLOWED_CONTINUE ) redirect_url = getattr(sale_order, 'payment_link_midtrans', '') or '' - if eligible and not redirect_url: - try: - sale_order.sudo().generate_payment_link_midtrans_sales_order() - redirect_url = getattr(sale_order, 'payment_link_midtrans', '') or '' - except Exception as e: - _logger.warning(f'Autogenerate Midtrans gagal untuk SO {sale_order.id}: {e}') - # sisipkan ke payload (snake_case; FE kamu sudah biasa auto-camelCase) + ensure_raw = params['value'].get('ensure_payment_link') + ensure_flag = False + if ensure_raw is not None: + s = str(ensure_raw).strip().lower() + ensure_flag = s not in ('', '0', 'false', 'no', 'none') + + if ensure_flag and eligible: + should_generate = False + if not redirect_url: + should_generate = True + elif pay_status in ('expire', 'cancel'): + should_generate = True + + if should_generate: + try: + sale_order.sudo().generate_payment_link_midtrans_sales_order() + redirect_url = getattr(sale_order, 'payment_link_midtrans', '') or '' + except Exception as e: + _logger.warning(f'Generate Midtrans gagal untuk SO {sale_order.id}: {e}') + data.update({ 'eligible_continue': eligible, 'payment_summary': { @@ -321,6 +325,7 @@ class SaleOrder(controller.Controller): } }) + # formatting tanggal (tetap sama) if sale_order.expected_ready_to_ship: bulan_id = [ "Januari", "Februari", "Maret", "April", "Mei", "Juni", @@ -330,6 +335,7 @@ class SaleOrder(controller.Controller): bulan = bulan_id[sale_order.expected_ready_to_ship.month - 1] tahun = sale_order.expected_ready_to_ship.year data['expected_ready_to_ship'] = f"{tanggal} {bulan} {tahun}" + if sale_order.eta_date_start: bulan_id = [ "Januari", "Februari", "Maret", "April", "Mei", "Juni", @@ -352,7 +358,6 @@ class SaleOrder(controller.Controller): return self.response(data) - @http.route(PREFIX_PARTNER + 'sale_order//checkout', auth='public', method=['POST', 'OPTIONS'], csrf=False) @controller.Controller.must_authorized(private=True, private_key='partner_id') def partner_checkout_sale_order_by_id(self, **kw): @@ -379,12 +384,12 @@ class SaleOrder(controller.Controller): sale_order.approval_status = 'pengajuan2' elif sale_order._requires_approval_margin_manager(): sale_order.approval_status = 'pengajuan1' - + data = request.env['sale.order'].api_v1_single_response( sale_order, context='with_detail') return self.response(data) - + @http.route(PREFIX_PARTNER + 'sale_order//approve', auth='public', method=['POST', 'OPTIONS'], csrf=False) @controller.Controller.must_authorized(private=True, private_key='partner_id') def partner_approve_sale_order_by_id(self, **kw): @@ -392,27 +397,27 @@ class SaleOrder(controller.Controller): 'partner_id': ['number'], 'id': ['number'] }) - + if not params['valid']: return self.response(code=400, description=params) - + value = params['value'] partner_child_ids = self.get_partner_child_ids(value['partner_id']) - + sale_order = request.env['sale.order'].search([ ('id', '=', value['id']), ('partner_id', 'in', partner_child_ids) ]) if not sale_order: return self.response(code=404, description='Sale Order not found') - + partner = request.env['res.partner'].browse(value['partner_id']) if not partner.web_role: return self.response(code=400, description='Unauthorized') - + if partner.web_role: sale_order.web_approval = 'cust_%s' % partner.web_role - + if sale_order.web_approval in ['cust_procurement', 'cust_director']: if sale_order._requires_approval_margin_leader(): sale_order.approval_status = 'pengajuan2' @@ -420,7 +425,7 @@ class SaleOrder(controller.Controller): sale_order.approval_status = 'pengajuan1' return self.response('success') - + @http.route(PREFIX_PARTNER + 'sale_order//reject', auth='public', method=['POST', 'OPTIONS'], csrf=False) @controller.Controller.must_authorized(private=True, private_key='partner_id') def partner_reject_sale_order_by_id(self, **kw): @@ -428,27 +433,27 @@ class SaleOrder(controller.Controller): 'partner_id': ['number'], 'id': ['number'] }) - + if not params['valid']: return self.response(code=400, description=params) - + value = params['value'] partner_child_ids = self.get_partner_child_ids(value['partner_id']) - + sale_order = request.env['sale.order'].search([ ('id', '=', value['id']), ('partner_id', 'in', partner_child_ids) ]) if not sale_order: return self.response(code=404, description='Sale Order not found') - + partner = request.env['res.partner'].browse(value['partner_id']) if not partner.web_role: return self.response(code=400, description='Unauthorized') - + if partner.web_role: sale_order.web_approval = 'cust_%s' % partner.web_role - + sale_order.state = 'cancel' sale_order.approval_status = False @@ -519,7 +524,7 @@ class SaleOrder(controller.Controller): sale_order = request.env['sale.order'].sudo().search_read([('id', '=', id)], ['name']) # pdf, type = request.env['ir.actions.report'].sudo().search([('report_name', '=', 'quotation_so_new')]).render_jasper([id], {}) pdf, type = request.env['ir.actions.report'].sudo().search([('report_name', '=', 'indoteknik_custom.report_saleorder_website')])._render_qweb_pdf([id]) - + if pdf and len(sale_order) > 0: return rest_api.response_attachment({ 'content': pdf, @@ -550,27 +555,27 @@ class SaleOrder(controller.Controller): sale_order.state = 'cancel' data = sale_order.id return self.response(data) - + @http.route(prefix + 'user//sale_order/checkout', auth='public', method=['GET', 'OPTIONS'], csrf=False) @controller.Controller.must_authorized(private=True, private_key='user_id') def get_user_checkout_so(self, user_id, **kw): m_voucher = request.env['voucher'] m_cart = request.env['website.user.cart'] - + voucher_code = kw.get('voucher') voucher_shipping_code = kw.get('voucher_shipping') source = kw.get('source') - + voucher = m_voucher.search([('code', '=', voucher_code), ('apply_type', 'in', ['all', 'brand'])], limit=1) voucher_shipping = m_voucher.search([('code', '=', voucher_shipping_code), ('apply_type', '=', 'shipping')], limit=1) result = m_cart.with_context(price_for="web").get_user_checkout( - user_id, - voucher=voucher, - voucher_shipping=voucher_shipping, + user_id, + voucher=voucher, + voucher_shipping=voucher_shipping, source=source ) return self.response(result) - + @http.route(PREFIX_PARTNER + 'sale_order/checkout', auth='public', method=['POST', 'OPTIONS'], csrf=False) @controller.Controller.must_authorized() def create_partner_sale_order(self, **kw): @@ -616,7 +621,7 @@ class SaleOrder(controller.Controller): main_partner = partner_invoice.get_main_parent() _logger.info( f"Partner Info - Sales: {sales_partner.id}, Invoice: {partner_invoice.id}, Main: {main_partner.id}") - + def _get_request_context(params, kw): # 1) kw (querystring di route) ctx = kw.get('context') @@ -654,7 +659,7 @@ class SaleOrder(controller.Controller): f"form={repr(request.httprequest.form.get('context'))}, " f"json={(request.httprequest.get_json(force=False, silent=True) or {}).get('context') if hasattr(request.httprequest,'get_json') else None}, " f"normalized={ctx}") - + payment_term_id_value = 26 ctx = str((kw.get('context') or '')) @@ -679,7 +684,7 @@ class SaleOrder(controller.Controller): payment_term_id_value = term.id except Exception as e: _logger.warning(f"Gagal resolve payment term dari user: {e}") - + parameters = { 'warehouse_id': 8, 'carrier_id': 1, @@ -839,7 +844,7 @@ class SaleOrder(controller.Controller): except Exception as e: _logger.error(f"Error in create_partner_sale_order: {str(e)}", exc_info=True) return self.response(code=500, description=str(e)) - + @http.route(PREFIX_PARTNER + 'sale-order//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): @@ -854,8 +859,8 @@ class SaleOrder(controller.Controller): for airway_bill in airway_bills: data = airway_bill.decode_response() delivery_order = airway_bill.do_id - result = data['rajaongkir']['result'] - + result = data['rajaongkir']['result'] + manifests_data = [] for manifest in airway_bill.manifest_ids: manifest_data = { @@ -865,7 +870,7 @@ class SaleOrder(controller.Controller): 'city': manifest.city, } manifests_data.append(manifest_data) - + airways.append({ 'delivery_order': { 'name': delivery_order.name, @@ -873,7 +878,7 @@ class SaleOrder(controller.Controller): 'receiver_name': airway_bill.receiver_name, 'receiver_city': airway_bill.receiver_city, }, - 'delivered': result['delivered'], + 'delivered': result['delivered'], 'waybill_number': result['summary']['waybill_number'], 'delivery_status': result['delivery_status'], 'manifests': manifests_data @@ -881,7 +886,7 @@ class SaleOrder(controller.Controller): 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(): -- cgit v1.2.3 From 8cf34c73b9276f88499b056c0a7070a3464f3367 Mon Sep 17 00:00:00 2001 From: Miqdad Date: Mon, 1 Sep 2025 14:54:15 +0700 Subject: fix finish transactions --- indoteknik_api/controllers/api_v1/sale_order.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indoteknik_api') diff --git a/indoteknik_api/controllers/api_v1/sale_order.py b/indoteknik_api/controllers/api_v1/sale_order.py index 339fee4d..accc7531 100644 --- a/indoteknik_api/controllers/api_v1/sale_order.py +++ b/indoteknik_api/controllers/api_v1/sale_order.py @@ -87,8 +87,8 @@ class SaleOrder(controller.Controller): 'amount_tax': sale.amount_tax, 'amount_total': sale.amount_total, 'expected_ready_to_ship': f"{sale.expected_ready_to_ship.day} {INDONESIAN_MONTHS[sale.expected_ready_to_ship.month]} {sale.expected_ready_to_ship.year}", - 'eta_date_start': f"{sale.eta_date_start.day} {INDONESIAN_MONTHS[sale.eta_date_start.month]} {sale.eta_date_start.year}", - 'eta_date_end': f"{sale.eta_date.day} {INDONESIAN_MONTHS[sale.eta_date.month]} {sale.eta_date.year}", + # 'eta_date_start': f"{sale.eta_date_start.day} {INDONESIAN_MONTHS[sale.eta_date_start.month]} {sale.eta_date_start.year}", + # 'eta_date_end': f"{sale.eta_date.day} {INDONESIAN_MONTHS[sale.eta_date.month]} {sale.eta_date.year}", 'product_name': product_name, 'product_not_in_id': product_not_in_id, 'details': [request.env['sale.order.line'].api_single_response(x, context='with_detail') for x in sale.order_line] -- cgit v1.2.3 From 69c9579636182d81b1b6da010f29f5efda6f88a7 Mon Sep 17 00:00:00 2001 From: Miqdad Date: Mon, 8 Sep 2025 15:13:38 +0700 Subject: Fix oauth google --- indoteknik_api/controllers/api_v1/user.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indoteknik_api') diff --git a/indoteknik_api/controllers/api_v1/user.py b/indoteknik_api/controllers/api_v1/user.py index dde30fec..c75e4954 100644 --- a/indoteknik_api/controllers/api_v1/user.py +++ b/indoteknik_api/controllers/api_v1/user.py @@ -89,7 +89,8 @@ class User(controller.Controller): 'name': name, 'login': email, 'oauth_provider_id': request.env.ref('auth_oauth.provider_google').id, - 'sel_groups_1_9_10': 9 + 'sel_groups_1_9_10': 9, + 'active': True } user = request.env['res.users'].create(user_data) -- cgit v1.2.3