From 387334dc0929087ac51cc09a90d2db15d79413f1 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Thu, 12 Feb 2026 14:18:25 +0700 Subject: automatic reconcile by GL and automatic penyusutan asset --- indoteknik_custom/__manifest__.py | 3 +- indoteknik_custom/models/__init__.py | 1 + indoteknik_custom/models/account_move_line.py | 65 +++++++++++++++++++++- .../models/update_depreciation_move_wizard.py | 48 ++++++++++++++++ indoteknik_custom/security/ir.model.access.csv | 1 + indoteknik_custom/views/account_move_line.xml | 12 ++++ .../views/update_depreciation_move_wizard_view.xml | 35 ++++++++++++ 7 files changed, 163 insertions(+), 2 deletions(-) create mode 100644 indoteknik_custom/models/update_depreciation_move_wizard.py create mode 100644 indoteknik_custom/views/update_depreciation_move_wizard_view.xml diff --git a/indoteknik_custom/__manifest__.py b/indoteknik_custom/__manifest__.py index 61eef35b..51cfa592 100755 --- a/indoteknik_custom/__manifest__.py +++ b/indoteknik_custom/__manifest__.py @@ -193,7 +193,8 @@ 'views/close_tempo_mail_template.xml', 'views/domain_apo.xml', 'views/uom_uom.xml', - 'views/commission_internal.xml' + 'views/commission_internal.xml', + 'views/update_depreciation_move_wizard_view.xml' ], 'demo': [], 'css': [], diff --git a/indoteknik_custom/models/__init__.py b/indoteknik_custom/models/__init__.py index a14c766e..19a96bee 100755 --- a/indoteknik_custom/models/__init__.py +++ b/indoteknik_custom/models/__init__.py @@ -165,3 +165,4 @@ from . import partial_delivery from . import domain_apo from . import uom_uom from . import commission_internal +from . import update_depreciation_move_wizard \ No newline at end of file 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/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/security/ir.model.access.csv b/indoteknik_custom/security/ir.model.access.csv index d501de1a..bc290370 100755 --- a/indoteknik_custom/security/ir.model.access.csv +++ b/indoteknik_custom/security/ir.model.access.csv @@ -215,3 +215,4 @@ access_surat_piutang_user,surat.piutang user,model_surat_piutang,,1,1,1,1 access_surat_piutang_line_user,surat.piutang.line user,model_surat_piutang_line,,1,1,1,1 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_update_depreciation_move_wizard,access.update.depreciation.move.wizard,model_update_depreciation_move_wizard,,1,1,1,1 \ No newline at end of file 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 @@ + + + Reconcile Selected + + + list + code + + action = records.action_gl_reconcile() + + + 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 @@ + + + + update.depreciation.move.wizard.form + update.depreciation.move.wizard + +
+ + + +
+
+
+
+
+ + + Update Depreciation Asset + ir.actions.act_window + update.depreciation.move.wizard + form + new + + + +
+ \ No newline at end of file -- cgit v1.2.3 From 37e0beac646ee2e676ff935e8289cf3189b3c21b Mon Sep 17 00:00:00 2001 From: Mqdd Date: Fri, 13 Feb 2026 09:42:53 +0700 Subject: check archived uom and product in sale order confirm --- indoteknik_custom/models/sale_order.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py index 49e36279..2548c7b3 100755 --- a/indoteknik_custom/models/sale_order.py +++ b/indoteknik_custom/models/sale_order.py @@ -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 -- cgit v1.2.3 From 57221d2537684168a4761ce2eb0b2ede5586325f Mon Sep 17 00:00:00 2001 From: Mqdd Date: Sat, 14 Feb 2026 12:02:15 +0700 Subject: fix flow approval state adjust out --- indoteknik_custom/models/stock_inventory.py | 44 +++++++++++++++++------------ indoteknik_custom/views/stock_inventory.xml | 7 ++--- 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/indoteknik_custom/models/stock_inventory.py b/indoteknik_custom/models/stock_inventory.py index cb7d3773..b3580a4c 100644 --- a/indoteknik_custom/models/stock_inventory.py +++ b/indoteknik_custom/models/stock_inventory.py @@ -16,11 +16,35 @@ 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) + ], default='logistic', tracking=True, readonly=True) + + def action_validate(self): + if self.adjusment_type == 'out': + + if self.approval_state != 'approved': + + if self.approval_state == 'logistic': + if not self.env.user.has_group('indoteknik_custom.group_role_logistic'): + raise UserError("Adjustment Out harus dilakukan oleh Logistic") + self.approval_state = 'accounting' + return True + + elif self.approval_state == 'accounting': + if not self.env.user.has_group('indoteknik_custom.group_role_fat'): + raise UserError("Adjustment Out harus dilakukan oleh Accounting") + self.approval_state = 'approved' + return True + + else: + raise UserError("Adjustment Out harus melalui approval terlebih dahulu.") + + return super(StockInventory, self).action_validate() + def _generate_number_stock_inventory(self): """Men-generate nomor untuk semua stock inventory yang belum memiliki number.""" @@ -58,10 +82,7 @@ class StockInventory(models.Model): return "00001" # Jika belum ada data, mulai dari 00001 def action_start(self): - 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]: + if self.env.user.id not in [21, 17, 571, 28, 25]: raise UserError("Hanya Rafly, Denise, Iqmal, dan Stephan yang bisa start inventory") return super(StockInventory, self).action_start() @@ -78,19 +99,6 @@ class StockInventory(models.Model): 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/views/stock_inventory.xml b/indoteknik_custom/views/stock_inventory.xml index 89c058ea..ab1b6eec 100644 --- a/indoteknik_custom/views/stock_inventory.xml +++ b/indoteknik_custom/views/stock_inventory.xml @@ -6,14 +6,10 @@ stock.inventory -
-
- +
@@ -26,6 +22,7 @@ + -- cgit v1.2.3 From 9e10c2db3c49bbca718061dbd852b8db513bed0f Mon Sep 17 00:00:00 2001 From: Mqdd Date: Sun, 15 Feb 2026 17:37:04 +0700 Subject: fix flow adjust out --- indoteknik_custom/models/stock_inventory.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/indoteknik_custom/models/stock_inventory.py b/indoteknik_custom/models/stock_inventory.py index b3580a4c..efd52e5c 100644 --- a/indoteknik_custom/models/stock_inventory.py +++ b/indoteknik_custom/models/stock_inventory.py @@ -21,7 +21,7 @@ class StockInventory(models.Model): ('logistic', 'Logistic'), ('accounting', 'Accounting'), ('approved', 'Approved'), - ], default='logistic', tracking=True, readonly=True) + ], tracking=True, readonly=True) def action_validate(self): if self.adjusment_type == 'out': @@ -38,7 +38,7 @@ class StockInventory(models.Model): if not self.env.user.has_group('indoteknik_custom.group_role_fat'): raise UserError("Adjustment Out harus dilakukan oleh Accounting") self.approval_state = 'approved' - return True + return super(StockInventory, self).action_validate() else: raise UserError("Adjustment Out harus melalui approval terlebih dahulu.") @@ -89,6 +89,12 @@ class StockInventory(models.Model): @api.model def create(self, vals): """Pastikan nomor hanya dibuat saat penyimpanan.""" + + if vals.get('adjusment_type') == 'in': + vals['approval_state'] = False + elif vals.get('adjusment_type') == 'out': + vals['approval_state'] = 'logistic' + if 'adjusment_type' in vals and not vals.get('number'): vals['number'] = False # Jangan buat number otomatis dulu @@ -105,6 +111,10 @@ class StockInventory(models.Model): res = super(StockInventory, self).write(vals) if 'adjusment_type' in vals: for record in self: + if record.adjusment_type == 'in': + record.approval_state = False + elif record.adjusment_type == 'out' and record.approval_state == False: + record.approval_state = 'logistic' self._assign_number(record) return res -- cgit v1.2.3