summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorit-fixcomart <it@fixcomart.co.id>2025-09-12 10:49:35 +0700
committerit-fixcomart <it@fixcomart.co.id>2025-09-12 10:49:35 +0700
commit40229df0261970eb3d955de2651cdb1a997bdbaa (patch)
treeb50870b51b682097dea6fd92e548268c7ba596a2
parent7d07a282c134cb5e2a784b73cc477e3f398df57c (diff)
parent73d249fd48d0aeae8ac77946f07668210e12ae7b (diff)
<hafid> fix conflict
-rw-r--r--indoteknik_api/controllers/api_v1/sale_order.py213
-rw-r--r--indoteknik_api/models/sale_order.py14
-rwxr-xr-xindoteknik_custom/__manifest__.py2
-rw-r--r--indoteknik_custom/models/account_move.py28
-rw-r--r--indoteknik_custom/models/approval_payment_term.py3
-rwxr-xr-xindoteknik_custom/models/purchase_order.py2
-rw-r--r--indoteknik_custom/models/refund_sale_order.py1
-rw-r--r--indoteknik_custom/models/res_partner.py11
-rwxr-xr-xindoteknik_custom/models/sale_order.py45
-rw-r--r--indoteknik_custom/models/stock_move.py3
-rw-r--r--indoteknik_custom/report/purchase_report.xml162
-rw-r--r--indoteknik_custom/views/res_partner.xml3
-rwxr-xr-xindoteknik_custom/views/sale_order.xml9
-rw-r--r--indoteknik_custom/views/stock_move_line.xml9
-rw-r--r--indoteknik_custom/views/stock_picking.xml105
15 files changed, 475 insertions, 135 deletions
diff --git a/indoteknik_api/controllers/api_v1/sale_order.py b/indoteknik_api/controllers/api_v1/sale_order.py
index 65894d8a..accc7531 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):
@@ -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,39 @@ 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)
- ]
-
+ ('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 == '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']),
+ ('payment_status', '!=', False),
+ ('payment_status', 'not in', ['', 'pending', 'expire']),
]
-
elif status in ['dikemas', 'dikirim', 'selesai', 'partial']:
domain += [('state', '=', 'sale')]
-
elif status == 'all':
domain += []
@@ -179,7 +177,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 +188,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
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]
@@ -213,25 +206,56 @@ 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)
- ):
+ 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]
+ # === Ringkasan (tanpa auto-generate) ===
+ CBD_PAYMENT_TERM_ID = 26
+ ALLOWED_CONTINUE = {'', 'pending', 'capture', 'expire', 'cancel'} # boleh munculkan "Bayar Sekarang"
+
+ def _is_website_order(so):
+ 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)
+
+ 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()
+ eligible = bool(approval_ok and source_ok and term_ok and pay_status in ALLOWED_CONTINUE)
+
+ redirect_url = getattr(so, 'payment_link_midtrans', '') or ''
+
+ item.update({
+ 'eligibleContinue': eligible,
+ 'paymentSummary': {
+ 'eligible': eligible,
+ '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': redirect_url,
+ }
+ })
+ 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/<id>', auth='public', method=['GET', 'OPTIONS'])
@@ -240,6 +264,7 @@ class SaleOrder(controller.Controller):
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)
@@ -247,9 +272,60 @@ 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_CONTINUE = {'', 'pending', 'capture', 'expire', 'cancel'}
+
+ def _is_website_order(so):
+ 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_CONTINUE
+ )
+
+ redirect_url = getattr(sale_order, 'payment_link_midtrans', '') or ''
+
+ 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': {
+ '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,
+ }
+ })
+
+ # formatting tanggal (tetap sama)
if sale_order.expected_ready_to_ship:
bulan_id = [
"Januari", "Februari", "Maret", "April", "Mei", "Juni",
@@ -259,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",
@@ -307,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/<id>/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):
@@ -320,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'
@@ -348,7 +425,7 @@ class SaleOrder(controller.Controller):
sale_order.approval_status = 'pengajuan1'
return self.response('success')
-
+
@http.route(PREFIX_PARTNER + 'sale_order/<id>/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):
@@ -356,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
@@ -447,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,
@@ -478,27 +555,27 @@ class SaleOrder(controller.Controller):
sale_order.state = 'cancel'
data = sale_order.id
return self.response(data)
-
+
@http.route(prefix + 'user/<user_id>/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):
@@ -544,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')
@@ -582,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 ''))
@@ -607,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,
@@ -767,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/<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):
@@ -782,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 = {
@@ -793,7 +870,7 @@ class SaleOrder(controller.Controller):
'city': manifest.city,
}
manifests_data.append(manifest_data)
-
+
airways.append({
'delivery_order': {
'name': delivery_order.name,
@@ -801,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
@@ -809,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():
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 = [
diff --git a/indoteknik_custom/__manifest__.py b/indoteknik_custom/__manifest__.py
index 31685005..09a3aa6f 100755
--- a/indoteknik_custom/__manifest__.py
+++ b/indoteknik_custom/__manifest__.py
@@ -166,6 +166,7 @@
'report/report_invoice.xml',
'report/report_picking.xml',
'report/report_sale_order.xml',
+ 'report/purchase_report.xml',
'views/vendor_sla.xml',
'views/coretax_faktur.xml',
'views/public_holiday.xml',
@@ -177,6 +178,7 @@
'views/tukar_guling_po.xml',
# 'views/refund_sale_order.xml',
'views/update_date_planned_po_wizard_view.xml',
+ # 'views/reimburse.xml',
],
'demo': [],
'css': [],
diff --git a/indoteknik_custom/models/account_move.py b/indoteknik_custom/models/account_move.py
index c93cfb76..70cd07e4 100644
--- a/indoteknik_custom/models/account_move.py
+++ b/indoteknik_custom/models/account_move.py
@@ -105,6 +105,34 @@ class AccountMove(models.Model):
tracking=True
)
+ # def _check_and_lock_cbd(self):
+ # cbd_term = self.env['account.payment.term'].browse(26)
+ # today = date.today()
+
+ # # Cari semua invoice overdue
+ # overdue_invoices = self.search([
+ # ('move_type', '=', 'out_invoice'),
+ # ('state', '=', 'posted'),
+ # ('payment_state', 'not in', ['paid', 'in_payment', 'reversed']),
+ # ('invoice_date_due', '!=', False),
+ # ('invoice_date_due', '<=', today - timedelta(days=30)),
+ # ], limit=3)
+
+ # _logger.info(f"Found {len(overdue_invoices)} overdue invoices for CBD lock check.")
+ # _logger.info(f"Overdue Invoices: {overdue_invoices.mapped('name')}")
+
+ # # Ambil partner unik dari invoice
+ # partners_to_lock = overdue_invoices.mapped('partner_id').filtered(lambda p: not p.is_cbd_locked)
+ # _logger.info(f"Partners to lock: {partners_to_lock.mapped('name')}")
+
+ # # Lock hanya partner yang belum locked
+ # if partners_to_lock:
+ # partners_to_lock.write({
+ # 'is_cbd_locked': True,
+ # 'property_payment_term_id': cbd_term.id,
+ # })
+
+
def compute_partial_payment(self):
for move in self:
if move.amount_total_signed > 0 and move.amount_residual_signed > 0 and move.payment_state == 'partial':
diff --git a/indoteknik_custom/models/approval_payment_term.py b/indoteknik_custom/models/approval_payment_term.py
index 8618856a..08d91738 100644
--- a/indoteknik_custom/models/approval_payment_term.py
+++ b/indoteknik_custom/models/approval_payment_term.py
@@ -171,7 +171,8 @@ class ApprovalPaymentTerm(models.Model):
'blocking_stage': self.blocking_stage,
'warning_stage': self.warning_stage,
'active_limit': self.active_limit,
- 'property_payment_term_id': self.property_payment_term_id.id
+ 'property_payment_term_id': self.property_payment_term_id.id,
+ 'is_locked_cbd': False,
})
self.approve_date = datetime.utcnow()
self.state = 'approved'
diff --git a/indoteknik_custom/models/purchase_order.py b/indoteknik_custom/models/purchase_order.py
index 50913a80..18811b85 100755
--- a/indoteknik_custom/models/purchase_order.py
+++ b/indoteknik_custom/models/purchase_order.py
@@ -66,7 +66,7 @@ class PurchaseOrder(models.Model):
sale_order = fields.Char(string='Sale Order')
matches_so = fields.Many2many('sale.order', string='Matches SO', compute='_compute_matches_so')
is_create_uangmuka = fields.Boolean(string='Uang Muka?')
- move_id = fields.Many2one('account.move', string='Journal Entries Uang Muka', domain=[('move_type', '=', 'entry')])
+ move_id = fields.Many2one('account.move', string='Journal Entries Uang Muka', domain=[('move_type', '=', 'entry')], copy=False)
logbook_bill_id = fields.Many2one('report.logbook.bill', string='Logbook Bill')
status_printed = fields.Selection([
('not_printed', 'Belum Print'),
diff --git a/indoteknik_custom/models/refund_sale_order.py b/indoteknik_custom/models/refund_sale_order.py
index e981abb5..9bcdd974 100644
--- a/indoteknik_custom/models/refund_sale_order.py
+++ b/indoteknik_custom/models/refund_sale_order.py
@@ -76,6 +76,7 @@ class RefundSaleOrder(models.Model):
transfer_move_id = fields.Many2one(
'account.move',
string="Journal Payment",
+ copy=False,
help="Pilih transaksi salah transfer dari jurnal Uang Muka (journal_id=11) yang tidak terkait SO."
)
diff --git a/indoteknik_custom/models/res_partner.py b/indoteknik_custom/models/res_partner.py
index 148a3fd0..36570e8f 100644
--- a/indoteknik_custom/models/res_partner.py
+++ b/indoteknik_custom/models/res_partner.py
@@ -1,6 +1,6 @@
from odoo import models, fields, api
from odoo.exceptions import UserError, ValidationError
-from datetime import datetime
+from datetime import datetime, timedelta
from odoo.http import request
import re
import requests
@@ -181,10 +181,8 @@ class ResPartner(models.Model):
payment_difficulty = fields.Selection([('bermasalah', 'Bermasalah'),('sulit', 'Sulit'),('agak_sulit', 'Agak Sulit'),('normal', 'Normal')], string='Payment Difficulty', tracking=3)
payment_history_url = fields.Text(string='Payment History URL')
- # no compute
- # payment_diff = fields.Selection([('bermasalah', 'Bermasalah'),('sulit', 'Sulit'),('agak_sulit', 'Agak Sulit'),('normal', 'Normal')], string='Payment Difficulty', tracking=3)
-
- # tidak terpakai
+ is_cbd_locked = fields.Boolean("Locked to CBD?", default=False, tracking=True, help="Jika dicentang, maka partner ini terkunci pada payment term CBD karena memiliki invoice yang sudah jatuh tempo lebih dari 30 hari.")
+
@api.model
def _default_payment_term(self):
@@ -193,9 +191,10 @@ class ResPartner(models.Model):
property_payment_term_id = fields.Many2one(
'account.payment.term',
string='Payment Terms',
- default=_default_payment_term
+ default=_default_payment_term, tracking=3
)
+
@api.depends("street", "street2", "city", "state_id", "country_id", "blok", "nomor", "rt", "rw", "kelurahan_id",
"kecamatan_id")
def _alamat_lengkap_text(self):
diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py
index 903f834b..76d4d7e7 100755
--- a/indoteknik_custom/models/sale_order.py
+++ b/indoteknik_custom/models/sale_order.py
@@ -393,6 +393,26 @@ class SaleOrder(models.Model):
('paid', 'Full Paid'),
('no_invoice', 'No Invoice'),
], string="Payment Status Invoice", compute="_compute_payment_state_custom", store=False)
+ partner_is_cbd_locked = fields.Boolean(
+ string="Partner Locked CBD",
+ compute="_compute_partner_is_cbd_locked"
+ )
+
+ @api.depends('partner_id.is_cbd_locked')
+ def _compute_partner_is_cbd_locked(self):
+ for order in self:
+ order.partner_is_cbd_locked = order.partner_id.is_cbd_locked
+
+
+ @api.constrains('payment_term_id', 'partner_id', 'state')
+ def _check_cbd_lock_sale_order(self):
+ # cbd_term = self.env['account.payment.term'].browse(26)
+ for rec in self:
+ if rec.state == 'draft' and rec.partner_id.is_cbd_locked:
+ # if rec.payment_term_id and rec.payment_term_id != cbd_term:
+ raise ValidationError(
+ "Customer ini terkunci ke CBD, hanya boleh pakai Payment Term CBD."
+ )
@api.depends('invoice_ids.payment_state', 'invoice_ids.amount_total', 'invoice_ids.amount_residual')
def _compute_payment_state_custom(self):
@@ -1899,26 +1919,30 @@ class SaleOrder(models.Model):
# raise UserError('Kelurahan Real Delivery Address harus diisi')
def generate_payment_link_midtrans_sales_order(self):
- # midtrans_url = 'https://app.sandbox.midtrans.com/snap/v1/transactions' # dev - sandbox
- # midtrans_auth = 'Basic U0ItTWlkLXNlcnZlci1uLVY3ZDJjMlpCMFNWRUQyOU95Q1dWWXA6' # dev - sandbox
- midtrans_url = 'https://app.midtrans.com/snap/v1/transactions' # production
- midtrans_auth = 'Basic TWlkLXNlcnZlci1SbGMxZ2gzWGpSVW5scl9JblZzTV9OTnU6' # production
+ # midtrans_url = 'https://app.sandbox.midtrans.com/snap/v1/transactions' # dev - sandbox
+ # midtrans_auth = 'Basic U0ItTWlkLXNlcnZlci1uLVY3ZDJjMlpCMFNWRUQyOU95Q1dWWXA6' # dev - sandbox
+ midtrans_url = 'https://app.midtrans.com/snap/v1/transactions' # production
+ midtrans_auth = 'Basic TWlkLXNlcnZlci1SbGMxZ2gzWGpSVW5scl9JblZzTV9OTnU6' # production
+
so_number = self.name
so_number = so_number.replace('/', '-')
so_grandtotal = math.floor(self.grand_total)
+
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': midtrans_auth,
}
- check_url = f'https://api.midtrans.com/v2/{so_number}/status'
- check_response = requests.get(check_url, headers=headers)
+ # ==== ENV ====
+ # check_url = f'https://api.sandbox.midtrans.com/v2/{so_number}/status' # dev - sandbox
+ check_url = f'https://api.midtrans.com/v2/{so_number}/status' # production
+ # =============================================
+ check_response = requests.get(check_url, headers=headers)
if check_response.status_code == 200:
status_response = check_response.json()
- if status_response.get('transaction_status') == 'expire' or status_response.get(
- 'transaction_status') == 'cancel':
+ if status_response.get('transaction_status') in ('expire', 'cancel'):
so_number = so_number + '-cpl'
json_data = {
@@ -1950,7 +1974,6 @@ class SaleOrder(models.Model):
buffer = BytesIO()
img.save(buffer, format="PNG")
qr_code_img = base64.b64encode(buffer.getvalue()).decode()
-
self.payment_qr_code = qr_code_img
@api.model
@@ -2112,8 +2135,8 @@ class SaleOrder(models.Model):
if self.payment_term_id.id == 31 and self.total_percent_margin < 25:
raise UserError("Jika ingin menggunakan Tempo 90 Hari maka margin harus di atas 25%")
- if self.warehouse_id.id != 8 and self.warehouse_id.id != 10: # GD Bandengan
- raise UserError('Gudang harus Bandengan')
+ if self.warehouse_id.id != 8 and self.warehouse_id.id != 10 and self.warehouse_id.id != 12: # GD Bandengan / Pameran
+ raise UserError('Gudang harus Bandengan atau Pameran')
if self.state not in ['draft', 'sent']:
raise UserError("Status harus draft atau sent")
diff --git a/indoteknik_custom/models/stock_move.py b/indoteknik_custom/models/stock_move.py
index 64cb6ba6..d6505a86 100644
--- a/indoteknik_custom/models/stock_move.py
+++ b/indoteknik_custom/models/stock_move.py
@@ -1,6 +1,9 @@
from odoo import fields, models, api
from odoo.tools.misc import format_date, OrderedSet
from odoo.exceptions import UserError
+import logging
+
+_logger = logging.getLogger(__name__)
class StockMove(models.Model):
_inherit = 'stock.move'
diff --git a/indoteknik_custom/report/purchase_report.xml b/indoteknik_custom/report/purchase_report.xml
new file mode 100644
index 00000000..9d7f4028
--- /dev/null
+++ b/indoteknik_custom/report/purchase_report.xml
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="utf-8"?>
+<odoo>
+ <data>
+ <!-- Report Action -->
+ <record id="action_report_purchaseorder_website" model="ir.actions.report">
+ <field name="name">Purchase Order (Website)</field>
+ <field name="model">purchase.order</field>
+ <field name="report_type">qweb-pdf</field>
+ <field name="report_name">indoteknik_custom.report_purchaseorder_website</field>
+ <field name="report_file">indoteknik_custom.report_purchaseorder_website</field>
+ <field name="print_report_name">
+ ('PO - %s - %s' % (object.partner_id.name, object.name))
+ </field>
+ <field name="binding_model_id" ref="purchase.model_purchase_order"/>
+ <field name="binding_type">report</field>
+ </record>
+ </data>
+
+ <!-- Wrapper Template -->
+ <template id="report_purchaseorder_website">
+ <t t-call="web.html_container">
+ <t t-foreach="docs" t-as="doc">
+ <t t-call="indoteknik_custom.report_purchaseorder_website_document" t-lang="doc.partner_id.lang"/>
+ </t>
+ </t>
+ </template>
+
+ <!-- Document Template -->
+<template id="report_purchaseorder_website_document">
+ <t t-call="web.external_layout">
+ <t t-set="doc" t-value="doc.with_context(lang=doc.partner_id.lang)" />
+
+ <div class="page">
+ <!-- Header Image -->
+ <div class="mb16">
+ <img src="https://erp.indoteknik.com/api/image/ir.attachment/datas/2498521"
+ style="width:100%; max-height:100px; object-fit:contain;"/>
+ </div>
+
+ <!-- Title -->
+ <h2 class="text-center mb4" style="color:#d32f2f; font-weight:bold;">
+ PURCHASE ORDER
+ </h2>
+ <h4 class="text-center mb32">
+ No. <span t-field="doc.name"/>
+ </h4>
+
+ <!-- Top Info sejajar -->
+ <div class="row mb16" style="font-size:12px;">
+ <div class="col-4">
+ <strong>Term Of Payment:</strong>
+ <span t-field="doc.payment_term_id.name"/>
+ </div>
+ <div class="col-4">
+ <strong>Order Date:</strong>
+ <span t-field="doc.date_order" t-options='{"widget": "date"}'/>
+ </div>
+ <div class="col-4">
+ <strong>Responsible:</strong>
+ <span t-field="doc.user_id"/>
+ </div>
+ </div>
+
+ <!-- Vendor & Shipping Info sejajar -->
+ <div class="row mb32" style="font-size:12px;">
+ <div class="col-6" style="border:1px solid #ccc; padding:8px;">
+ <strong>Alamat Pengiriman:</strong><br/>
+ PT Indoteknik (Bandengan 1 Depan)<br/>
+ Jl. Bandengan Utara Komp A 8 B<br/>
+ RT. Penjaringan, Kec. Penjaringan, Jakarta (BELAKANG INDOMARET)<br/>
+ JK 14440<br/>
+ Indonesia
+ </div>
+ <div class="col-6" style="border:1px solid #ccc; padding:8px;">
+ <strong>Nama Vendor:</strong><br/>
+ <div t-field="doc.partner_id"
+ t-options='{"widget": "contact", "fields": ["address", "name", "phone"],
+ "no_marker": True, "phone_icons": True}'/>
+ </div>
+ </div>
+
+ <!-- Order Lines -->
+ <table class="table table-sm o_main_table" style="font-size:11px; border:1px solid #000; border-collapse: collapse; width:100%;">
+ <thead style="display: table-row-group; background:#f5f5f5;">
+ <tr>
+ <th style="border:1px solid #000; padding:4px;">Description</th>
+ <th class="text-right" style="border:1px solid #000; padding:4px;">Quantity</th>
+ <th class="text-right" style="border:1px solid #000; padding:4px;">Unit Price</th>
+ <th class="text-right" style="border:1px solid #000; padding:4px;">Taxes</th>
+ <th class="text-right" style="border:1px solid #000; padding:4px;">Subtotal</th>
+ </tr>
+ </thead>
+ <tbody>
+ <t t-foreach="doc.order_line" t-as="line">
+ <!-- Main row -->
+ <tr>
+ <td style="border:1px solid #000; padding:4px;">
+ <span t-field="line.name"/>
+ </td>
+ <td class="text-right" style="border:1px solid #000; padding:4px;">
+ <span t-field="line.product_qty"/>
+ <span t-field="line.product_uom"/>
+ </td>
+ <td class="text-right" style="border:1px solid #000; padding:4px;">
+ <span t-field="line.price_unit"/>
+ </td>
+ <td class="text-right" style="border:1px solid #000; padding:4px;">
+ <span t-esc="', '.join(map(lambda x: (x.description or x.name), line.taxes_id))"/>
+ </td>
+ <td class="text-right" style="border:1px solid #000; padding:4px;">
+ <span t-field="line.price_subtotal"/>
+ </td>
+ </tr>
+ <!-- Website Description row -->
+ <t t-if="line.product_id.website_description">
+ <tr>
+ <td colspan="5" style="border:1px solid #000; padding:6px; font-size:10px; color:#555;">
+ <div t-raw="line.product_id.website_description"/>
+ </td>
+ </tr>
+ </t>
+ </t>
+ </tbody>
+ </table>
+
+ <!-- Totals -->
+ <div class="clearfix">
+ <div class="row">
+ <div class="col-4 ml-auto">
+ <table class="table table-sm" style="border:1px solid #000; border-collapse: collapse; width:100%;">
+ <tr>
+ <td style="border:1px solid #000; padding:4px;"><strong>Subtotal</strong></td>
+ <td class="text-right" style="border:1px solid #000; padding:4px;">
+ <span t-field="doc.amount_untaxed"/>
+ </td>
+ </tr>
+ <tr>
+ <td style="border:1px solid #000; padding:4px;">Taxes</td>
+ <td class="text-right" style="border:1px solid #000; padding:4px;">
+ <span t-field="doc.amount_tax"/>
+ </td>
+ </tr>
+ <tr class="o_total">
+ <td style="border:1px solid #000; padding:4px;"><strong>Total</strong></td>
+ <td class="text-right" style="border:1px solid #000; padding:4px;">
+ <span t-field="doc.amount_total"/>
+ </td>
+ </tr>
+ </table>
+ </div>
+ </div>
+ </div>
+
+ <!-- Notes -->
+ <div class="mt32" style="font-size:11px;">
+ <p t-field="doc.notes"/>
+ </div>
+ </div>
+ </t>
+ </template>
+
+</odoo>
diff --git a/indoteknik_custom/views/res_partner.xml b/indoteknik_custom/views/res_partner.xml
index ca1a36de..7d5be3b7 100644
--- a/indoteknik_custom/views/res_partner.xml
+++ b/indoteknik_custom/views/res_partner.xml
@@ -21,6 +21,7 @@
<field name="reference_number"/>
</field>
<field name="property_payment_term_id" position="after">
+ <field name="is_cbd_locked" readonly="1"/>
<field name="user_payment_terms_sales" readonly="1"/>
<field name="date_payment_terms_sales" readonly="1"/>
</field>
@@ -107,7 +108,7 @@
<field name="reminder_invoices"/>
</xpath>
<xpath expr="//field[@name='property_payment_term_id']" position="attributes">
- <attribute name="readonly">0</attribute>
+ <attribute name="readonly">1</attribute>
</xpath>
<xpath expr="//field[@name='property_supplier_payment_term_id']" position="attributes">
<attribute name="readonly">1</attribute>
diff --git a/indoteknik_custom/views/sale_order.xml b/indoteknik_custom/views/sale_order.xml
index 156c48d7..326fd560 100755
--- a/indoteknik_custom/views/sale_order.xml
+++ b/indoteknik_custom/views/sale_order.xml
@@ -41,6 +41,15 @@
string="Refund"
class="btn-primary" />
</xpath>
+ <xpath expr="//sheet" position="before">
+ <field name="partner_is_cbd_locked" invisible="1"/>
+ <div class="alert alert-danger"
+ role="alert"
+ style="height: 40px; margin-bottom:0px;"
+ attrs="{'invisible':['|', ('partner_is_cbd_locked','=',False), ('state', 'not in', ['draft', 'cancel'])]}">
+ <strong>Warning!</strong> Payment Terms Customer terkunci menjadi <b>Cash Before Delivery (C.B.D.)</b> karena ada invoice telah jatuh tempo <b>30 hari</b>. Silakan ajukan <b>Approval Payment Term</b> untuk membuka kunci.
+ </div>
+ </xpath>
<div class="oe_button_box" name="button_box">
<field name="advance_payment_move_ids" invisible="1"/>
<button name="action_open_advance_payment_moves"
diff --git a/indoteknik_custom/views/stock_move_line.xml b/indoteknik_custom/views/stock_move_line.xml
index 757d2522..94c0bf53 100644
--- a/indoteknik_custom/views/stock_move_line.xml
+++ b/indoteknik_custom/views/stock_move_line.xml
@@ -3,18 +3,19 @@
<record id="stock_move_line_form_view_inherited" model="ir.ui.view">
<field name="name">Stock Move Line</field>
<field name="model">stock.move.line</field>
- <field name="inherit_id" ref="stock.view_move_line_form" />
+ <field name="inherit_id" ref="stock.view_move_line_form"/>
+ <field name="priority" eval="100"/>
<field name="arch" type="xml">
- <field name="qty_done" position="after">
+ <xpath expr="(//form//group[.//field[@name='qty_done']])[last()]" position="inside">
<field name="manufacture"/>
- </field>
+ </xpath>
</field>
</record>
<record id="stock_move_line_tree_view_inherited" model="ir.ui.view">
<field name="name">Stock Move Line</field>
<field name="model">stock.move.line</field>
- <field name="inherit_id" ref="stock.view_move_line_tree" />
+ <field name="inherit_id" ref="stock.view_move_line_tree"/>
<field name="arch" type="xml">
<field name="product_id" position="after">
<field name="manufacture"/>
diff --git a/indoteknik_custom/views/stock_picking.xml b/indoteknik_custom/views/stock_picking.xml
index b3f0ce9f..fc8be790 100644
--- a/indoteknik_custom/views/stock_picking.xml
+++ b/indoteknik_custom/views/stock_picking.xml
@@ -8,7 +8,7 @@
<field name="arch" type="xml">
<tree position="attributes">
<attribute name="default_order">final_seq asc</attribute>
- <!-- <attribute name="default_order">create_date desc</attribute> -->
+ <!-- <attribute name="default_order">create_date desc</attribute> -->
</tree>
<field name="json_popover" position="after">
<field name="date_done" optional="hide"/>
@@ -20,9 +20,11 @@
<field name="sj_return_date" optional="hide"/>
<field name="date_reserved" optional="hide"/>
<field name="state_reserve" optional="hide"/>
- <field name="state_packing" widget="badge" decoration-success="state_packing == 'packing_done'" decoration-danger="state_packing == 'not_packing'" optional="hide"/>
+ <field name="state_packing" widget="badge" decoration-success="state_packing == 'packing_done'"
+ decoration-danger="state_packing == 'not_packing'" optional="hide"/>
<field name="final_seq"/>
- <field name="state_approve_md" widget="badge" decoration-success="state_approve_md == 'done'" decoration-warning="state_approve_md == 'pending'" optional="hide"/>
+ <field name="state_approve_md" widget="badge" decoration-success="state_approve_md == 'done'"
+ decoration-warning="state_approve_md == 'pending'" optional="hide"/>
<!-- <field name="countdown_hours" optional="hide"/>
<field name="countdown_ready_to_ship" /> -->
</field>
@@ -50,11 +52,11 @@
type="object"
attrs="{'invisible': ['|', ('state', 'in', ['done']), ('approval_receipt_status', '=', 'pengajuan1')]}"
/>
-<!-- <button name="ask_return_approval"-->
-<!-- string="Ask Return/Acc"-->
-<!-- type="object"-->
-<!-- attrs="{'invisible': [('state', 'in', ['draft', 'cancel', 'assigned'])]}"-->
-<!-- />-->
+ <!-- <button name="ask_return_approval"-->
+ <!-- string="Ask Return/Acc"-->
+ <!-- type="object"-->
+ <!-- attrs="{'invisible': [('state', 'in', ['draft', 'cancel', 'assigned'])]}"-->
+ <!-- />-->
<button name="action_create_invoice_from_mr"
string="Create Bill"
type="object"
@@ -64,12 +66,12 @@
string="Biteship"
type="object"
/>
- <!-- <button name="action_sync_biteship_tracking"
- type="object"
- string="Lacak dari Biteship"
- class="btn-primary"
- attrs="{'invisible': [('biteship_id', '=', False)]}"
- /> -->
+ <!-- <button name="action_sync_biteship_tracking"
+ type="object"
+ string="Lacak dari Biteship"
+ class="btn-primary"
+ attrs="{'invisible': [('biteship_id', '=', False)]}"
+ /> -->
<button name="track_envio_shipment"
string="Tracking Envio"
type="object"
@@ -97,6 +99,11 @@
attrs="{'invisible': [('state_approve_md', 'not in', ['waiting'])]}"
/>
</button>
+ <!-- <xpath expr="//field[@name='move_ids_without_package']//tree//field[@name='product_uom']"
+ position="after">
+ <field name="product_image" widget="image"
+ style="height:128px;width:128px;" readonly="1"/>
+ </xpath> -->
<field name="backorder_id" position="after">
<field name="select_shipping_option_so"/>
<field name="shipping_method_so_id"/>
@@ -105,7 +112,8 @@
<field name="count_line_detail"/>
<field name="dokumen_tanda_terima"/>
<field name="dokumen_pengiriman"/>
- <field name="quantity_koli" attrs="{'invisible': [('location_dest_id', '!=', 60)], 'required': [('location_dest_id', '=', 60)]}"/>
+ <field name="quantity_koli"
+ attrs="{'invisible': [('location_dest_id', '!=', 60)], 'required': [('location_dest_id', '=', 60)]}"/>
<field name="total_mapping_koli" attrs="{'invisible': [('location_id', '!=', 60)]}"/>
<field name="total_koli_display" readonly="1" attrs="{'invisible': [('location_id', '!=', 60)]}"/>
<field name="linked_out_picking_id" readonly="1" attrs="{'invisible': [('location_id', '=', 60)]}"/>
@@ -132,8 +140,13 @@
<field name="scheduled_date" position="attributes">
<attribute name="readonly">1</attribute>
</field>
+ <xpath expr="//field[@name='move_ids_without_package']/form/group/field[@name='description_picking']"
+ position="after">
+ <field name="product_image" widget="image" string="Product Image"/>
+ </xpath>
+
<field name="origin" position="after">
-<!-- <field name="show_state_approve_md" invisible="1" optional="hide"/>-->
+ <!-- <field name="show_state_approve_md" invisible="1" optional="hide"/>-->
<field name="state_approve_md" widget="badge"/>
<field name="purchase_id"/>
<field name="sale_order"/>
@@ -141,7 +154,8 @@
<field name="date_doc_kirim" attrs="{'readonly':[('invoice_status', '=', 'invoiced')]}"/>
<field name="summary_qty_operation"/>
<field name="count_line_operation"/>
- <field name="linked_manual_bu_out" attrs="{'invisible': [('location_id', '=', 60)]}" domain="[('picking_type_code', '=', 'outgoing'),('state', 'not in', ['done','cancel']), ('group_id', '=', group_id)]"/>
+ <field name="linked_manual_bu_out" attrs="{'invisible': [('location_id', '=', 60)]}"
+ domain="[('picking_type_code', '=', 'outgoing'),('state', 'not in', ['done','cancel']), ('group_id', '=', group_id)]"/>
<field name="account_id"
attrs="{
'readonly': [['state', 'in', ['done', 'cancel']]],
@@ -189,29 +203,35 @@
</group>
</group>
</page>
- <page string="Delivery" name="delivery_order" attrs="{'invisible': [('location_dest_id', '=', 60)]}">
+ <page string="Delivery" name="delivery_order"
+ attrs="{'invisible': [('location_dest_id', '=', 60)]}">
<group>
<group>
<field name="notee"/>
<field name="note_logistic"/>
<field name="note_info"/>
- <field name="responsible" />
- <field name="carrier_id" attrs="{'invisible': [('select_shipping_option_so', '=', 'biteship')]}" />
+ <field name="responsible"/>
+ <field name="carrier_id"
+ attrs="{'invisible': [('select_shipping_option_so', '=', 'biteship')]}"/>
<field name="biteship_id" invisible="1"/>
<field name="out_code" attrs="{'invisible': [['out_code', '=', False]]}"/>
<field name="picking_code" attrs="{'invisible': [['picking_code', '=', False]]}"/>
- <field name="picking_code" string="Picking code (akan digenerate ketika sudah di-validate)" attrs="{'invisible': [['picking_code', '!=', False]]}"/>
- <field name="driver_departure_date" attrs="{'readonly':[('invoice_status', '=', 'invoiced')]}"/>
+ <field name="picking_code"
+ string="Picking code (akan digenerate ketika sudah di-validate)"
+ attrs="{'invisible': [['picking_code', '!=', False]]}"/>
+ <field name="driver_departure_date"
+ attrs="{'readonly':[('invoice_status', '=', 'invoiced')]}"/>
<field name="driver_arrival_date"/>
- <field name="delivery_tracking_no" attrs="{'invisible': [('select_shipping_option_so', '=', 'biteship')]}"/>
+ <field name="delivery_tracking_no"
+ attrs="{'invisible': [('select_shipping_option_so', '=', 'biteship')]}"/>
<field name="driver_id"/>
<field name='sj_return_date'/>
- <field name="sj_documentation" widget="image" />
- <field name="paket_documentation" widget="image" />
+ <field name="sj_documentation" widget="image"/>
+ <field name="paket_documentation" widget="image"/>
</group>
<!-- Biteship Group -->
<group attrs="{'invisible': [('select_shipping_option_so', '!=', 'biteship')]}">
- <field name="delivery_tracking_no" />
+ <field name="delivery_tracking_no"/>
<field name="shipping_method_so_id"/>
<field name="shipping_option_so_id"/>
<field name="biteship_shipping_price" readonly="1"/>
@@ -220,7 +240,8 @@
<field name="biteship_driver_name" readonly="1"/>
<field name="biteship_driver_phone" readonly="1"/>
<field name="biteship_driver_plate_number" readonly="1"/>
- <button name="action_open_biteship_tracking" string="Visit Biteship Tracking" type="object"/>
+ <button name="action_open_biteship_tracking" string="Visit Biteship Tracking"
+ type="object"/>
</group>
<group attrs="{'invisible': [('carrier_id', '!=', 151)]}">
@@ -261,23 +282,27 @@
</group>
</group>
</page>
- <page string="Check Product" name="check_product" attrs="{'invisible': [('picking_type_code', '=', 'outgoing')]}">
+ <page string="Check Product" name="check_product"
+ attrs="{'invisible': [('picking_type_code', '=', 'outgoing')]}">
<field name="check_product_lines"/>
</page>
- <page string="Barcode Product" name="barcode_product" attrs="{'invisible': [('picking_type_code', '!=', 'incoming')]}">
+ <page string="Barcode Product" name="barcode_product"
+ attrs="{'invisible': [('picking_type_code', '!=', 'incoming')]}">
<field name="barcode_product_lines"/>
</page>
<page string="Check Koli" name="check_koli" attrs="{'invisible': [('location_dest_id', '!=', 60)]}">
<field name="check_koli_lines"/>
</page>
- <page string="Mapping Koli" name="konfirm_koli" attrs="{'invisible': [('picking_type_code', '!=', 'outgoing')]}">
+ <page string="Mapping Koli" name="konfirm_koli"
+ attrs="{'invisible': [('picking_type_code', '!=', 'outgoing')]}">
<field name="konfirm_koli_lines"/>
</page>
- <page string="Konfirm Koli" name="scan_koli" attrs="{'invisible': [('picking_type_code', '!=', 'outgoing')]}">
+ <page string="Konfirm Koli" name="scan_koli"
+ attrs="{'invisible': [('picking_type_code', '!=', 'outgoing')]}">
<field name="scan_koli_lines"/>
</page>
</page>
-
+
</field>
</record>
@@ -287,18 +312,20 @@
<field name="arch" type="xml">
<tree editable="bottom">
<field name="code_koli"/>
- <field name="koli_id" options="{'no_create': True}" domain="[('state', '=', 'not_delivered')]"/>
+ <field name="koli_id" options="{'no_create': True}" domain="[('state', '=', 'not_delivered')]"/>
<field name="scan_koli_progress"/>
</tree>
</field>
</record>
+
<record id="konfirm_koli_tree" model="ir.ui.view">
<field name="name">konfirm.koli.tree</field>
<field name="model">konfirm.koli</field>
<field name="arch" type="xml">
<tree editable="bottom">
- <field name="pick_id" options="{'no_create': True}" required="1" domain="[('picking_type_code', '=', 'internal'), ('group_id', '=', parent.group_id), ('linked_manual_bu_out', '=', parent.id)]"/>
+ <field name="pick_id" options="{'no_create': True}" required="1"
+ domain="[('picking_type_code', '=', 'internal'), ('group_id', '=', parent.group_id), ('linked_manual_bu_out', '=', parent.id)]"/>
</tree>
</field>
</record>
@@ -307,7 +334,7 @@
<field name="name">check.koli.tree</field>
<field name="model">check.koli</field>
<field name="arch" type="xml">
- <tree editable="bottom">
+ <tree editable="bottom">
<field name="koli"/>
<field name="reserved_id"/>
<field name="check_koli_progress"/>
@@ -344,12 +371,14 @@
<field name="model">stock.move.line</field>
<field name="inherit_id" ref="stock.view_stock_move_line_detailed_operation_tree"/>
<field name="arch" type="xml">
- <tree editable="bottom" decoration-muted="(state == 'done' and is_locked == True)" decoration-danger="qty_done&gt;product_uom_qty and state!='done' and parent.picking_type_code != 'incoming'" decoration-success="qty_done==product_uom_qty and state!='done' and not result_package_id">
+ <tree editable="bottom" decoration-muted="(state == 'done' and is_locked == True)"
+ decoration-danger="qty_done&gt;product_uom_qty and state!='done' and parent.picking_type_code != 'incoming'"
+ decoration-success="qty_done==product_uom_qty and state!='done' and not result_package_id">
<field name="note" placeholder="Add a note here"/>
</tree>
</field>
</record>
-
+
<record id="view_picking_internal_search_inherit" model="ir.ui.view">
<field name="name">stock.picking.internal.search.inherit</field>
@@ -382,7 +411,7 @@
</form>
</field>
</record>
-
+
<record id="action_warning_modal_wizard" model="ir.actions.act_window">
<field name="name">Peringatan Koli</field>
<field name="res_model">warning.modal.wizard</field>