From 1c5eaef25d30a2f760afaad4f5329a87cc4da3c1 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Wed, 26 Feb 2025 16:30:42 +0700 Subject: CR repeat order --- indoteknik_api/models/sale_order.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/indoteknik_api/models/sale_order.py b/indoteknik_api/models/sale_order.py index 727379c5..0b9881ec 100644 --- a/indoteknik_api/models/sale_order.py +++ b/indoteknik_api/models/sale_order.py @@ -104,11 +104,28 @@ class SaleOrder(models.Model): data.update(data_with_detail) else: data_with_detail = { + 'products': [], 'address': { 'customer': res_users.api_address_response(sale_order.partner_id), } } data.update(data_with_detail) + for line in sale_order.order_line: + product = self.env['product.product'].api_single_response(line.product_id) + product['price'] = { + 'price': line.price_unit, + 'discount_percentage': line.discount, + 'price_discount': line.price_reduce_taxexcl, + 'subtotal': line.price_subtotal + } + product['quantity'] = line.product_uom_qty + product['available_quantity'] = line.product_available_quantity + for data_v2 in sale_order.fulfillment_line_v2: + product_v2 = self.env['product.product'].api_single_response(data_v2.product_id) + if product['id'] == product_v2['id']: + product['so_qty'] = data_v2.so_qty + product['reserved_stock_qty'] = data_v2.reserved_stock_qty + data_with_detail['products'].append(product) return data -- cgit v1.2.3 From d416d5b06fbc4cb7b9c5c2ee2bf2b356faad3fe9 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Fri, 28 Feb 2025 15:34:10 +0700 Subject: add status --- indoteknik_api/controllers/api_v1/sale_order.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/indoteknik_api/controllers/api_v1/sale_order.py b/indoteknik_api/controllers/api_v1/sale_order.py index a7e027c8..b73798b0 100644 --- a/indoteknik_api/controllers/api_v1/sale_order.py +++ b/indoteknik_api/controllers/api_v1/sale_order.py @@ -85,7 +85,8 @@ class SaleOrder(controller.Controller): 'site': [], 'limit': ['default:0', 'number'], 'offset': ['default:0', 'number'], - 'context': [] + 'context': [], + 'status': [] }) limit = params['value']['limit'] offset = params['value']['offset'] @@ -116,7 +117,23 @@ class SaleOrder(controller.Controller): domain += [ ('partner_id.site_id.name', 'ilike', '%' + site + '%') ] - + if params['value']['status']: + if params['value']['status'] == 'quotation': + domain += [('state', '=', 'draft')] + elif params['value']['status'] == 'cancel': + domain += [('state', '=', 'cancel')] + elif params['value']['status'] == 'diterima': + domain += [('state', '=', 'draft')] + domain += [('is_continue_transaction', '=', True)] + domain += [('approval_status', 'in', ['pengajuan1', 'pengajuan2'])] + elif params['value']['status'] == 'diproses': + domain += [('state', '=', 'sale')] + domain += [('picking_ids.state', 'in', ['draft', 'waiting', 'confirmed', 'assigned'])] + elif params['value']['status'] == 'dikirim': + domain += [('state', '=', 'sale')] + domain += [('picking_ids.state', 'not in', ['draft', 'waiting', 'confirmed', 'assigned', 'cancel'])] + elif params['value']['status'] == 'selesai': + domain += [('state', '=', 'done')] sale_orders = request.env['sale.order'].search( domain, offset=offset, limit=limit) data = { -- cgit v1.2.3 From bfb7d3b45bbf780fa77b9abc8a0f1860a50da57c Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Mon, 3 Mar 2025 16:38:40 +0700 Subject: update code --- indoteknik_api/controllers/api_v1/sale_order.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indoteknik_api/controllers/api_v1/sale_order.py b/indoteknik_api/controllers/api_v1/sale_order.py index b73798b0..8723c738 100644 --- a/indoteknik_api/controllers/api_v1/sale_order.py +++ b/indoteknik_api/controllers/api_v1/sale_order.py @@ -124,7 +124,7 @@ class SaleOrder(controller.Controller): domain += [('state', '=', 'cancel')] elif params['value']['status'] == 'diterima': domain += [('state', '=', 'draft')] - domain += [('is_continue_transaction', '=', True)] + # domain += [('is_continue_transaction', '=', True)] domain += [('approval_status', 'in', ['pengajuan1', 'pengajuan2'])] elif params['value']['status'] == 'diproses': domain += [('state', '=', 'sale')] -- cgit v1.2.3 From d7285a4c58256bbadcdd72dc5afbba2cc0b2b491 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Mon, 10 Mar 2025 11:21:30 +0700 Subject: add sort filter --- indoteknik_api/controllers/api_v1/sale_order.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/indoteknik_api/controllers/api_v1/sale_order.py b/indoteknik_api/controllers/api_v1/sale_order.py index 5914a23c..bf03e04d 100644 --- a/indoteknik_api/controllers/api_v1/sale_order.py +++ b/indoteknik_api/controllers/api_v1/sale_order.py @@ -86,7 +86,8 @@ class SaleOrder(controller.Controller): 'limit': ['default:0', 'number'], 'offset': ['default:0', 'number'], 'context': [], - 'status': [] + 'status': [], + 'sort': [], }) limit = params['value']['limit'] offset = params['value']['offset'] @@ -117,6 +118,7 @@ class SaleOrder(controller.Controller): domain += [ ('partner_id.site_id.name', 'ilike', '%' + site + '%') ] + if params['value']['status']: if params['value']['status'] == 'quotation': domain += [('state', '=', 'draft')] @@ -134,8 +136,18 @@ class SaleOrder(controller.Controller): domain += [('picking_ids.state', 'not in', ['draft', 'waiting', 'confirmed', 'assigned', 'cancel'])] elif params['value']['status'] == 'selesai': domain += [('state', '=', 'done')] + + # Sorting + order = None + if params['value']['sort']: + if params['value']['sort'] == 'asc': + order = 'amount_total asc' + elif params['value']['sort'] == 'desc': + order = 'amount_total desc' + sale_orders = request.env['sale.order'].search( - domain, offset=offset, limit=limit) + domain, offset=offset, limit=limit, order=order) + data = { 'sale_order_total': request.env['sale.order'].search_count(domain), 'sale_orders': [request.env['sale.order'].api_v1_single_response(x) for x in sale_orders] -- cgit v1.2.3 From 61fc24442212691483873fa85dc3eacad8b253be Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Wed, 12 Mar 2025 09:38:53 +0700 Subject: fix transaction --- indoteknik_api/controllers/api_v1/sale_order.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/indoteknik_api/controllers/api_v1/sale_order.py b/indoteknik_api/controllers/api_v1/sale_order.py index bf03e04d..3219fc07 100644 --- a/indoteknik_api/controllers/api_v1/sale_order.py +++ b/indoteknik_api/controllers/api_v1/sale_order.py @@ -88,6 +88,8 @@ class SaleOrder(controller.Controller): 'context': [], 'status': [], 'sort': [], + 'startDate': [], + 'endDate': [], }) limit = params['value']['limit'] offset = params['value']['offset'] @@ -145,6 +147,19 @@ class SaleOrder(controller.Controller): elif params['value']['sort'] == 'desc': order = 'amount_total desc' + # Filter berdasarkan tanggal order + if params['value']['startDate'] and params['value']['endDate']: + try: + start_date = datetime.strptime(params['value']['startDate'], '%d/%m/%Y').strftime('%Y-%m-%d 00:00:00') + end_date = datetime.strptime(params['value']['endDate'], '%d/%m/%Y').strftime('%Y-%m-%d 23:59:59') + + 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, offset=offset, limit=limit, order=order) -- cgit v1.2.3 From 84a7a5fde0f5be9c24a5b324087b8726b1b8f01a Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Wed, 12 Mar 2025 16:59:54 +0700 Subject: add sorting dari yg terbaru --- indoteknik_api/models/sale_order.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/indoteknik_api/models/sale_order.py b/indoteknik_api/models/sale_order.py index 0b9881ec..6debf762 100644 --- a/indoteknik_api/models/sale_order.py +++ b/indoteknik_api/models/sale_order.py @@ -28,12 +28,19 @@ class SaleOrder(models.Model): 'date_order': self.env['rest.api'].datetime_to_str(sale_order.date_order, '%d/%m/%Y %H:%M:%S'), 'pickings': [] } - for picking in sale_order.picking_ids: + # Urutkan picking berdasarkan create_date descending + sorted_pickings = sale_order.picking_ids.sorted(key=lambda p: p.create_date, reverse=True) + + for picking in sorted_pickings: data['pickings'].append({ 'id': picking.id, 'name': picking.name, 'tracking_number': picking.delivery_tracking_no or '', + 'carrier_name': picking.carrier_id.name or '', 'delivered': picking.waybill_id.delivered or picking.driver_arrival_date != False or picking.sj_return_date != False, + 'date': self.env['rest.api'].datetime_to_str(picking.driver_departure_date, '%d/%m/%Y'), + 'eta': picking.generate_eta_delivery(), + 'service_type': sale_order.delivery_service_type or '', }) if sale_order.state == 'cancel': data['status'] = 'cancel' -- cgit v1.2.3 From 431229f2a6f1203fbdfe470229e55da8ebd3ea01 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Fri, 14 Mar 2025 16:17:10 +0700 Subject: fix code --- indoteknik_api/models/sale_order.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/indoteknik_api/models/sale_order.py b/indoteknik_api/models/sale_order.py index 6debf762..4fc96386 100644 --- a/indoteknik_api/models/sale_order.py +++ b/indoteknik_api/models/sale_order.py @@ -20,12 +20,14 @@ class SaleOrder(models.Model): 'amount_untaxed': sale_order.amount_untaxed, 'amount_tax': sale_order.amount_tax, 'amount_total': sale_order.grand_total, + 'amount_discount': sale_order.amount_voucher_shipping_disc, 'purchase_order_name': sale_order.partner_purchase_order_name or sale_order.client_order_ref, 'purchase_order_file': True if sale_order.partner_purchase_order_file else False, 'invoice_count': sale_order.invoice_count, 'status': 'draft', 'approval_step': APPROVAL_STEP[sale_order.web_approval] if sale_order.web_approval else 0, 'date_order': self.env['rest.api'].datetime_to_str(sale_order.date_order, '%d/%m/%Y %H:%M:%S'), + 'payment_type': sale_order.payment_type, 'pickings': [] } # Urutkan picking berdasarkan create_date descending @@ -41,6 +43,7 @@ class SaleOrder(models.Model): 'date': self.env['rest.api'].datetime_to_str(picking.driver_departure_date, '%d/%m/%Y'), 'eta': picking.generate_eta_delivery(), 'service_type': sale_order.delivery_service_type or '', + 'weight_total': picking.weight or 0, }) if sale_order.state == 'cancel': data['status'] = 'cancel' -- cgit v1.2.3 From deba962d7368a5c4e30441b5a640102608e3dde6 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Sat, 31 May 2025 08:56:21 +0700 Subject: fix repeat order --- indoteknik_api/controllers/api_v1/sale_order.py | 45 ++++++++++++++++--------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/indoteknik_api/controllers/api_v1/sale_order.py b/indoteknik_api/controllers/api_v1/sale_order.py index 39fa0e13..e87b357e 100644 --- a/indoteknik_api/controllers/api_v1/sale_order.py +++ b/indoteknik_api/controllers/api_v1/sale_order.py @@ -136,24 +136,39 @@ class SaleOrder(controller.Controller): ('partner_id.site_id.name', 'ilike', '%' + site + '%') ] - if params['value']['status']: - if params['value']['status'] == 'quotation': + status = params['value'].get('status') + if status: + if status == 'quotation': domain += [('state', '=', 'draft')] - elif params['value']['status'] == 'cancel': + domain += [('approval_status', '=', False)] + + elif status == 'cancel': domain += [('state', '=', 'cancel')] - elif params['value']['status'] == 'diterima': - domain += [('state', '=', 'draft')] - # domain += [('is_continue_transaction', '=', True)] - domain += [('approval_status', 'in', ['pengajuan1', 'pengajuan2'])] - elif params['value']['status'] == 'diproses': - domain += [('state', '=', 'sale')] - domain += [('picking_ids.state', 'in', ['draft', 'waiting', 'confirmed', 'assigned'])] - elif params['value']['status'] == 'dikirim': - domain += [('state', '=', 'sale')] - domain += [('picking_ids.state', 'not in', ['draft', 'waiting', 'confirmed', 'assigned', 'cancel'])] - elif params['value']['status'] == 'selesai': + + elif status == 'diterima': + domain += [ + ('state', '=', 'draft'), + ('approval_status', 'in', ['pengajuan1', 'pengajuan2']), + ] + + elif status == 'dikirim': + domain += [ + ('state', '=', 'sale'), + ('picking_ids.state', 'in', ['done']) + ] + + elif status == 'diproses': + domain += [ + ('state', '=', 'sale'), + ('picking_ids.state', 'in', ['draft', 'waiting', 'confirmed', 'assigned']) + ] + + elif status == 'selesai': domain += [('state', '=', 'done')] + elif status == 'all': + domain += [] + # Sorting order = None if params['value']['sort']: @@ -190,7 +205,7 @@ class SaleOrder(controller.Controller): def partner_get_sale_order_detail(self, **kw): params = self.get_request_params(kw, { 'partner_id': ['number'], - 'id': ['number'] + 'id': ['number'], }) if not params['valid']: return self.response(code=400, description=params) -- cgit v1.2.3 From a05a1dc3f4c936c0162f66a24f69ca8b236acfea Mon Sep 17 00:00:00 2001 From: Miqdad Date: Thu, 31 Jul 2025 08:17:06 +0700 Subject: add validation when changing payment term when so payment term is not match --- indoteknik_custom/models/sale_order.py | 18 ++++++++++++++++++ indoteknik_custom/views/sale_order.xml | 5 +++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py index 4e36a9fb..47018f52 100755 --- a/indoteknik_custom/models/sale_order.py +++ b/indoteknik_custom/models/sale_order.py @@ -3088,6 +3088,24 @@ class SaleOrder(models.Model): except: pass + #payment term vals + if 'payment_term_id' in vals and any( + order.approval_status in ['pengajuan1', 'pengajuan2', 'approved'] for order in self): + raise UserError( + "Payment Term tidak dapat diubah karena Sales Order sedang dalam proses approval atau sudah diapprove.") + + if 'payment_term_id' in vals: + for order in self: + partner = order.partner_id.parent_id or order.partner_id + customer_payment_term = partner.property_payment_term_id + if vals['payment_term_id'] != customer_payment_term.id: + raise UserError( + f"Payment Term berbeda pada Master Data Customer. " + f"Harap ganti ke '{customer_payment_term.name}' " + f"sesuai dengan payment term yang terdaftar pada customer." + ) + + res = super(SaleOrder, self).write(vals) # Update before margin setelah write diff --git a/indoteknik_custom/views/sale_order.xml b/indoteknik_custom/views/sale_order.xml index e8f41ca3..868bce7b 100755 --- a/indoteknik_custom/views/sale_order.xml +++ b/indoteknik_custom/views/sale_order.xml @@ -355,8 +355,9 @@ - {'readonly': [('approval_status', '=', 'approved'), ('state', 'not in', - ['cancel', 'draft'])]} + {'readonly': ['|', ('approval_status', 'in', ['pengajuan1', 'pengajuan2', 'approved']), + ('state', 'not in', + ['cancel', 'draft'])]} -- cgit v1.2.3 From 8d1af98bb7dab812f91d7d275b4004c4e5b0ff75 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Thu, 31 Jul 2025 08:33:22 +0700 Subject: repeat order fix --- indoteknik_api/controllers/api_v1/sale_order.py | 52 ++++++++++++++++--------- indoteknik_api/models/sale_order.py | 45 +++++++++++---------- 2 files changed, 58 insertions(+), 39 deletions(-) diff --git a/indoteknik_api/controllers/api_v1/sale_order.py b/indoteknik_api/controllers/api_v1/sale_order.py index 3ecaff57..f116f189 100644 --- a/indoteknik_api/controllers/api_v1/sale_order.py +++ b/indoteknik_api/controllers/api_v1/sale_order.py @@ -145,26 +145,14 @@ class SaleOrder(controller.Controller): elif status == 'cancel': domain += [('state', '=', 'cancel')] - elif status == 'diterima': + elif status == 'diproses': domain += [ ('state', '=', 'draft'), ('approval_status', 'in', ['pengajuan1', 'pengajuan2']), ] - elif status == 'dikirim': - domain += [ - ('state', '=', 'sale'), - ('picking_ids.state', 'in', ['done']) - ] - - elif status == 'diproses': - domain += [ - ('state', '=', 'sale'), - ('picking_ids.state', 'in', ['draft', 'waiting', 'confirmed', 'assigned']) - ] - - elif status == 'selesai': - domain += [('state', '=', 'done')] + elif status in ['dikemas', 'dikirim', 'selesai', 'partial']: + domain += [('state', '=', 'sale')] elif status == 'all': domain += [] @@ -191,11 +179,39 @@ class SaleOrder(controller.Controller): sale_orders = request.env['sale.order'].search( - domain, offset=offset, limit=limit, order=order) + domain, order=order) + 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 + ] + 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.driver_arrival_date] + done_without_driver = [p for p in done_pickings if not p.driver_arrival_date] + + 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: + 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) + ): + filtered_orders.append(sale_order) + else: + filtered_orders = sale_orders + + filtered_orders_paginated = filtered_orders[offset: offset + limit] data = { - 'sale_order_total': request.env['sale.order'].search_count(domain), - 'sale_orders': [request.env['sale.order'].api_v1_single_response(x) for x in sale_orders] + 'sale_order_total': len(filtered_orders), + 'sale_orders': [request.env['sale.order'].api_v1_single_response(x) for x in filtered_orders_paginated] } return self.response(data) diff --git a/indoteknik_api/models/sale_order.py b/indoteknik_api/models/sale_order.py index 5427ed07..54b4a6dc 100644 --- a/indoteknik_api/models/sale_order.py +++ b/indoteknik_api/models/sale_order.py @@ -51,29 +51,32 @@ class SaleOrder(models.Model): }) if sale_order.state == 'cancel': data['status'] = 'cancel' - if sale_order.state in ['draft', 'sent']: + if sale_order.state == 'draft' and sale_order.approval_status == False: data['status'] = 'draft' - if sale_order.is_continue_transaction: - data['status'] = 'waiting' - if sale_order.approval_status in ['pengajuan1', 'pengajuan2']: - data['status'] = 'waiting' - if sale_order.state == 'sale': - data['status'] = 'sale' - picking_count = { - 'assigned': 0, - 'done': 0, - } - for picking in sale_order.picking_ids: - if picking.state in ['confirmed', 'assigned']: - picking_count['assigned'] += 1 - if picking.state == 'done': - picking_count['done'] += 1 - if picking_count['done'] > 0: + if sale_order.state == 'draft' and sale_order.approval_status in ['pengajuan1', 'pengajuan2']: + data['status'] = 'waiting' + + + if sale_order.state == 'sale': + bu_pickings = [ + p for p in sale_order.picking_ids + if p.picking_type_id and p.picking_type_id.id == 29 + ] + + # Hitung status masing-masing picking + 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.driver_arrival_date] + done_without_driver = [p for p in done_pickings if not p.driver_arrival_date] + + if len(done_pickings) == 0: + data['status'] = 'sale' + elif len(done_pickings) == total and len(done_pickings) > 0 and len(done_with_driver) == total: + data['status'] = 'done' + elif len(done_pickings) == total and len(done_pickings) > 0 and len(done_without_driver) == total: data['status'] = 'shipping' - if picking_count['assigned'] > 0: - data['status'] = 'partial_shipping' - if sale_order.state == 'done': - data['status'] = 'done' + else: + data['status'] = 'partial_shipping' res_users = self.env['res.users'] if context: -- cgit v1.2.3 From c8d46915cfb2ef9488eea0834c28eed6facfee6c Mon Sep 17 00:00:00 2001 From: Miqdad Date: Thu, 31 Jul 2025 10:18:04 +0700 Subject: hide date po --- indoteknik_custom/views/purchasing_job.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indoteknik_custom/views/purchasing_job.xml b/indoteknik_custom/views/purchasing_job.xml index e3866d84..2466e7be 100644 --- a/indoteknik_custom/views/purchasing_job.xml +++ b/indoteknik_custom/views/purchasing_job.xml @@ -17,7 +17,7 @@ - +