diff options
| -rw-r--r-- | indoteknik_api/controllers/api_v1/product.py | 102 | ||||
| -rw-r--r-- | indoteknik_api/controllers/api_v1/stock_picking.py | 29 | ||||
| -rw-r--r-- | indoteknik_api/models/sale_order.py | 16 | ||||
| -rwxr-xr-x | indoteknik_custom/__manifest__.py | 1 | ||||
| -rwxr-xr-x | indoteknik_custom/models/__init__.py | 1 | ||||
| -rwxr-xr-x | indoteknik_custom/models/sale_order.py | 22 | ||||
| -rw-r--r-- | indoteknik_custom/models/sale_order_delay.py | 31 | ||||
| -rw-r--r-- | indoteknik_custom/models/stock_picking.py | 121 | ||||
| -rwxr-xr-x | indoteknik_custom/security/ir.model.access.csv | 1 | ||||
| -rw-r--r-- | indoteknik_custom/views/sale_order_delay.xml | 44 |
10 files changed, 258 insertions, 110 deletions
diff --git a/indoteknik_api/controllers/api_v1/product.py b/indoteknik_api/controllers/api_v1/product.py index a88c3368..7d6ebdb6 100644 --- a/indoteknik_api/controllers/api_v1/product.py +++ b/indoteknik_api/controllers/api_v1/product.py @@ -51,7 +51,7 @@ class Product(controller.Controller): additional_days = request.env['sale.order'].get_days_until_next_business_day(start_date) include_instant = True - if(len(products) != len(product_ids)): + if(len(products) == len(product_ids)): products_data_params = {product["id"] : product for product in product_data } all_fast_products = all( @@ -96,27 +96,40 @@ class Product(controller.Controller): }) @http.route(prefix + 'product_variant/<id>/stock', auth='public', methods=['GET', 'OPTIONS']) - @controller.Controller.must_authorized() + @controller.Controller.must_authorized() def get_product_template_stock_by_id(self, **kw): id = int(kw.get('id')) date_7_days_ago = datetime.now() - timedelta(days=7) - product = request.env['product.product'].search( - [('id', '=', id)], limit=1) - product_sla = request.env['product.sla'].search( - [('product_variant_id', '=', id)], limit=1) + product_pruchase = request.env['purchase.pricelist'].search([ + ('product_id', '=', id), + ('is_winner', '=', True) + ]) stock_vendor = request.env['stock.vendor'].search([ ('product_variant_id', '=', id), ('write_date', '>=', date_7_days_ago.strftime("%Y-%m-%d %H:%M:%S")) ], limit=1) + + product = product_pruchase.product_id + + vendor_sla = request.env['vendor.sla'].search([('id_vendor', '=', product_pruchase.vendor_id.id)], limit=1) + slatime = 15 + if vendor_sla: + if vendor_sla.unit == 'hari': + vendor_duration = vendor_sla.duration * 24 * 60 + else : + vendor_duration = vendor_sla.duration * 60 + + estimation_sla = (1 * 24 * 60) + vendor_duration + estimation_sla_days = estimation_sla / (24 * 60) + slatime = math.ceil(estimation_sla_days) qty_available = product.qty_free_bandengan - if qty_available < 1 : qty_available = 0 qty = 0 - sla_date = '-' + sla_date = f'{slatime} Hari' # Qty Stock Vendor qty_vendor = stock_vendor.quantity @@ -136,28 +149,89 @@ class Product(controller.Controller): if qty_available > 0: qty = qty_available + total_adem + total_excell - sla_date = product_sla.sla or 1 + sla_date = '1 Hari' elif qty_altama > 0 or qty_vendor > 0: qty = total_adem if qty_altama > 0 else total_excell - sla_date = product_sla.sla + sla_date = f'{slatime} Hari' else: - sla_date = product_sla.sla + sla_date = f'{slatime} Hari' except: print('error') else: if qty_available > 0: qty = qty_available - sla_date = product_sla.sla or 'Indent' + sla_date = f'{slatime} Hari' elif qty_vendor > 0: qty = total_excell - sla_date = '2-4 Hari' + sla_date = f'{slatime} Hari' data = { 'qty': qty, 'sla_date': sla_date } - return self.response(data, headers=[('Cache-Control', 'max-age=600, private')]) + return self.response(data, headers=[('Cache-Control', 'max-age=600, private')]) + # def get_product_template_stock_by_id(self, **kw): + # id = int(kw.get('id')) + # date_7_days_ago = datetime.now() - timedelta(days=7) + # product = request.env['product.product'].search( + # [('id', '=', id)], limit=1) + # product_sla = request.env['product.sla'].search( + # [('product_variant_id', '=', id)], limit=1) + # stock_vendor = request.env['stock.vendor'].search([ + # ('product_variant_id', '=', id), + # ('write_date', '>=', date_7_days_ago.strftime("%Y-%m-%d %H:%M:%S")) + # ], limit=1) + + # qty_available = product.qty_free_bandengan + + + # if qty_available < 1 : + # qty_available = 0 + + # qty = 0 + # sla_date = '-' + + # # Qty Stock Vendor + # qty_vendor = stock_vendor.quantity + # qty_vendor -= int(qty_vendor * 0.1) + # qty_vendor = math.ceil(float(qty_vendor)) + # total_excell = qty_vendor + + # is_altama_product = product.x_manufacture.id in [10, 122, 89] + # if is_altama_product: + # try: + # # Qty Altama + # qty_altama = request.env['product.template'].get_stock_altama( + # product.default_code) + # qty_altama -= int(qty_altama * 0.1) + # qty_altama = math.ceil(float(qty_altama)) + # total_adem = qty_altama + + # if qty_available > 0: + # qty = qty_available + total_adem + total_excell + # sla_date = product_sla.sla or 1 + # elif qty_altama > 0 or qty_vendor > 0: + # qty = total_adem if qty_altama > 0 else total_excell + # sla_date = product_sla.sla + # else: + # sla_date = product_sla.sla + # except: + # print('error') + # else: + # if qty_available > 0: + # qty = qty_available + # sla_date = product_sla.sla or 'Indent' + # elif qty_vendor > 0: + # qty = total_excell + # sla_date = '2-4 Hari' + + # data = { + # 'qty': qty, + # 'sla_date': sla_date + # } + + # return self.response(data, headers=[('Cache-Control', 'max-age=600, private')]) @http.route(prefix + 'product_variant/<id>/qty_available', auth='public', methods=['GET', 'OPTIONS']) @controller.Controller.must_authorized() diff --git a/indoteknik_api/controllers/api_v1/stock_picking.py b/indoteknik_api/controllers/api_v1/stock_picking.py index 31706b99..e16af332 100644 --- a/indoteknik_api/controllers/api_v1/stock_picking.py +++ b/indoteknik_api/controllers/api_v1/stock_picking.py @@ -3,6 +3,7 @@ from odoo import http from odoo.http import request from pytz import timezone from datetime import datetime +import json class StockPicking(controller.Controller): @@ -101,7 +102,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']) @@ -141,13 +141,12 @@ class StockPicking(controller.Controller): 'name': picking_data.name }) - @http.route(prefix + 'webhook/biteship', type='json', auth='public', methods=['POST'], csrf=False) + @http.route(prefix + 'webhook/biteship', auth='public', methods=['POST'], csrf=False) def udpate_status_from_bitehsip(self, **kw): try: - if not request.jsonrequest: - return "ok" + data = kw # Ambil data JSON dari request - data = request.jsonrequest # Ambil data JSON dari request + print(data) event = data.get('event') # Handle Event Berdasarkan Jenisnya @@ -158,27 +157,29 @@ class StockPicking(controller.Controller): elif event == "order.waybill_id": self.process_order_waybill(data) - return {'success': True, 'message': f'Webhook {event} received'} + return self.response({'success': True}) except Exception as e: - return {'success': False, 'message': str(e)} + return self.response({'success': False, '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()}) + if picking_model : + if data.get('status') == 'picked': + result = picking_model.write({'driver_departure_date': datetime.utcnow()}) + print(result) + elif data.get('status') == 'delivered': + picking_model.write({'driver_arrival_date': datetime.utcnow()}) 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) + picking_model = request.env['stock.picking'].search([('biteship_id', '=', data.get('order_id'))], limit=1) + order = request.env['sale.order'].search([('name', '=', picking_model.sale_id.name)], limit=1) if order: order.write({ 'delivery_amt': 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) + picking_model = request.env['stock.picking'].search([('biteship_id', '=', data.get('order_id'))], limit=1) if picking_model: picking_model.write({ 'biteship_waybill_id': data.get('courier_waybill_id'), diff --git a/indoteknik_api/models/sale_order.py b/indoteknik_api/models/sale_order.py index 727379c5..ce728f95 100644 --- a/indoteknik_api/models/sale_order.py +++ b/indoteknik_api/models/sale_order.py @@ -29,11 +29,23 @@ class SaleOrder(models.Model): 'pickings': [] } for picking in sale_order.picking_ids: + picking_model = self.env['stock.picking'].sudo().search([('id', '=', picking.id)], limit=1) + if not picking_model: + continue + response = picking_model.get_tracking_detail() + data['pickings'].append({ + 'waybill_number' : response['waybill_number'] or '', + 'delivered_date': response['delivered_date'], + 'delivery_order' : { + 'carrier' : response['delivery_order']['carrier'] or '', + 'service' : response['delivery_order']['service'] or '' + }, + 'eta' : response['eta'], 'id': picking.id, 'name': picking.name, - 'tracking_number': picking.delivery_tracking_no or '', - 'delivered': picking.waybill_id.delivered or picking.driver_arrival_date != False or picking.sj_return_date != False, + # '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' diff --git a/indoteknik_custom/__manifest__.py b/indoteknik_custom/__manifest__.py index 8272efc4..dec0f26a 100755 --- a/indoteknik_custom/__manifest__.py +++ b/indoteknik_custom/__manifest__.py @@ -166,6 +166,7 @@ 'views/coretax_faktur.xml', 'views/public_holiday.xml', 'views/stock_inventory.xml', + 'views/sale_order_delay.xml', ], 'demo': [], 'css': [], diff --git a/indoteknik_custom/models/__init__.py b/indoteknik_custom/models/__init__.py index 08fa9803..605d1016 100755 --- a/indoteknik_custom/models/__init__.py +++ b/indoteknik_custom/models/__init__.py @@ -149,4 +149,5 @@ from . import sales_order_koli from . import stock_backorder_confirmation from . import account_payment_register from . import stock_inventory +from . import sale_order_delay from . import approval_invoice_date diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py index 02d61387..3117a330 100755 --- a/indoteknik_custom/models/sale_order.py +++ b/indoteknik_custom/models/sale_order.py @@ -530,7 +530,7 @@ class SaleOrder(models.Model): @api.depends('date_order', 'estimated_arrival_days', 'state', 'estimated_arrival_days_start') def _compute_eta_date(self): - current_date = datetime.now().date() + current_date = datetime.now() for rec in self: if rec.date_order and rec.state not in ['cancel'] and rec.estimated_arrival_days and rec.estimated_arrival_days_start: rec.eta_date = current_date + timedelta(days=rec.estimated_arrival_days) @@ -541,7 +541,19 @@ class SaleOrder(models.Model): def get_days_until_next_business_day(self,start_date=None, *args, **kwargs): - today = start_date or datetime.today().date() + now = start_date or datetime.now() + + # Jika hanya diberikan tanggal (tanpa jam), asumsikan jam 00:00 + if isinstance(now, datetime): + order_datetime = now + else: + order_datetime = datetime.combine(now, datetime.min.time()) + + today = order_datetime.date() + + if order_datetime.time() > datetime.strptime("15:00", "%H:%M").time(): + today += timedelta(days=1) + offset = 0 # Counter jumlah hari yang ditambahkan holiday = self.env['hr.public.holiday'] @@ -602,13 +614,13 @@ class SaleOrder(models.Model): rec.expected_ready_to_ship = False return - current_date = datetime.now().date() + current_date = datetime.now() max_slatime = 1 # Default SLA jika tidak ada slatime = self.calculate_sla_by_vendor(rec.order_line) max_slatime = max(max_slatime, slatime['slatime']) - sum_days = max_slatime + self.get_days_until_next_business_day(current_date) - 1 + sum_days = max_slatime + self.get_days_until_next_business_day(current_date) if not rec.estimated_arrival_days: rec.estimated_arrival_days = sum_days @@ -631,7 +643,7 @@ class SaleOrder(models.Model): max_slatime = 1 # Default SLA jika tidak ada slatime = self.calculate_sla_by_vendor(rec.order_line) max_slatime = max(max_slatime, slatime['slatime']) - sum_days = max_slatime + self.get_days_until_next_business_day(current_date) - 1 + sum_days = max_slatime + self.get_days_until_next_business_day(current_date) eta_minimum = current_date + timedelta(days=sum_days) if expected_date < eta_minimum: diff --git a/indoteknik_custom/models/sale_order_delay.py b/indoteknik_custom/models/sale_order_delay.py new file mode 100644 index 00000000..dfd94650 --- /dev/null +++ b/indoteknik_custom/models/sale_order_delay.py @@ -0,0 +1,31 @@ +from odoo import api, fields, models + + +class SaleOrderDelay(models.Model): + _name = 'sale.order.delay' + _description = 'Sale Order Delay' + _primary_key = 'so_number' + + so_number = fields.Char(string="SO Number", required=True) + days_delayed = fields.Integer(string="Day Delayed or Erly") + status = fields.Selection([ + ('delayed', 'Delayed'), + ('on track', 'On Track'), + ('early', 'Early') + ], string='Status', required=True) + + _sql_constraints = [ + ('unique_so_number', 'unique(so_number)', 'SO Number must be unique!') + ] + + def update_delay(self): + query = "SELECT check_so_delay();" + self.env.cr.execute(query) + + @api.model + def create(self, vals): + return super(SaleOrderDelay, self).create(vals) + + def write(self, vals): + return super(SaleOrderDelay, self).write(vals) +
\ No newline at end of file diff --git a/indoteknik_custom/models/stock_picking.py b/indoteknik_custom/models/stock_picking.py index 8f8ab54d..36129f00 100644 --- a/indoteknik_custom/models/stock_picking.py +++ b/indoteknik_custom/models/stock_picking.py @@ -242,9 +242,6 @@ class StockPicking(models.Model): biteship_id = fields.Char(string="Biteship Respon ID") biteship_tracking_id = fields.Char(string="Biteship Trackcking ID") biteship_waybill_id = fields.Char(string="Biteship Waybill ID") - # estimated_ready_ship_date = fields.Datetime(string='ET Ready to Ship', copy=False, related='sale_id.estimated_ready_ship_date') - # countdown_hours = fields.Float(string='Countdown in Hours', compute='_callculate_sequance', default=False, store=False, compute_sudo=False) - # countdown_ready_to_ship = fields.Char(string='Countdown Ready to Ship', compute='_callculate_sequance', store=False, compute_sudo=False) final_seq = fields.Float(string='Remaining Time') shipping_method_so_id = fields.Many2one('delivery.carrier', string='Shipping Method SO', related='sale_id.carrier_id') state_packing = fields.Selection([('not_packing', 'Belum Packing'), ('packing_done', 'Sudah Packing')], string='Packing Status') @@ -359,54 +356,6 @@ class StockPicking(models.Model): def schduled_update_sequance(self): query = "SELECT update_sequance_stock_picking();" self.env.cr.execute(query) - - - # @api.depends('estimated_ready_ship_date', 'state') - # def _callculate_sequance(self): - # for record in self: - # try : - # if record.estimated_ready_ship_date and record.state not in ('cancel', 'done'): - # rts = record.estimated_ready_ship_date - waktu.now() - # rts_days = rts.days - # rts_hours = divmod(rts.seconds, 3600) - - # estimated_by_erts = rts.total_seconds() / 3600 - - # record.countdown_ready_to_ship = f"{rts_days} days, {rts_hours} hours" - # record.countdown_hours = estimated_by_erts - # else: - # record.countdown_hours = 999999999999 - # record.countdown_ready_to_ship = False - # except Exception as e : - # _logger.error(f"Error calculating sequance {record.id}: {str(e)}") - # print(str(e)) - # return { 'error': str(e) } - - - # @api.depends('estimated_ready_ship_date', 'state') - # def _compute_countdown_hours(self): - # for record in self: - # if record.state in ('cancel', 'done') or not record.estimated_ready_ship_date: - # # Gunakan nilai yang sangat besar sebagai placeholder - # record.countdown_hours = 999999 - # else: - # delta = record.estimated_ready_ship_date - waktu.now() - # record.countdown_hours = delta.total_seconds() / 3600 - - # @api.depends('estimated_ready_ship_date', 'state') - # def _compute_countdown_ready_to_ship(self): - # for record in self: - # if record.state in ('cancel', 'done'): - # record.countdown_ready_to_ship = False - # else: - # if record.estimated_ready_ship_date: - # delta = record.estimated_ready_ship_date - waktu.now() - # days = delta.days - # hours, remainder = divmod(delta.seconds, 3600) - # record.countdown_ready_to_ship = f"{days} days, {hours} hours" - # record.countdown_hours = delta.total_seconds() / 3600 - # else: - # record.countdown_ready_to_ship = False def _compute_lalamove_image_html(self): for record in self: @@ -1471,28 +1420,42 @@ class StockPicking(models.Model): self.ensure_one() order = self.env['sale.order'].search([('name', '=', self.sale_id.name)], limit=1) + + sale_order_delay = self.env['sale.order.delay'].search([('so_number', '=', order.name)], limit=1) response = { 'delivery_order': { 'name': self.name, - 'carrier': self.carrier_id.name or '', - 'service' : order.delivery_service_type or '', + 'carrier': self.carrier_id.name or '-', + 'service' : order.delivery_service_type or '-', 'receiver_name': '', 'receiver_city': '' }, + 'delivered_date': self.driver_departure_date.strftime('%d %b %Y') if self.driver_departure_date != False else '-', 'delivered': False, 'status': self.shipping_status, - 'waybill_number': self.delivery_tracking_no or '', + 'waybill_number': self.delivery_tracking_no or '-', 'delivery_status': None, 'eta': self.generate_eta_delivery(), 'is_biteship': True if self.biteship_id else False, - 'manifests': self.get_manifests() + 'manifests': self.get_manifests(), + 'is_delay': True if sale_order_delay and sale_order_delay.status == 'delayed' else False } if self.biteship_id : histori = self.get_manifest_biteship() - eta_start = order.date_order + timedelta(days=order.estimated_arrival_days_start) - eta_end = order.date_order + timedelta(days=order.estimated_arrival_days) + day_start = order.estimated_arrival_days_start + day_end = order.estimated_arrival_days + if sale_order_delay: + if sale_order_delay.status == 'delayed': + day_start = day_start + sale_order_delay.days_delayed + day_end = day_end + sale_order_delay.days_delayed + elif sale_order_delay.status == 'early': + day_start = day_start - sale_order_delay.days_delayed + day_end = day_end - sale_order_delay.days_delayed + + eta_start = order.date_order + timedelta(days=day_start) + eta_end = order.date_order + timedelta(days=day_end) formatted_eta = f"{eta_start.strftime('%d %b')} - {eta_end.strftime('%d %b %Y')}" response['eta'] = formatted_eta response['manifests'] = histori.get("manifests", []) @@ -1519,7 +1482,6 @@ class StockPicking(models.Model): "Content-Type": "application/json" } - manifests = [] try: @@ -1530,10 +1492,10 @@ class StockPicking(models.Model): 'confirmed' : 'Indoteknik telah melakukan permintaan pick-up', 'allocated' : 'Kurir akan melakukan pick-up pesanan', 'picking_up' : 'Kurir sedang dalam perjalanan menuju lokasi pick-up', - 'picked' : 'Pesanan sudah di pick-up kurir '+result.get("courier", {}).get("name", ""), + 'picked' : 'Pesanan sudah di pick-up kurir '+result.get("courier", {}).get("company", ""), 'on_hold' : 'Pesanan ditahan sementara karena masalah pengiriman', - 'dropping_off' : 'Kurir sudah ditugaskan dan pesanan akan segera diantar ke pembeli', - 'delivered' : 'Pesanan telah sampai dan diterima oleh '+result.get("destination", {}).get("contact_name", "") + 'dropping_off' : 'Kurir sudah ditugaskan dan pesanan akan segera diantar ke pembeli', + 'delivered' : f'Pesanan telah sampai dan diterima oleh <span style="color:#DC2626;">{result.get("destination", {}).get("contact_name", "")}</span>' } if(result.get('success') == True): history = result.get("history", []) @@ -1551,7 +1513,10 @@ class StockPicking(models.Model): "delivered": status } - return manifests + return { + "manifests": [], + "delivered": False + } except Exception as e : _logger.error(f"Error fetching Biteship order for picking {self.id}: {str(e)}") return { 'error': str(e) } @@ -1584,20 +1549,26 @@ class StockPicking(models.Model): def generate_eta_delivery(self): current_date = datetime.datetime.now() - prepare_days = 3 - start_date = self.driver_departure_date or self.create_date - - ead = self.sale_id.estimated_arrival_days or 0 - if not self.driver_departure_date: - ead += prepare_days - - ead_datetime = datetime.timedelta(days=ead) - fastest_eta = start_date + ead_datetime - if not self.driver_departure_date and fastest_eta < current_date: - fastest_eta = current_date + ead_datetime + days_start = self.sale_id.estimated_arrival_days_start or self.sale_id.estimated_arrival_days + days_end = self.sale_id.estimated_arrival_days or (self.sale_id.estimated_arrival_days + 3) + start_date = self.sale_id.create_date + datetime.timedelta(days=days_start) + end_date = self.sale_id.create_date + datetime.timedelta(days=days_end) + + + add_day_start = 0 + add_day_end = 0 + sale_order_delay = self.env['sale.order.delay'].search([('so_number', '=', self.sale_id.name)], limit=1) + if sale_order_delay: + if sale_order_delay.status == 'delayed': + add_day_start = sale_order_delay.days_delayed + add_day_end = sale_order_delay.days_delayed + elif sale_order_delay.status == 'early': + add_day_start = -abs(sale_order_delay.days_delayed) + add_day_end = -abs(sale_order_delay.days_delayed) + + fastest_eta = start_date +datetime.timedelta(days=add_day_start + add_day_start) - longest_days = 3 - longest_eta = fastest_eta + datetime.timedelta(days=longest_days) + longest_eta = end_date + datetime.timedelta(days=add_day_end) format_time = '%d %b %Y' format_time_fastest = '%d %b' if fastest_eta.year == longest_eta.year else format_time diff --git a/indoteknik_custom/security/ir.model.access.csv b/indoteknik_custom/security/ir.model.access.csv index 30088680..46ab4c1f 100755 --- a/indoteknik_custom/security/ir.model.access.csv +++ b/indoteknik_custom/security/ir.model.access.csv @@ -177,4 +177,5 @@ access_stock_inventory,access.stock.inventory,model_stock_inventory,,1,1,1,1 access_cancel_reason_order,cancel.reason.order,model_cancel_reason_order,,1,1,1,0 access_reject_reason_commision,reject.reason.commision,model_reject_reason_commision,,1,1,1,0 access_shipping_option,shipping.option,model_shipping_option,,1,1,1,1 +access_sale_order_delay,sale.order.delay,model_sale_order_delay,,1,1,1,1 access_production_purchase_match,access.production.purchase.match,model_production_purchase_match,,1,1,1,1 diff --git a/indoteknik_custom/views/sale_order_delay.xml b/indoteknik_custom/views/sale_order_delay.xml new file mode 100644 index 00000000..b2aad8eb --- /dev/null +++ b/indoteknik_custom/views/sale_order_delay.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + <record id="view_sale_order_delay_tree" model="ir.ui.view"> + <field name="name">sale.order.delay.tree</field> + <field name="model">sale.order.delay</field> + <field name="arch" type="xml"> + <tree> + <field name="so_number" /> + <field name="days_delayed" /> + <field name="status" /> + </tree> + </field> + </record> + + <record id="sale_order_delay_action" model="ir.actions.act_window"> + <field name="name">Sale Order Delay</field> + <field name="type">ir.actions.act_window</field> + <field name="res_model">sale.order.delay</field> + <field name="view_mode">tree,form</field> + </record> + + <record id="view_sale_order_delay_form" model="ir.ui.view"> + <field name="name">sale.order.delay.form</field> + <field name="model">sale.order.delay</field> + <field name="arch" type="xml"> + <form> + <sheet> + <group> + <field name="so_number" /> + <field name="days_delayed" /> + <field name="status" /> + </group> + </sheet> + </form> + </field> + </record> + + <menuitem id="menu_sale_order_delay" + name="Sale Order Delay" + action="sale_order_delay_action" + parent="sale.product_menu_catalog" + sequence="8" + /> +</odoo>
\ No newline at end of file |
