summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMqdd <ahmadmiqdad27@gmail.com>2026-02-14 11:14:01 +0700
committerMqdd <ahmadmiqdad27@gmail.com>2026-02-14 11:14:01 +0700
commit472f36669375d3d0bcecf137e07260fac25d12b3 (patch)
tree873a665fd8d3cc249a6460858e85272b838162d3
parent24b33148858c9827ad0b14e716562c377e1644ca (diff)
parent37e0beac646ee2e676ff935e8289cf3189b3c21b (diff)
Merge branch 'odoo-backup' of https://bitbucket.org/altafixco/indoteknik-addons into gudang-service
-rwxr-xr-xindoteknik_custom/__manifest__.py2
-rwxr-xr-xindoteknik_custom/models/__init__.py4
-rw-r--r--indoteknik_custom/models/account_move.py16
-rw-r--r--indoteknik_custom/models/account_move_line.py65
-rw-r--r--indoteknik_custom/models/advance_payment_request.py14
-rwxr-xr-xindoteknik_custom/models/purchase_order.py29
-rwxr-xr-xindoteknik_custom/models/purchase_order_line.py46
-rw-r--r--indoteknik_custom/models/refund_sale_order.py57
-rwxr-xr-xindoteknik_custom/models/sale_order.py18
-rw-r--r--indoteknik_custom/models/sale_order_line.py53
-rw-r--r--indoteknik_custom/models/shipment_group.py24
-rw-r--r--indoteknik_custom/models/stock_inventory.py26
-rw-r--r--indoteknik_custom/models/stock_picking.py13
-rw-r--r--indoteknik_custom/models/tukar_guling_po.py38
-rw-r--r--indoteknik_custom/models/update_depreciation_move_wizard.py48
-rwxr-xr-xindoteknik_custom/models/x_manufactures.py2
-rw-r--r--indoteknik_custom/report/purchase_report_internal.xml201
-rwxr-xr-xindoteknik_custom/security/ir.model.access.csv3
-rw-r--r--indoteknik_custom/views/account_move_line.xml12
-rw-r--r--indoteknik_custom/views/advance_payment_request.xml1
-rw-r--r--indoteknik_custom/views/approval_date_doc.xml2
-rwxr-xr-xindoteknik_custom/views/purchase_order.xml1
-rwxr-xr-xindoteknik_custom/views/sale_order.xml1
-rw-r--r--indoteknik_custom/views/shipment_group.xml6
-rw-r--r--indoteknik_custom/views/stock_inventory.xml6
-rw-r--r--indoteknik_custom/views/stock_picking.xml1
-rw-r--r--indoteknik_custom/views/tukar_guling.xml24
-rw-r--r--indoteknik_custom/views/update_depreciation_move_wizard_view.xml35
-rwxr-xr-xindoteknik_custom/views/x_manufactures.xml2
29 files changed, 707 insertions, 43 deletions
diff --git a/indoteknik_custom/__manifest__.py b/indoteknik_custom/__manifest__.py
index ddf80cb1..fd6f3140 100755
--- a/indoteknik_custom/__manifest__.py
+++ b/indoteknik_custom/__manifest__.py
@@ -169,6 +169,7 @@
'report/report_surat_piutang.xml',
'report/report_tutup_tempo.xml',
'report/purchase_report.xml',
+ 'report/purchase_report_internal.xml',
'views/vendor_sla.xml',
'views/coretax_faktur.xml',
'views/public_holiday.xml',
@@ -193,6 +194,7 @@
'views/domain_apo.xml',
'views/uom_uom.xml',
'views/commission_internal.xml',
+ 'views/update_depreciation_move_wizard_view.xml',
'views/gudang_service.xml'
],
'demo': [],
diff --git a/indoteknik_custom/models/__init__.py b/indoteknik_custom/models/__init__.py
index e6a59246..2b1851ce 100755
--- a/indoteknik_custom/models/__init__.py
+++ b/indoteknik_custom/models/__init__.py
@@ -165,4 +165,8 @@ from . import partial_delivery
from . import domain_apo
from . import uom_uom
from . import commission_internal
+<<<<<<< HEAD
from . import gudang_service
+=======
+from . import update_depreciation_move_wizard
+>>>>>>> 37e0beac646ee2e676ff935e8289cf3189b3c21b
diff --git a/indoteknik_custom/models/account_move.py b/indoteknik_custom/models/account_move.py
index e1360cfa..42467b78 100644
--- a/indoteknik_custom/models/account_move.py
+++ b/indoteknik_custom/models/account_move.py
@@ -587,6 +587,10 @@ class AccountMove(models.Model):
records = self.search([('id', 'in', self.ids)])
template = self.env.ref('indoteknik_custom.mail_template_efaktur_document')
+ ICP = self.env['ir.config_parameter'].sudo()
+ special_partner_ids = set(
+ int(x) for x in (ICP.get_param('efaktur.special_partner_ids') or '').split(',') if x
+ )
for record in records:
if record.invoice_payment_term_id.id == 26:
@@ -595,6 +599,18 @@ class AccountMove(models.Model):
'attachment_ids': [(4, attachment.id)]
}
template.send_mail(record.id, email_values=email_values, force_send=True)
+
+ elif record.partner_id.id in special_partner_ids:
+ attachment = self.generate_attachment(record)
+ email_list = [record.partner_id.email] if record.partner_id.email else []
+ if record.real_invoice_id and record.real_invoice_id.email:
+ email_list.append(record.real_invoice_id.email)
+
+ email_values = {
+ 'email_to': ",".join(set(email_list)),
+ 'attachment_ids': [(4, attachment.id)]
+ }
+ template.send_mail(record.id, email_values=email_values, force_send=True)
# @api.model
# def create(self, vals):
diff --git a/indoteknik_custom/models/account_move_line.py b/indoteknik_custom/models/account_move_line.py
index 7c95d4ef..5edea25f 100644
--- a/indoteknik_custom/models/account_move_line.py
+++ b/indoteknik_custom/models/account_move_line.py
@@ -1,5 +1,5 @@
from odoo import models, api, fields
-
+from odoo.exceptions import AccessError, UserError, ValidationError
class AccountMoveLine(models.Model):
_inherit = "account.move.line"
@@ -9,6 +9,69 @@ class AccountMoveLine(models.Model):
analytic_account_ids = fields.Many2many('account.analytic.account', string='Analytic Account')
line_no = fields.Integer('No', default=0)
+ def action_gl_reconcile(self):
+ lines = self
+
+ journal = self.env['account.journal'].search([
+ ('suspense_account_id', '=', lines[0].account_id.id)
+ ], limit=1)
+
+ if not journal:
+ raise UserError('Journal dengan suspense account ini tidak ditemukan!')
+
+ statement = self.env['account.bank.statement'].create({
+ 'journal_id': journal.id,
+ 'name': f'REKONSIL {journal.name} {lines[0].date.strftime("%d-%m-%Y")}',
+ 'company_id': self.env.company.id,
+ 'date': lines[0].date,
+ })
+
+ widget_vals = []
+ st_line_ids = []
+
+ for line in lines:
+ amount = line.debit - line.credit
+
+ st_line = self.env['account.bank.statement.line'].create({
+ 'statement_id': statement.id,
+ 'date': line.date or fields.Date.today(),
+ 'payment_ref': line.name,
+ 'partner_id': line.partner_id.id,
+ 'amount': amount,
+ 'ref': line.name,
+ })
+
+ st_line_ids.append(st_line.id)
+
+ widget_vals.append({
+ 'partner_id': st_line.partner_id.id,
+ 'counterpart_aml_dicts': [{
+ 'counterpart_aml_id': line.id,
+ 'debit': abs(amount) if amount < 0 else 0,
+ 'credit': abs(amount) if amount > 0 else 0,
+ 'name': line.name or '/',
+ }],
+ 'payment_aml_ids': [],
+ 'new_aml_dicts': [],
+ 'to_check': False,
+ })
+
+ statement.button_post()
+
+ self.env['account.reconciliation.widget'].process_bank_statement_line(
+ st_line_ids,
+ widget_vals
+ )
+ # statement.button_validate_or_action()
+
+ return {
+ 'effect': {
+ 'fadeout': 'slow',
+ 'message': 'Statement + Auto Reconcile sukses besar 😎🔥',
+ 'type': 'rainbow_man',
+ }
+ }
+
@api.onchange('account_id')
def _onchange_account_id(self):
for account in self:
diff --git a/indoteknik_custom/models/advance_payment_request.py b/indoteknik_custom/models/advance_payment_request.py
index ed0b0809..8cadb1b6 100644
--- a/indoteknik_custom/models/advance_payment_request.py
+++ b/indoteknik_custom/models/advance_payment_request.py
@@ -641,10 +641,16 @@ class AdvancePaymentRequest(models.Model):
today = date.today()
for rec in self:
- current_days = rec.days_remaining or 0
- current_due_date = rec.estimated_return_date or False
- if rec.type_request == 'pum':
- is_settlement_approved = any(s.status == 'approved' for s in rec.settlement_ids)
+ # current_days = rec.days_remaining or 0
+ # current_due_date = rec.estimated_return_date or False
+ current_days = 0
+ current_due_date = False
+
+ is_settlement_approved = any(s.status == 'approved' for s in rec.settlement_ids)
+ is_pum_canceled = (rec.status == 'cancel')
+
+ if rec.type_request == 'pum' and not is_pum_canceled and not is_settlement_approved:
+
if not is_settlement_approved:
due_date = False
diff --git a/indoteknik_custom/models/purchase_order.py b/indoteknik_custom/models/purchase_order.py
index e16c8d61..b3ecca56 100755
--- a/indoteknik_custom/models/purchase_order.py
+++ b/indoteknik_custom/models/purchase_order.py
@@ -53,6 +53,7 @@ class PurchaseOrder(models.Model):
total_so_percent_margin = fields.Float(
'SO Margin%', compute='compute_total_margin',
help="Total % Margin in Sales Order Header")
+ amount_cashback = fields.Float('Cashback', compute = 'compute_total_margin', help = 'Total Cashback brand Altama')
amount_total_without_service = fields.Float('AmtTotalWithoutService', compute='compute_amt_total_without_service')
summary_qty_po = fields.Float('Total Qty', compute='_compute_summary_qty')
summary_qty_receipt = fields.Float('Summary Qty Receipt', compute='_compute_summary_qty')
@@ -1410,19 +1411,36 @@ class PurchaseOrder(models.Model):
real_item_margin = sales_price - purchase_price
sum_margin += real_item_margin
+ cashback_amount = 0
+ if self.partner_id.id == 5571:
+ cashback_percent = line.product_id.x_manufacture.cashback_percent or 0.0
+ if cashback_percent > 0:
+ cashback_amount = purchase_price * cashback_percent
+ purchase_price -= cashback_amount
+
+ # line.amount_cashback = cashback_amount
+
if sum_so_margin != 0 and sum_sales_price != 0 and sum_margin != 0:
self.total_so_margin = sum_so_margin
self.total_so_percent_margin = round((sum_so_margin / sum_sales_price), 2) * 100
self.total_margin = sum_margin
self.total_percent_margin = round((sum_margin / sum_sales_price), 2) * 100
+ self.amount_cashback = 0
+ elif self.partner_id.id == 5571 and sum_so_margin != 0 and sum_sales_price != 0 and sum_margin != 0 and cashback_amount != 0:
+ self.total_so_margin = sum_so_margin
+ self.total_so_percent_margin = round((sum_so_margin / sum_sales_price), 2) * 100
+ self.total_margin = sum_margin
+ self.total_percent_margin = round((sum_margin / sum_sales_price), 2) * 100
+ self.amount_cashback = cashback_amount
else:
self.total_margin = 0
self.total_percent_margin = 0
self.total_so_margin = 0
self.total_so_percent_margin = 0
+ self.amount_cashback = 0
def compute_total_margin_from_apo(self):
- sum_so_margin = sum_sales_price = sum_margin = 0
+ sum_so_margin = sum_sales_price = sum_margin = cashback_amount = 0
for line in self.order_sales_match_line:
po_line = self.env['purchase.order.line'].search([
('product_id', '=', line.product_id.id),
@@ -1459,18 +1477,27 @@ class PurchaseOrder(models.Model):
if line.purchase_order_id.delivery_amt > 0:
purchase_price += line.purchase_order_id.delivery_amt
+ if self.partner_id.id == 5571:
+ cashback_percent = line.product_id.x_manufacture.cashback_percent or 0.0
+ if cashback_percent > 0:
+ cashback_amount = purchase_price * cashback_percent
+ purchase_price -= cashback_amount
+
real_item_margin = sales_price - purchase_price
sum_margin += real_item_margin
+ self.amount_cashback = cashback_amount
# Akumulasi hasil akhir
if sum_sales_price != 0:
self.total_so_margin = sum_so_margin
self.total_so_percent_margin = round((sum_so_margin / sum_sales_price), 2) * 100
self.total_margin = sum_margin
self.total_percent_margin = round((sum_margin / sum_sales_price), 2) * 100
+ self.amount_cashback = cashback_amount
else:
self.total_margin = self.total_percent_margin = 0
self.total_so_margin = self.total_so_percent_margin = 0
+ self.amount_cashback = 0
def compute_amt_total_without_service(self):
diff --git a/indoteknik_custom/models/purchase_order_line.py b/indoteknik_custom/models/purchase_order_line.py
index 8c72887d..76dcc09e 100755
--- a/indoteknik_custom/models/purchase_order_line.py
+++ b/indoteknik_custom/models/purchase_order_line.py
@@ -23,6 +23,9 @@ class PurchaseOrderLine(models.Model):
so_item_percent_margin = fields.Float(
'SO Margin%', compute='compute_item_margin',
help="Total % Margin in Sales Order Header")
+ amount_cashback = fields.Float(
+ 'SO Margin%', compute='_compute_cashback_brand',
+ help="Total % Margin in Sales Order Header")
delivery_amt_line = fields.Float('DeliveryAmtLine', compute='compute_delivery_amt_line')
line_no = fields.Integer('No', default=0)
qty_available = fields.Float('Qty Available', compute='_compute_qty_stock')
@@ -373,6 +376,9 @@ class PurchaseOrderLine(models.Model):
purchase_price = line.price_subtotal
if order.delivery_amount > 0:
purchase_price += line.delivery_amt_line
+
+ if line.amount_cashback > 0:
+ purchase_price = purchase_price - line.amount_cashback
# Hitung margin dan persentase margin
real_item_margin = total_sales_price - purchase_price
@@ -384,6 +390,46 @@ class PurchaseOrderLine(models.Model):
sum_margin += real_item_margin
+ def _compute_cashback_brand(self):
+ start_date = datetime(2026, 2, 1, 0, 0, 0)
+
+ for line in self:
+ line.amount_cashback = 0.0
+
+ product = line.product_id
+ order = line.order_id
+
+ if not product or not order:
+ continue
+
+ if order.partner_id.id != 5571:
+ continue
+
+ sales_matches = self.env['purchase.order.sales.match'].search([
+ ('purchase_order_id', '=', order.id),
+ ('product_id', '=', product.id)
+ ])
+
+ total_cashback = 0.0
+
+ for match in sales_matches:
+ so_line = match.sale_line_id
+ so_order = so_line.order_id
+
+ if not so_order.date_order or so_order.date_order < start_date:
+ continue
+
+ cashback_percent = product.x_manufacture.cashback_percent or 0.0
+ if cashback_percent <= 0:
+ continue
+ sales_price = so_line.price_reduce_taxexcl * match.qty_so
+
+ cashback = sales_price * cashback_percent
+ total_cashback += cashback
+
+ line.amount_cashback = total_cashback
+
+
def compute_delivery_amt_line(self):
for line in self:
if line.product_id.type == 'product':
diff --git a/indoteknik_custom/models/refund_sale_order.py b/indoteknik_custom/models/refund_sale_order.py
index 646376ab..4c3ca52e 100644
--- a/indoteknik_custom/models/refund_sale_order.py
+++ b/indoteknik_custom/models/refund_sale_order.py
@@ -62,7 +62,8 @@ class RefundSaleOrder(models.Model):
('uang', 'Refund Lebih Bayar'),
('retur_half', 'Refund Retur Sebagian'),
('retur', 'Refund Retur Full'),
- ('salah_transfer', 'Salah Transfer')
+ ('salah_transfer', 'Salah Transfer'),
+ ('berita_acara', 'Kebutuhan Berita Acara')
], string='Refund Type', required=True)
tukar_guling_ids = fields.One2many(
@@ -242,7 +243,7 @@ class RefundSaleOrder(models.Model):
)
invoices = sale_orders.mapped('invoice_ids').filtered(
- lambda inv: inv.move_type in ['out_invoice', 'out_refund'] and inv.payment_state == 'paid'
+ lambda inv: inv.move_type in ['out_invoice', 'out_refund'] and inv.state == 'posted'
)
if invoices:
vals['invoice_ids'] = [(6, 0, invoices.ids)]
@@ -251,7 +252,7 @@ class RefundSaleOrder(models.Model):
invoice_ids_data = vals.get('invoice_ids', [])
invoice_ids = invoice_ids_data[0][2] if invoice_ids_data and invoice_ids_data[0][0] == 6 else []
invoices = self.env['account.move'].browse(invoice_ids)
- if invoice_ids and refund_type and refund_type not in ['uang', 'barang_kosong_sebagian', 'barang_kosong', 'retur_half']:
+ if invoice_ids and refund_type and refund_type not in ['uang', 'barang_kosong_sebagian', 'barang_kosong', 'retur_half', 'berita_acara']:
raise UserError("Refund type Hanya Bisa Lebih Bayar, Barang Kosong Sebagian, atau Retur jika ada invoice")
if not invoice_ids and refund_type and refund_type in ['uang', 'barang_kosong_sebagian', 'retur_half']:
@@ -434,13 +435,17 @@ class RefundSaleOrder(models.Model):
total_invoice = sum(self.env['account.move'].browse(invoice_ids).mapped('amount_total_signed')) if invoice_ids else 0.0
vals['total_invoice'] = total_invoice
amount_refund = vals.get('amount_refund', 0.0)
- can_refund = sisa_uang_masuk - total_invoice
-
- if amount_refund > can_refund or can_refund == 0.0:
- raise ValidationError(
- _("Maksimal refund yang bisa dilakukan adalah sebesar %s. "
- "Silakan sesuaikan jumlah refund.") % (can_refund)
- )
+ can_refund = 0.0
+ if refund_type == 'berita_acara':
+ can_refund = sisa_uang_masuk
+ else:
+ can_refund = sisa_uang_masuk - total_invoice
+ if refund_type != 'berita_acara':
+ if amount_refund > can_refund or can_refund == 0.0:
+ raise ValidationError(
+ _("Maksimal refund yang bisa dilakukan adalah sebesar %s. "
+ "Silakan sesuaikan jumlah refund.") % (can_refund)
+ )
if amount_refund <= 0.00:
raise ValidationError('Total Refund harus lebih dari 0 jika ingin mengajukan refund')
@@ -492,7 +497,7 @@ class RefundSaleOrder(models.Model):
valid_invoices = sale_orders.mapped('invoice_ids').filtered(
- lambda inv: inv.move_type in ['out_invoice', 'out_refund'] and inv.payment_state == 'paid'
+ lambda inv: inv.move_type in ['out_invoice', 'out_refund'] and inv.state == 'posted'
)
vals['invoice_ids'] = [(6, 0, valid_invoices.ids)]
vals['ongkir'] = sum(so.delivery_amt or 0.0 for so in sale_orders)
@@ -535,7 +540,7 @@ class RefundSaleOrder(models.Model):
else:
invoice_ids = rec.invoice_ids.ids
- if invoice_ids and vals.get('refund_type', rec.refund_type) not in ['uang', 'barang_kosong_sebagian', 'barang_kosong', 'retur_half', 'retur']:
+ if invoice_ids and vals.get('refund_type', rec.refund_type) not in ['uang', 'barang_kosong_sebagian', 'barang_kosong', 'retur_half', 'retur', 'berita_acara']:
raise UserError("Refund type Hanya Bisa Lebih Bayar, Barang Kosong Sebagian, atau Retur jika ada invoice")
if not invoice_ids and vals.get('refund_type', rec.refund_type) in ['uang', 'barang_kosong_sebagian', 'retur_half']:
@@ -548,10 +553,28 @@ class RefundSaleOrder(models.Model):
if any(field in vals for field in ['uang_masuk', 'invoice_ids', 'ongkir', 'sale_order_ids', 'amount_refund']):
total_invoice = sum(self.env['account.move'].browse(invoice_ids).mapped('amount_total_signed'))
vals['total_invoice'] = total_invoice
- uang_masuk = rec.uang_masuk
- can_refund = uang_masuk - total_invoice
-
+ uang_masuk = vals.get('uang_masuk', rec.uang_masuk)
amount_refund = vals.get('amount_refund', rec.amount_refund)
+ can_refund = 0.0
+ total_refunded = 0.0
+
+ if refund_type == 'berita_acara':
+ can_refund = uang_masuk
+ remaining = uang_masuk - amount_refund
+ else:
+ can_refund = uang_masuk - total_invoice
+
+ existing_refunds = self.search([
+ ('sale_order_ids', 'in', so_ids),
+ ('id', '!=', rec.id)
+ ])
+ total_refunded = sum(existing_refunds.mapped('amount_refund'))
+
+ if existing_refunds:
+ remaining = uang_masuk - total_refunded
+ else:
+ remaining = uang_masuk - amount_refund
+
if amount_refund > can_refund:
raise ValidationError(
@@ -601,7 +624,7 @@ class RefundSaleOrder(models.Model):
for rec in self:
move_links = []
- invoice_ids = rec.sale_order_ids.mapped('invoice_ids')
+ invoice_ids = rec.sale_order_ids.mapped('invoice_ids').filtered(lambda m: m.state == 'posted')
moves = self.env['account.move'].search([
('sale_id', 'in', rec.sale_order_ids.ids),
@@ -708,7 +731,7 @@ class RefundSaleOrder(models.Model):
for so in self.sale_order_ids:
self.ongkir += so.delivery_amt or 0.0
valid_invoices = so.invoice_ids.filtered(
- lambda inv: inv.move_type in ['out_invoice', 'out_refund'] and inv.payment_state == 'paid'
+ lambda inv: inv.move_type in ['out_invoice', 'out_refund'] and inv.state == 'posted'
)
all_invoices |= valid_invoices
total_invoice += sum(valid_invoices.mapped('amount_total_signed'))
diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py
index 469509d4..2548c7b3 100755
--- a/indoteknik_custom/models/sale_order.py
+++ b/indoteknik_custom/models/sale_order.py
@@ -2316,7 +2316,7 @@ class SaleOrder(models.Model):
for order in self:
for line in order.order_line:
search_product = self.env['sale.order.line'].search(
- [('product_id', '=', line.product_id.id), ('order_id', '=', order.id)])
+ [('product_id', '=', line.product_id.id), ('order_id', '=', order.id), ('display_type', '=', False)])
if len(search_product) > 1:
raise UserError("Terdapat DUPLIKASI data pada Product {}".format(line.product_id.display_name))
@@ -2598,6 +2598,18 @@ class SaleOrder(models.Model):
else:
return False
+ def check_archived_product(self):
+ for order in self:
+ for line in order.order_line:
+ if line.product_id.active == False:
+ raise UserError("Terdapat Product yang sudah di Archive pada Product: {}".format(line.product_id.display_name))
+
+ def check_archived_uom(self):
+ for order in self:
+ for line in order.order_line:
+ if line.product_uom.active == False:
+ raise UserError("Terdapat UoM yang sudah di Archive pada UoM {} di Product {}".format(line.product_uom.name, line.product_id.display_name))
+
def action_confirm(self):
for order in self:
order._validate_delivery_amt()
@@ -2614,6 +2626,8 @@ class SaleOrder(models.Model):
order._validate_order()
order._validate_npwp()
order.order_line.validate_line()
+ order.check_archived_product()
+ order.check_archived_uom()
main_parent = order.partner_id.get_main_parent()
SYSTEM_UID = 25
@@ -3438,7 +3452,7 @@ class SaleOrder(models.Model):
def button_refund(self):
self.ensure_one()
- invoice_ids = self.invoice_ids.filtered(lambda inv: inv.payment_state == 'paid')
+ invoice_ids = self.invoice_ids.filtered(lambda inv: inv.state == 'posted')
moves = self.env['account.move'].search([
('sale_id', '=', self.id),
diff --git a/indoteknik_custom/models/sale_order_line.py b/indoteknik_custom/models/sale_order_line.py
index 1df1a058..dd44f84a 100644
--- a/indoteknik_custom/models/sale_order_line.py
+++ b/indoteknik_custom/models/sale_order_line.py
@@ -17,6 +17,7 @@ class SaleOrderLine(models.Model):
help="Total % Margin in Sales Order Header")
item_percent_margin_before = fields.Float('%Margin Before', compute='_compute_item_percent_margin_before',
help="Total % Margin excluding third party in Sales Order Header")
+ amount_cashback = fields.Float('Cashback Brand', compute='_compute_cashback_brand', help='Cashback from product who has cashback percent in manufacture')
initial_discount = fields.Float('Initial Discount')
vendor_id = fields.Many2one(
'res.partner', string='Vendor', readonly=True,
@@ -164,7 +165,10 @@ class SaleOrderLine(models.Model):
purchase_price = line.purchase_price
if line.purchase_tax_id.price_include:
- purchase_price = line.purchase_price / 1.11
+ purchase_price = line.purchase_price / (1 + (line.purchase_tax_id.amount / 100))
+
+ if line.amount_cashback > 0:
+ purchase_price = purchase_price - line.amount_cashback
purchase_price = purchase_price * line.product_uom_qty
margin_per_item = sales_price - purchase_price
@@ -186,7 +190,10 @@ class SaleOrderLine(models.Model):
purchase_price = line.purchase_price
if line.purchase_tax_id and line.purchase_tax_id.price_include:
- purchase_price = line.purchase_price / 1.11
+ purchase_price = line.purchase_price / (1 + (line.purchase_tax_id.amount / 100))
+
+ if line.amount_cashback > 0:
+ purchase_price = purchase_price - line.amount_cashback
purchase_price = purchase_price * line.product_uom_qty
@@ -215,7 +222,10 @@ class SaleOrderLine(models.Model):
purchase_price = line.purchase_price
if line.purchase_tax_id.price_include:
- purchase_price = line.purchase_price / 1.11
+ purchase_price = line.purchase_price / (1 + (line.purchase_tax_id.amount / 100))
+
+ if line.amount_cashback > 0:
+ purchase_price = purchase_price - line.amount_cashback
purchase_price = purchase_price * line.product_uom_qty
margin_per_item = sales_price - purchase_price
@@ -241,12 +251,47 @@ class SaleOrderLine(models.Model):
purchase_price = line.purchase_price
if line.purchase_tax_id.price_include:
- purchase_price = line.purchase_price / 1.11
+ purchase_price = line.purchase_price / (1 + (line.purchase_tax_id.amount / 100))
+
+ if line.amount_cashback > 0:
+ purchase_price = purchase_price - line.amount_cashback
purchase_price = purchase_price * line.product_uom_qty
margin_per_item = sales_price - purchase_price
line.item_before_margin = margin_per_item
+ def _compute_cashback_brand(self):
+ start_date = datetime(2026, 2, 1, 0, 0, 0)
+ for line in self:
+ line.amount_cashback = 0
+
+ if not line.product_id:
+ continue
+
+ if line.order_id.date_order < start_date:
+ continue
+
+ price, taxes, vendor_id = self._get_purchase_price(line.product_id)
+
+ cashback_percent = line.product_id.x_manufacture.cashback_percent or 0
+ if cashback_percent <= 0:
+ continue
+
+
+ if line.vendor_id.id != 5571:
+ continue
+
+ price_tax_excl = price
+
+ if taxes:
+ tax = self.env['account.tax'].browse(taxes)
+ if tax.price_include:
+ price_tax_excl = price / (1 + (tax.amount / 100))
+ else:
+ price_tax_excl = price
+
+ line.amount_cashback = price_tax_excl * cashback_percent
+
# @api.onchange('vendor_id')
# def onchange_vendor_id(self):
# # TODO : need to change this logic @stephan
diff --git a/indoteknik_custom/models/shipment_group.py b/indoteknik_custom/models/shipment_group.py
index 7203b566..ce4a9fdd 100644
--- a/indoteknik_custom/models/shipment_group.py
+++ b/indoteknik_custom/models/shipment_group.py
@@ -2,6 +2,7 @@ from odoo import models, api, fields
from odoo.exceptions import AccessError, UserError, ValidationError
from datetime import timedelta, date
import logging
+from markupsafe import escape as html_escape
_logger = logging.getLogger(__name__)
@@ -16,7 +17,21 @@ class ShipmentGroup(models.Model):
partner_id = fields.Many2one('res.partner', string='Customer')
carrier_id = fields.Many2one('delivery.carrier', string='Ekspedisi')
total_colly_line = fields.Float(string='Total Colly', compute='_compute_total_colly_line')
+ is_multi_partner = fields.Boolean(string='Is Multi Partner', compute='_compute_is_multi_partner')
+ partner_ids = fields.Many2many('res.partner', string='Customers', compute='_compute_partner_ids')
+ driver = fields.Many2one('res.users', string='Driver')
+ @api.depends('shipment_line.partner_id')
+ def _compute_partner_ids(self):
+ for rec in self:
+ rec.partner_ids = rec.shipment_line.mapped('partner_id').ids
+
+ @api.depends('shipment_line.partner_id')
+ def _compute_is_multi_partner(self):
+ for rec in self:
+ partners = rec.shipment_line.mapped('partner_id')
+ rec.is_multi_partner = len(partners) > 1
+
def sync_api_shipping(self):
for rec in self.shipment_line:
picking_names = [lines.picking_id.name for lines in self.shipment_line]
@@ -97,14 +112,14 @@ class ShipmentGroupLine(models.Model):
@api.onchange('picking_id')
def onchange_picking_id(self):
if self.picking_id:
- picking = self.env['stock.picking'].browse(self.picking_id.id)
+ picking = self.picking_id
if self.shipment_id.carrier_id and self.shipment_id.carrier_id != picking.carrier_id:
raise UserError('carrier must be same as shipment group')
-
+
if picking.total_mapping_koli == 0:
raise UserError(f'Picking {picking.name} tidak memiliki mapping koli')
-
+
self.partner_id = picking.partner_id
self.shipping_paid_by = picking.sale_id.shipping_paid_by
self.carrier_id = picking.carrier_id.id
@@ -115,6 +130,9 @@ class ShipmentGroupLine(models.Model):
self.sale_id = picking.sale_id
+ if self.shipment_id:
+ self.shipment_id._compute_is_multi_partner()
+
@api.model
def create(self, vals):
record = super(ShipmentGroupLine, self).create(vals)
diff --git a/indoteknik_custom/models/stock_inventory.py b/indoteknik_custom/models/stock_inventory.py
index 84eb5a17..cb7d3773 100644
--- a/indoteknik_custom/models/stock_inventory.py
+++ b/indoteknik_custom/models/stock_inventory.py
@@ -16,6 +16,11 @@ class StockInventory(models.Model):
('in', 'Adjusment In'),
('out', 'Adjusment Out'),
], string='Adjusments Type', required=True)
+ approval_state = fields.Selection([
+ ('logistic', 'Logistic'),
+ ('accounting', 'Accounting'),
+ ('approved', 'Approved'),
+ ], default='logistic', tracking=True)
def _generate_number_stock_inventory(self):
"""Men-generate nomor untuk semua stock inventory yang belum memiliki number."""
@@ -53,8 +58,11 @@ class StockInventory(models.Model):
return "00001" # Jika belum ada data, mulai dari 00001
def action_start(self):
- if self.env.user.id not in [21, 17, 571, 28]:
- raise UserError("Hanya Rafly, Denise, Iqmal, dan Stephan yang bisa start inventory")
+ if self.approval_state != 'approved' and self.adjusment_type == 'out':
+ raise UserError('Harus melalui proses approval')
+ if self.adjusment_type == 'in':
+ if self.env.user.id not in [21, 17, 571, 28]:
+ raise UserError("Hanya Rafly, Denise, Iqmal, dan Stephan yang bisa start inventory")
return super(StockInventory, self).action_start()
@api.model
@@ -69,6 +77,20 @@ class StockInventory(models.Model):
self._assign_number(order) # Generate number setelah save
return order
+
+ def action_approve(self):
+ if self.adjusment_type == 'out':
+ for rec in self:
+ if rec.approval_state == 'logistic':
+ if not rec.env.user.has_group('indoteknik_custom.group_role_logistic'):
+ raise UserError("Harus diapprove logistic")
+ rec.approval_state = 'accounting'
+ elif rec.approval_state == 'accounting':
+ if not rec.env.user.has_group('indoteknik_custom.group_role_fat'):
+ raise UserError("Harus diapprove accounting")
+ rec.approval_state = 'approved'
+ else:
+ raise UserError("Sudah Approved")
def write(self, vals):
"""Jika adjusment_type diubah, generate ulang nomor."""
diff --git a/indoteknik_custom/models/stock_picking.py b/indoteknik_custom/models/stock_picking.py
index 2465fa96..065b1484 100644
--- a/indoteknik_custom/models/stock_picking.py
+++ b/indoteknik_custom/models/stock_picking.py
@@ -203,6 +203,16 @@ class StockPicking(models.Model):
is_so_fiktif = fields.Boolean('SO Fiktif?', compute='_compute_is_so_fiktif', tracking=3)
payment_term = fields.Char('Payment Term', compute='_get_partner_payment_term')
is_rev_tg = fields.Boolean('Administrasi')
+ shipment_group_id = fields.Many2one('shipment.group', string='Shipment Group', compute='_compute_shipment_group_id')
+
+ @api.depends('shipment_group_id')
+ def _compute_shipment_group_id(self):
+ for record in self:
+ shipment_line = self.env['shipment.group.line'].search([('picking_id', '=', record.id)], limit=1)
+ if shipment_line:
+ record.shipment_group_id = shipment_line.shipment_id.id
+ else:
+ record.shipment_group_id = False
@api.depends('sale_id.payment_term_id')
def _get_partner_payment_term(self):
@@ -1387,7 +1397,8 @@ class StockPicking(models.Model):
])
if quant:
- return quant.quantity
+ return sum(quant.mapped('quantity'))
+ # return quant.quantity
return 0
diff --git a/indoteknik_custom/models/tukar_guling_po.py b/indoteknik_custom/models/tukar_guling_po.py
index ae58d509..1ee10679 100644
--- a/indoteknik_custom/models/tukar_guling_po.py
+++ b/indoteknik_custom/models/tukar_guling_po.py
@@ -582,7 +582,23 @@ class TukarGulingPO(models.Model):
('group_id', '=', group.id),
('state', '=', 'done')
])
- bu_inputs = po_pickings.filtered(lambda p: p.picking_type_id.id == 28)
+
+ product_ids = set(record.line_ids.mapped("product_id").ids)
+
+ _logger.info("TG product_ids: %s", product_ids)
+
+ def _get_moves(picking):
+ return picking.move_ids_without_package if picking.move_ids_without_package else picking.move_lines
+
+ bu_inputs = po_pickings.filtered(
+ lambda p: p.picking_type_id.id == 28 and any(
+ m.product_id.id in product_ids
+ for m in _get_moves(p)
+ )
+ )
+
+ _logger.info("BU INPUT dengan product sama: %s", bu_inputs.mapped("name"))
+
bu_puts = po_pickings.filtered(lambda p: p.picking_type_id.id == 75)
else:
raise UserError("Group ID tidak ditemukan pada BU Operations.")
@@ -711,12 +727,26 @@ class TukarGulingPO(models.Model):
# Ambil pasangannya di BU INPUT (asumsi urutan sejajar)
sorted_bu_puts = sorted(bu_puts, key=lambda p: p.name)
+ # sorted_bu_inputs = sorted(bu_inputs, key=lambda p: p.name)
+
+ # if bu_put_index >= len(sorted_bu_inputs):
+ # raise UserError("Tidak ditemukan pasangan BU INPUT untuk BU PUT yang dipilih.")
+
+ # paired = [(sorted_bu_puts[bu_put_index], sorted_bu_inputs[bu_put_index])]
sorted_bu_inputs = sorted(bu_inputs, key=lambda p: p.name)
- if bu_put_index >= len(sorted_bu_inputs):
- raise UserError("Tidak ditemukan pasangan BU INPUT untuk BU PUT yang dipilih.")
+ if not sorted_bu_inputs:
+ raise UserError(
+ "Tidak ditemukan BU INPUT yang memiliki product TG."
+ )
- paired = [(sorted_bu_puts[bu_put_index], sorted_bu_inputs[bu_put_index])]
+ paired = [(record.operations, sorted_bu_inputs[0])]
+
+ _logger.info(
+ "🔗 Pairing BU PUT %s dengan BU INPUT %s",
+ record.operations.name,
+ sorted_bu_inputs[0].name
+ )
for bu_put, bu_input in paired:
vrt = _create_return_from_picking(bu_put, bu_put_qty_map)
diff --git a/indoteknik_custom/models/update_depreciation_move_wizard.py b/indoteknik_custom/models/update_depreciation_move_wizard.py
new file mode 100644
index 00000000..7d465f1d
--- /dev/null
+++ b/indoteknik_custom/models/update_depreciation_move_wizard.py
@@ -0,0 +1,48 @@
+from odoo import models, fields, api
+from odoo.exceptions import UserError
+
+class UpdateDepreciationMoveWizard(models.TransientModel):
+ _name = 'update.depreciation.move.wizard'
+ _description = 'Wizard untuk Update Move Check Depreciation Line'
+
+ target_date = fields.Date(string="Tanggal Depresiasi", required=True)
+
+ # def action_update_move_check(self):
+ # lines = self.env['account.asset.depreciation.line'].search([
+ # ('depreciation_date', '=', self.target_date),
+ # ])
+ # if not lines:
+ # raise UserError("Tidak ada baris depresiasi dengan tanggal tersebut.")
+
+ # updated_count = 0
+ # for line in lines:
+ # if not line.move_check:
+ # line.move_check = True
+ # line.move_posted_check = True
+ # updated_count += 1
+
+ # return {
+ # 'type': 'ir.actions.client',
+ # 'tag': 'display_notification',
+ # 'params': {
+ # 'title': 'Update Selesai',
+ # 'message': f'{updated_count} baris berhasil di-update.',
+ # 'type': 'success',
+ # 'sticky': False,
+ # }
+ # }
+
+ def action_update_move_check(self):
+ assets = self.env['account.asset.asset']
+ assets.compute_generated_entries(self.target_date)
+
+ return {
+ 'type': 'ir.actions.client',
+ 'tag': 'display_notification',
+ 'params': {
+ 'title': 'Update Selesai',
+ 'message': 'Depresiasi berhasil di-update.',
+ 'type': 'success',
+ 'sticky': False,
+ }
+ } \ No newline at end of file
diff --git a/indoteknik_custom/models/x_manufactures.py b/indoteknik_custom/models/x_manufactures.py
index 9e214d92..0c3bfa3b 100755
--- a/indoteknik_custom/models/x_manufactures.py
+++ b/indoteknik_custom/models/x_manufactures.py
@@ -50,7 +50,7 @@ class XManufactures(models.Model):
# user_id = fields.Many2one('res.users', string='Responsible', domain="['|'('id', '=', 19), ('id', '=', 6)]", help="Siapa yang bertanggung jawab")
user_id = fields.Many2one('res.users', string='Responsible', help="Siapa yang bertanggung jawab")
override_vendor_id = fields.Many2one('res.partner', string='Override Vendor')
- # cashback_percent = fields.Float(string='Cashback Percent')
+ cashback_percent = fields.Float(string='Cashback Percent', default=0)
def _compute_vendor_ids(self):
for manufacture in self:
diff --git a/indoteknik_custom/report/purchase_report_internal.xml b/indoteknik_custom/report/purchase_report_internal.xml
new file mode 100644
index 00000000..7df847de
--- /dev/null
+++ b/indoteknik_custom/report/purchase_report_internal.xml
@@ -0,0 +1,201 @@
+<?xml version="1.0" encoding="utf-8"?>
+<odoo>
+ <data>
+ <!-- Report Action -->
+ <record id="action_report_purchaseorder_internal" model="ir.actions.report">
+ <field name="name">Purchase Order (Internal)</field>
+ <field name="model">purchase.order</field>
+ <field name="report_type">qweb-pdf</field>
+ <field name="report_name">indoteknik_custom.report_purchaseorder_internal</field>
+ <field name="report_file">indoteknik_custom.report_purchaseorder_internal</field>
+ <field name="print_report_name">
+ ('%s - %s' % (object.name, object.partner_id.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_internal">
+ <t t-call="web.html_container">
+ <t t-foreach="docs" t-as="doc">
+ <t t-call="indoteknik_custom.report_purchaseorder_internal_document" t-lang="doc.partner_id.lang"/>
+ </t>
+ </t>
+ </template>
+
+ <template id="report_purchaseorder_internal_document">
+ <t t-call="web.html_container">
+ <t t-set="doc" t-value="doc.with_context(lang=doc.partner_id.lang)" />
+
+ <!-- HEADER -->
+ <div class="header">
+ <img src="https://erp.indoteknik.com/api/image/ir.attachment/datas/2498521"
+ style="width:100%; display:block;"/>
+ </div>
+
+ <!-- PAGE CONTENT -->
+ <div class="article" style="margin: 0 1.5cm 0 1.5cm; font-family:Arial, sans-serif; font-size:14px; color:#333;">
+
+ <!-- TITLE -->
+ <h2 style="text-align:center; margin:8px 0 0 0; color:#d32f2f; font-weight:800; letter-spacing:1px;">
+ PURCHASE ORDER
+ </h2>
+ <h4 style="text-align:center; margin:4px 0 20px 0; font-weight:normal; color:#555;">
+ No. <span t-field="doc.name"/>
+ </h4>
+
+ <!-- TOP INFO -->
+ <table style="width:100%; margin-bottom:20px; border-radius:8px; box-shadow:0 1px 4px rgba(0,0,0,0.1); overflow:hidden; border:1px solid #ddd;">
+ <tr style="background:#fafafa;">
+ <td style="padding:10px 12px;"><strong>Term Of Payment:</strong> <span t-field="doc.payment_term_id.name"/></td>
+ <td style="padding:10px 12px;"><strong>Order Date:</strong> <span t-field="doc.date_order" t-options='{"widget": "date"}'/></td>
+ <td style="padding:10px 12px;"><strong>Responsible:</strong> <span t-field="doc.user_id"/></td>
+ </tr>
+ </table>
+
+ <!-- VENDOR & DELIVERY -->
+ <table style="width:100%; margin-bottom:24px; border-spacing:16px 0;">
+ <tr>
+ <td style="width:50%; border:1px solid #ccc; border-radius:8px; padding:10px; background:#fcfcfc; vertical-align:top;">
+ <strong style="color:#d32f2f;">Alamat Pengiriman</strong><br/>
+ PT. Indoteknik Dotcom Gemilang<br/>
+ <t t-if="doc.overseas_po == True">
+ JALAN BANDENGAN UTARA 85A NO.8-9 RT. 003<br/>
+ RW. 016, PENJARINGAN, PENJARINGAN, KOTA<br/>
+ ADM. JAKARTA UTARA, DKI JAKARTA
+ </t>
+ <t t-else="">
+ Jl. Bandengan Utara Komp A &amp; B RT.<br/>
+ Penjaringan, Kec. Penjaringan, Jakarta<br/>
+ (BELAKANG INDOMARET)
+ </t>
+ <br/>
+ Daerah Khusus Ibukota Jakarta 14440
+ </td>
+ <td style="width:50%; border:1px solid #ccc; border-radius:8px; padding:10px; background:#fcfcfc; vertical-align:top;">
+ <strong style="color:#d32f2f;">Nama Vendor</strong><br/>
+ <span t-field="doc.partner_id.name"/><br/>
+ <span t-field="doc.partner_id.street"/><br/>
+ <span t-field="doc.partner_id.city"/> - <span t-field="doc.partner_id.zip"/>
+ </td>
+ </tr>
+ </table>
+
+ <!-- ORDER LINES -->
+ <table style="border-collapse:collapse; width:100%; margin-top:16px; font-size:14px;">
+ <tbody>
+ <!-- HEADER -->
+ <tr style="background:#e53935; color:white;">
+ <th style="border:1px solid #ccc; padding:8px; text-align:left;">No. &amp; Description</th>
+ <th style="border:1px solid #ccc; padding:8px; text-align:left;">Image</th>
+ <th style="border:1px solid #ccc; padding:8px; text-align:center;">Quantity</th>
+ <th style="border:1px solid #ccc; padding:8px; text-align:center;">Unit Price</th>
+ <th style="border:1px solid #ccc; padding:8px; text-align:center;">Taxes</th>
+ <th style="border:1px solid #ccc; padding:8px; text-align:center;">Subtotal</th>
+ </tr>
+
+ <!-- ISI ORDER LINE -->
+ <t t-foreach="doc.order_line" t-as="line" t-index="line_index">
+ <tr t-attf-style="background-color: #{ '#fafafa' if line_index % 2 == 0 else 'white' };">
+
+ <!-- NO & DESCRIPTION + IMAGE -->
+ <td style="border:1px solid #ccc; padding: 6px; display:flex; align-items:center; gap:10px;">
+ <!-- TEKS -->
+ <div style="display:flex; flex-direction:column; flex:1;">
+ <span style="font-weight:bold; margin-bottom:2px;">
+ <t t-esc="line_index + 1"/>.
+ <t t-if="line.product_id.id in [114360, 595346, 610166, 420315]">
+ <t t-esc="line.name"/>
+ </t>
+ <t t-else="">
+ <t t-esc="line.product_id.display_name"/>
+ </t>
+ </span>
+ </div>
+
+ </td>
+
+ <td style="border:1px solid #ccc; padding:6px; text-align:center;">
+ <t t-if="line.image_small">
+ <img t-att-src="image_data_uri(line.image_small)"
+ style="width:100px; height:100px; object-fit:contain; border:1px solid #ddd; border-radius:6px; background:#fff;"/>
+ </t>
+ </td>
+ <!-- QTY -->
+ <td style="border:1px solid #ccc; padding:6px; text-align:center;">
+ <span t-field="line.product_qty"/> <span t-field="line.product_uom"/>
+ </td>
+
+ <!-- UNIT PRICE -->
+ <td style="border:1px solid #ccc; padding:6px; text-align:center;">
+ <span t-field="line.price_unit"/>
+ </td>
+
+ <!-- TAXES -->
+ <td style="border:1px solid #ccc; padding:6px; text-align:center;">
+ <span t-esc="', '.join(map(lambda x: (x.description or x.name), line.taxes_id))"/>
+ </td>
+
+ <!-- SUBTOTAL -->
+ <td style="border:1px solid #ccc; padding:6px; text-align:right; font-weight:bold;">
+ <span t-field="line.price_subtotal"/>
+ </td>
+ </tr>
+
+ <!-- WEBSITE DESCRIPTION -->
+ <t t-if="line.show_description == True">
+ <tr t-attf-style="background-color: #{ '#fef5f5' if line_index % 2 == 0 else '#fffafa' }; ">
+ <td colspan="6" style="padding: 10px 14px; font-size:10px; line-height:1.3; font-style:italic; color:#555; border-left:1px solid #ccc; border-right:1px solid #ccc; border-bottom:1px solid #ccc;">
+ <div t-raw="line.product_id.website_description"/>
+ </td>
+ </tr>
+ </t>
+ </t>
+ </tbody>
+ </table>
+
+
+ <!-- TOTALS -->
+ <table style="margin-top:24px; margin-left:auto; width:40%; font-size:14px; border:1px solid #ddd; border-radius:6px; box-shadow:0 1px 3px rgba(0,0,0,0.08);">
+ <tr style="background:#fafafa;">
+ <td style="padding:8px;"><strong>Subtotal</strong></td>
+ <td style="text-align:right; padding:8px;"><span t-field="doc.amount_untaxed"/></td>
+ </tr>
+ <tr>
+ <td style="padding:8px;">Taxes</td>
+ <td style="text-align:right; padding:8px;"><span t-field="doc.amount_tax"/></td>
+ </tr>
+ <tr style="background:#fbe9e7; font-weight:bold; color:#d32f2f;">
+ <td style="padding:8px;">Total</td>
+ <td style="text-align:right; padding:8px;"><span t-field="doc.amount_total"/></td>
+ </tr>
+ <tr>
+ <td style="padding:8px;">Margin PO %</td>
+ <td style="text-align:right; padding:8px;"><span t-field="doc.total_percent_margin"/></td>
+ </tr>
+ <tr>
+ <td style="padding:8px;">Margin SO %</td>
+ <td style="text-align:right; padding:8px;"><span t-field="doc.total_so_percent_margin"/></td>
+ </tr>
+ </table>
+
+ <!-- NOTES -->
+ <div style="margin-top:24px; padding:12px; border-top:1px solid #ddd; font-style:italic; color:#555;">
+ <p t-field="doc.notes"/>
+ </div>
+ </div>
+
+ <!-- STATIC FOOTER -->
+ <div class="footer">
+ <img src="https://erp.indoteknik.com/api/image/ir.attachment/datas/2859765"
+ style="width:100%; display:block;"/>
+ </div>
+
+ </t>
+ </template>
+
+
+
+</odoo>
diff --git a/indoteknik_custom/security/ir.model.access.csv b/indoteknik_custom/security/ir.model.access.csv
index 84545488..50e2b382 100755
--- a/indoteknik_custom/security/ir.model.access.csv
+++ b/indoteknik_custom/security/ir.model.access.csv
@@ -216,4 +216,5 @@ access_surat_piutang_line_user,surat.piutang.line user,model_surat_piutang_line,
access_sj_tele,access.sj.tele,model_sj_tele,base.group_system,1,1,1,1
access_stock_picking_sj_document,stock.picking.sj.document,model_stock_picking_sj_document,base.group_user,1,1,1,1
access_gudang_service,gudang.service,model_gudang_service,base.group_user,1,1,1,1
-access_gudang_service_line,gudang.service.line,model_gudang_service_line,base.group_user,1,1,1,1 \ No newline at end of file
+access_gudang_service_line,gudang.service.line,model_gudang_service_line,base.group_user,1,1,1,1
+access_update_depreciation_move_wizard,access.update.depreciation.move.wizard,model_update_depreciation_move_wizard,,1,1,1,1
diff --git a/indoteknik_custom/views/account_move_line.xml b/indoteknik_custom/views/account_move_line.xml
index cb24a0f0..838596c8 100644
--- a/indoteknik_custom/views/account_move_line.xml
+++ b/indoteknik_custom/views/account_move_line.xml
@@ -22,4 +22,16 @@
</field>
</record>
</data>
+ <data>
+ <record id="action_gl_reconcile_server" model="ir.actions.server">
+ <field name="name">Reconcile Selected</field>
+ <field name="model_id" ref="account.model_account_move_line"/>
+ <field name="binding_model_id" ref="account.model_account_move_line"/>
+ <field name="binding_view_types">list</field>
+ <field name="state">code</field>
+ <field name="code">
+ action = records.action_gl_reconcile()
+ </field>
+ </record>
+ </data>
</odoo>
diff --git a/indoteknik_custom/views/advance_payment_request.xml b/indoteknik_custom/views/advance_payment_request.xml
index 7f422aa9..340e0caf 100644
--- a/indoteknik_custom/views/advance_payment_request.xml
+++ b/indoteknik_custom/views/advance_payment_request.xml
@@ -236,6 +236,7 @@
<filter string="PUM" name="filter_pum" domain="[('type_request','=','pum')]"/>
<filter string="Reimburse" name="filter_reimburse" domain="[('type_request','=','reimburse')]"/>
<separator/>
+ <filter string="Cancelled" name="filter_cancelled" domain="[('status','=','cancel')]"/>
<filter string="Waiting for Approval" name="filter_waiting_approval" domain="[('status','in',['pengajuan1','pengajuan2','pengajuan3'])]"/>
<filter string="Approved" name="filter_approved" domain="[('status','=','approved')]"/>
<separator/>
diff --git a/indoteknik_custom/views/approval_date_doc.xml b/indoteknik_custom/views/approval_date_doc.xml
index 3d597aa8..a3aae3b4 100644
--- a/indoteknik_custom/views/approval_date_doc.xml
+++ b/indoteknik_custom/views/approval_date_doc.xml
@@ -14,6 +14,7 @@
<field name="approve_date"/>
<field name="approve_by"/>
<field name="create_uid"/>
+ <field name="create_date"/>
</tree>
</field>
</record>
@@ -46,6 +47,7 @@
<field name="approve_date"/>
<field name="approve_by"/>
<field name="create_uid"/>
+ <field name="create_date"/>
<field name="note" attrs="{'invisible': [('state', '!=', 'cancel')]}"/>
<field name="state" readonly="1"/>
</group>
diff --git a/indoteknik_custom/views/purchase_order.xml b/indoteknik_custom/views/purchase_order.xml
index 16b8bd44..59e317d2 100755
--- a/indoteknik_custom/views/purchase_order.xml
+++ b/indoteknik_custom/views/purchase_order.xml
@@ -105,6 +105,7 @@
<field name="amount_total" position="after">
<field name="total_margin"/>
<field name="total_so_margin"/>
+ <field name="amount_cashback"/>
<field name="total_percent_margin"/>
<field name="total_so_percent_margin"/>
</field>
diff --git a/indoteknik_custom/views/sale_order.xml b/indoteknik_custom/views/sale_order.xml
index 23fbe155..c3df92ec 100755
--- a/indoteknik_custom/views/sale_order.xml
+++ b/indoteknik_custom/views/sale_order.xml
@@ -302,6 +302,7 @@
]
}
"/>
+ <field name="amount_cashback"/>
<field name="purchase_price_md" optional="hide"/>
<field name="purchase_tax_id"
attrs="{'readonly': [('parent.approval_status', '!=', False)]}"
diff --git a/indoteknik_custom/views/shipment_group.xml b/indoteknik_custom/views/shipment_group.xml
index c3f79bda..e348867c 100644
--- a/indoteknik_custom/views/shipment_group.xml
+++ b/indoteknik_custom/views/shipment_group.xml
@@ -7,6 +7,7 @@
<tree default_order="create_date desc">
<field name="number"/>
<field name="partner_id"/>
+ <field name="partner_ids" widget="many2many_tags" optional="hide"/>
<field name="carrier_id"/>
<field name="total_colly_line"/>
</tree>
@@ -42,9 +43,12 @@
<group>
<group>
<field name="number" readonly="1"/>
+ <field name="is_multi_partner" readonly="1"/>
</group>
<group>
- <field name="partner_id" readonly="1"/>
+ <field name="partner_id" readonly="1" attrs="{'invisible': [('is_multi_partner', '=', True)]}"/>
+ <field name="partner_ids" readonly="1" widget="many2many_tags" attrs="{'invisible': [('is_multi_partner', '=', False)]}"/>
+ <field name="driver" attrs="{'invisible': [('carrier_id', '!=', 1)]}"/>
<field name="carrier_id" readonly="1"/>
<field name="total_colly_line" readonly="1"/>
</group>
diff --git a/indoteknik_custom/views/stock_inventory.xml b/indoteknik_custom/views/stock_inventory.xml
index db85f05c..89c058ea 100644
--- a/indoteknik_custom/views/stock_inventory.xml
+++ b/indoteknik_custom/views/stock_inventory.xml
@@ -6,9 +6,14 @@
<field name="model">stock.inventory</field>
<field name="inherit_id" ref="stock.view_inventory_form"/>
<field name="arch" type="xml">
+ <header>
+ <button name="action_approve" string="Approve" type="object"
+ class="btn-primary" attrs="{'invisible': [('adjusment_type', 'not in', ['out'])]}"/>
+ </header>
<xpath expr="//field[@name='location_ids']" position="after">
<field name="number" readonly="1"/>
<field name="adjusment_type" />
+ <field name="approval_state" readonly="1" attrs="{'invisible': [('adjusment_type', 'not in', ['out'])]}"/>
</xpath>
</field>
</record>
@@ -21,6 +26,7 @@
<field name="arch" type="xml">
<xpath expr="//field[@name='date']" position="after">
<field name="number"/>
+ <field name="approval_state"/>
</xpath>
</field>
</record>
diff --git a/indoteknik_custom/views/stock_picking.xml b/indoteknik_custom/views/stock_picking.xml
index 9aa0581c..9cd63e25 100644
--- a/indoteknik_custom/views/stock_picking.xml
+++ b/indoteknik_custom/views/stock_picking.xml
@@ -245,6 +245,7 @@
<field name="responsible"/>
<field name="carrier_id"
attrs="{'invisible': [('select_shipping_option_so', '=', 'biteship')]}"/>
+ <field name="shipment_group_id"/>
<field name="biteship_id" invisible="1"/>
<field name="out_code" attrs="{'invisible': [['out_code', '=', False]]}"/>
<field name="picking_code" attrs="{'invisible': [['picking_code', '=', False]]}"/>
diff --git a/indoteknik_custom/views/tukar_guling.xml b/indoteknik_custom/views/tukar_guling.xml
index 8cfb5680..609dea15 100644
--- a/indoteknik_custom/views/tukar_guling.xml
+++ b/indoteknik_custom/views/tukar_guling.xml
@@ -133,5 +133,29 @@
</form>
</field>
</record>
+ <record id="view_tukar_guling_filter" model="ir.ui.view">
+ <field name="name">tukar.guling.filter</field>
+ <field name="model">tukar.guling</field>
+ <field name="arch" type="xml">
+ <search string="Tukar Guling">
+ <field name="name" string="No. Dokumen"/>
+ <field name="partner_id" string="Customer"/>
+ <field name="origin" string="SO Number"/>
+ <field name="operations" string="Operations"/>
+ <!-- <filter string="Pengajuan Saya" name="my_tukar_guling" domain="[('create_uid', '=', uid)]"/> -->
+ <separator/>
+ <filter string="Tukar Guling" name="tukar_guling" domain="[('return_type', '=', 'tukar_guling')]"/>
+ <filter string="Return SO" name="return_so" domain="[('return_type', '=', 'retur_so')]"/>
+ <separator/>
+ <filter string="Approval Sales" name="approval_sales" domain="[('state', '=', 'approval_sales')]"/>
+ <filter string="Approval Logistic" name="approval_logistic" domain="[('state', '=', 'approval_logistic')]"/>
+ <filter string="Approval Finance" name="approval_finance" domain="[('state', '=', 'approval_finance')]"/>
+ <filter string="Approved" name="approved" domain="[('state', '=', 'approved')]"/>
+ <separator/>
+ <filter string="Done" name="done" domain="[('state', '=', 'done')]"/>
+ <filter string="Cancelled" name="cancel" domain="[('state', '=', 'cancel')]"/>
+ </search>
+ </field>
+ </record>
</data>
</odoo>
diff --git a/indoteknik_custom/views/update_depreciation_move_wizard_view.xml b/indoteknik_custom/views/update_depreciation_move_wizard_view.xml
new file mode 100644
index 00000000..ff128a71
--- /dev/null
+++ b/indoteknik_custom/views/update_depreciation_move_wizard_view.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<odoo>
+ <record id="view_update_depreciation_move_wizard_form" model="ir.ui.view">
+ <field name="name">update.depreciation.move.wizard.form</field>
+ <field name="model">update.depreciation.move.wizard</field>
+ <field name="arch" type="xml">
+ <form string="Update Move Check">
+ <group>
+ <field name="target_date"/>
+ </group>
+ <footer>
+ <button string="Update" type="object" name="action_update_move_check" class="btn-primary"/>
+ <button string="Batal" special="cancel" class="btn-secondary"/>
+ </footer>
+ </form>
+ </field>
+ </record>
+
+ <record id="update_depreciation_move_wizard_action" model="ir.actions.act_window">
+ <field name="name">Update Depreciation Asset</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">update.depreciation.move.wizard</field>
+ <field name="view_mode">form</field>
+ <field name="target">new</field>
+ </record>
+
+ <menuitem
+ id="menu_update_depreciation_move_wizard"
+ name="Update Depreciation Asset"
+ parent="account.menu_finance_entries_management"
+ sequence="4"
+ action="update_depreciation_move_wizard_action"
+ />
+</odoo>
+ \ No newline at end of file
diff --git a/indoteknik_custom/views/x_manufactures.xml b/indoteknik_custom/views/x_manufactures.xml
index d5cec350..b52fe795 100755
--- a/indoteknik_custom/views/x_manufactures.xml
+++ b/indoteknik_custom/views/x_manufactures.xml
@@ -82,7 +82,7 @@
<field name="x_negara_asal"/>
<field name="x_short_desc"/>
<field name="x_manufacture_level"/>
- <!-- <field name="cashback_percent" widget="percentage"/> -->
+ <field name="cashback_percent" widget="percentage"/>
<field name="x_produk_aksesoris_sparepart"/>
<field name="cache_reset_status"/>
<field name="parent_id"/>