From 38ba3d7f5b59a4444d9eb953a6c83e4ab6015ba6 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Fri, 4 Jul 2025 09:18:50 +0700 Subject: approval payment term --- indoteknik_custom/models/approval_payment_term.py | 82 +++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 indoteknik_custom/models/approval_payment_term.py (limited to 'indoteknik_custom/models/approval_payment_term.py') diff --git a/indoteknik_custom/models/approval_payment_term.py b/indoteknik_custom/models/approval_payment_term.py new file mode 100644 index 00000000..81eb1908 --- /dev/null +++ b/indoteknik_custom/models/approval_payment_term.py @@ -0,0 +1,82 @@ +from odoo import models, api, fields +from odoo.exceptions import AccessError, UserError, ValidationError +from datetime import timedelta, date, datetime +import logging + +_logger = logging.getLogger(__name__) + +class ApprovalPaymentTerm(models.Model): + _name = "approval.payment.term" + _description = "Approval Payment Term" + _inherit = ['mail.thread'] + _rec_name = 'number' + + number = fields.Char(string='Document No', index=True, copy=False, readonly=True, tracking=True) + partner_id = fields.Many2one('res.partner', string='Partner', copy=False) + property_payment_term_id = fields.Many2one('account.payment.term', string='Payment Term', copy=False, tracking=True) + parent_id = fields.Many2one('res.partner', string='Related Company', copy=False) + blocking_stage = fields.Float(string='Blocking Amount', + help="Cannot make sales once the selected " + "customer is crossed blocking amount." + "Set its value to 0.00 to disable " + "this feature", tracking=True, copy=False) + warning_stage = fields.Float(string='Warning Amount', + help="A warning message will appear once the " + "selected customer is crossed warning " + "amount. Set its value to 0.00 to" + " disable this feature", tracking=True, copy=False) + active_limit = fields.Boolean('Active Credit Limit', copy=False, tracking=True) + approve_sales_manager = fields.Boolean('Approve Sales Manager', tracking=True, copy=False) + approve_finance = fields.Boolean('Approve Finance', tracking=True, copy=False) + approve_leader = fields.Boolean('Approve Pimpinan', tracking=True, copy=False) + reason = fields.Text('Reason', tracking=True) + approve_date = fields.Datetime('Approve Date') + + + @api.constrains('partner_id') + def constrains_partner_id(self): + if self.partner_id: + self.parent_id = self.partner_id.parent_id.id if self.partner_id.parent_id else None + self.blocking_stage = self.partner_id.blocking_stage + self.warning_stage = self.partner_id.warning_stage + self.active_limit = self.partner_id.active_limit + self.property_payment_term_id = self.partner_id.property_payment_term_id.id + + def button_approve(self): + user = self.env.user + is_it = user.has_group('indoteknik_custom.group_role_it') + + if is_it or user.id == 19: + self.approve_sales_manager = True + return + + if is_it or user.id == 688 and self.approve_sales_manager: + self.approve_finance = True + return + + if is_it or user.id == 7 and self.approve_sales_manager and self.approve_finance: + self.approve_leader = True + + if not is_it or not self.approve_finance: + raise UserError('Harus Approval Finance!!') + if not is_it or not self.approve_leader: + raise UserError('Harus Approval Pimpinan!!') + + if user.id == 7: + if not self.approve_finance: + raise UserError('Belum Di Approve Oleh Finance') + + if self.approve_leader == True: + self.partner_id.write({ + '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 + }) + self.approve_date = datetime.utcnow() + + @api.model + def create(self, vals): + vals['number'] = self.env['ir.sequence'].next_by_code('approval.payment.term') or '0' + result = super(ApprovalPaymentTerm, self).create(vals) + return result -- cgit v1.2.3 From 05879e52666f02c117aee569621556db97ef345c Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Tue, 8 Jul 2025 09:11:11 +0700 Subject: add statusbar and fix bug --- indoteknik_custom/models/approval_payment_term.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'indoteknik_custom/models/approval_payment_term.py') diff --git a/indoteknik_custom/models/approval_payment_term.py b/indoteknik_custom/models/approval_payment_term.py index 81eb1908..da71b7e4 100644 --- a/indoteknik_custom/models/approval_payment_term.py +++ b/indoteknik_custom/models/approval_payment_term.py @@ -31,6 +31,8 @@ class ApprovalPaymentTerm(models.Model): approve_leader = fields.Boolean('Approve Pimpinan', tracking=True, copy=False) reason = fields.Text('Reason', tracking=True) approve_date = fields.Datetime('Approve Date') + state = fields.Selection([('waiting_approval', 'Waiting Approval'), ('approved', 'Approved'), ('rejected', 'Rejected')], default='waiting_approval', tracking=True) + reason_reject = fields.Selection([('reason1', 'Reason 1'), ('reason2', 'Reason 2'), ('reason3', 'Reason 3')], string='Reason Reject', tracking=True) @api.constrains('partner_id') @@ -46,20 +48,20 @@ class ApprovalPaymentTerm(models.Model): user = self.env.user is_it = user.has_group('indoteknik_custom.group_role_it') - if is_it or user.id == 19: + if user.id == 19 or is_it: self.approve_sales_manager = True return - if is_it or user.id == 688 and self.approve_sales_manager: + if user.id == 688 or is_it: self.approve_finance = True return - if is_it or user.id == 7 and self.approve_sales_manager and self.approve_finance: + if (user.id == 7 and self.approve_finance) or is_it: self.approve_leader = True - if not is_it or not self.approve_finance: + if not self.approve_finance or not is_it: raise UserError('Harus Approval Finance!!') - if not is_it or not self.approve_leader: + if not self.approve_leader or not is_it: raise UserError('Harus Approval Pimpinan!!') if user.id == 7: @@ -74,6 +76,12 @@ class ApprovalPaymentTerm(models.Model): 'property_payment_term_id': self.property_payment_term_id.id }) self.approve_date = datetime.utcnow() + self.state = 'approved' + + def button_reject(self): + if self.env.user.id not in [688, 7]: + raise UserError("Hanya Finance atau Pimpinan Yang Bisa Reject") + self.state = 'rejected' @api.model def create(self, vals): -- cgit v1.2.3 From fbc29fcf20ef2571be30a7c06ad60f193282fa4b Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Tue, 8 Jul 2025 12:58:12 +0700 Subject: fix bug --- indoteknik_custom/models/approval_payment_term.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'indoteknik_custom/models/approval_payment_term.py') diff --git a/indoteknik_custom/models/approval_payment_term.py b/indoteknik_custom/models/approval_payment_term.py index da71b7e4..4cd9ea36 100644 --- a/indoteknik_custom/models/approval_payment_term.py +++ b/indoteknik_custom/models/approval_payment_term.py @@ -48,20 +48,20 @@ class ApprovalPaymentTerm(models.Model): user = self.env.user is_it = user.has_group('indoteknik_custom.group_role_it') - if user.id == 19 or is_it: + if (not user.id ==7 and user.id == 19) or is_it: self.approve_sales_manager = True return - if user.id == 688 or is_it: + if (not user.id ==7 and user.id == 688) or is_it: self.approve_finance = True return if (user.id == 7 and self.approve_finance) or is_it: self.approve_leader = True - if not self.approve_finance or not is_it: + if not self.approve_finance and not is_it: raise UserError('Harus Approval Finance!!') - if not self.approve_leader or not is_it: + if not self.approve_leader and not is_it: raise UserError('Harus Approval Pimpinan!!') if user.id == 7: -- cgit v1.2.3 From 3df2346732b38eb47accfb07d3dfb0feaab65854 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Wed, 9 Jul 2025 08:58:47 +0700 Subject: cr approval payment terms --- indoteknik_custom/models/approval_payment_term.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'indoteknik_custom/models/approval_payment_term.py') diff --git a/indoteknik_custom/models/approval_payment_term.py b/indoteknik_custom/models/approval_payment_term.py index 4cd9ea36..291e8e37 100644 --- a/indoteknik_custom/models/approval_payment_term.py +++ b/indoteknik_custom/models/approval_payment_term.py @@ -33,6 +33,13 @@ class ApprovalPaymentTerm(models.Model): approve_date = fields.Datetime('Approve Date') state = fields.Selection([('waiting_approval', 'Waiting Approval'), ('approved', 'Approved'), ('rejected', 'Rejected')], default='waiting_approval', tracking=True) reason_reject = fields.Selection([('reason1', 'Reason 1'), ('reason2', 'Reason 2'), ('reason3', 'Reason 3')], string='Reason Reject', tracking=True) + sale_order_id = fields.Many2one('sale.order', string='Sale Order', copy=False, tracking=True) + total = fields.Float(string='Total', compute='_compute_total') + + @api.depends('sale_order_id') + def _compute_total(self): + for rec in self: + rec.total = rec.sale_order_id.amount_total @api.constrains('partner_id') @@ -48,11 +55,11 @@ class ApprovalPaymentTerm(models.Model): user = self.env.user is_it = user.has_group('indoteknik_custom.group_role_it') - if (not user.id ==7 and user.id == 19) or is_it: + if (not user.id ==7 and user.id == 19 and not self.approve_sales_manager) or is_it: self.approve_sales_manager = True return - if (not user.id ==7 and user.id == 688) or is_it: + if (not user.id ==7 and user.id == 688 and not self.approve_finance) or is_it: self.approve_finance = True return -- cgit v1.2.3 From 7cf4a10aa25c1f358b57d01ebf4efdbbcdd7b6a9 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Wed, 9 Jul 2025 10:57:41 +0700 Subject: change request approval payment terms --- indoteknik_custom/models/approval_payment_term.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'indoteknik_custom/models/approval_payment_term.py') diff --git a/indoteknik_custom/models/approval_payment_term.py b/indoteknik_custom/models/approval_payment_term.py index 291e8e37..00d990de 100644 --- a/indoteknik_custom/models/approval_payment_term.py +++ b/indoteknik_custom/models/approval_payment_term.py @@ -33,13 +33,26 @@ class ApprovalPaymentTerm(models.Model): approve_date = fields.Datetime('Approve Date') state = fields.Selection([('waiting_approval', 'Waiting Approval'), ('approved', 'Approved'), ('rejected', 'Rejected')], default='waiting_approval', tracking=True) reason_reject = fields.Selection([('reason1', 'Reason 1'), ('reason2', 'Reason 2'), ('reason3', 'Reason 3')], string='Reason Reject', tracking=True) - sale_order_id = fields.Many2one('sale.order', string='Sale Order', copy=False, tracking=True) - total = fields.Float(string='Total', compute='_compute_total') + sale_order_ids = fields.Many2many( + 'sale.order', + string='Sale Orders', + copy=False, + tracking=True + ) + + total = fields.Char( + string='Sale Order Totals', + compute='_compute_total' + ) - @api.depends('sale_order_id') def _compute_total(self): for rec in self: - rec.total = rec.sale_order_id.amount_total + totals_list = [] + for order in rec.sale_order_ids: + formatted_total = "{:,.2f}".format(order.amount_total) + totals_list.append(f"{order.name}: {formatted_total}") + + rec.total = "\n".join(totals_list) if totals_list else "No Sale Orders" @api.constrains('partner_id') -- cgit v1.2.3 From 0604dbc3a2789c139ea66dd561726f796ad92cd6 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Wed, 9 Jul 2025 11:15:10 +0700 Subject: add grand total on approval payment term --- indoteknik_custom/models/approval_payment_term.py | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'indoteknik_custom/models/approval_payment_term.py') diff --git a/indoteknik_custom/models/approval_payment_term.py b/indoteknik_custom/models/approval_payment_term.py index 00d990de..6e1c8103 100644 --- a/indoteknik_custom/models/approval_payment_term.py +++ b/indoteknik_custom/models/approval_payment_term.py @@ -44,6 +44,13 @@ class ApprovalPaymentTerm(models.Model): string='Sale Order Totals', compute='_compute_total' ) + + grand_total = fields.Float(string='Grand Total', compute="_compute_grand_total") + + def _compute_grand_total(self): + for rec in self: + grand_total = sum(order.amount_total for order in rec.sale_order_ids) + rec.grand_total = grand_total def _compute_total(self): for rec in self: -- cgit v1.2.3 From b298a37963027a08e0046629bbcb795effa58e3a Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Fri, 11 Jul 2025 15:40:38 +0700 Subject: view and add new status on approval payment term --- indoteknik_custom/models/approval_payment_term.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'indoteknik_custom/models/approval_payment_term.py') diff --git a/indoteknik_custom/models/approval_payment_term.py b/indoteknik_custom/models/approval_payment_term.py index 6e1c8103..cd54b53a 100644 --- a/indoteknik_custom/models/approval_payment_term.py +++ b/indoteknik_custom/models/approval_payment_term.py @@ -31,7 +31,13 @@ class ApprovalPaymentTerm(models.Model): approve_leader = fields.Boolean('Approve Pimpinan', tracking=True, copy=False) reason = fields.Text('Reason', tracking=True) approve_date = fields.Datetime('Approve Date') - state = fields.Selection([('waiting_approval', 'Waiting Approval'), ('approved', 'Approved'), ('rejected', 'Rejected')], default='waiting_approval', tracking=True) + state = fields.Selection([ + ('waiting_approval_sales_manager', 'Waiting Approval Sales Manager'), + ('waiting_approval_finance', 'Waiting Approval Finance'), + ('waiting_approval_leader', 'Waiting Approval Leader'), + ('approved', 'Approved'), + ('rejected', 'Rejected')], + default='waiting_approval_sales_manager', tracking=True) reason_reject = fields.Selection([('reason1', 'Reason 1'), ('reason2', 'Reason 2'), ('reason3', 'Reason 3')], string='Reason Reject', tracking=True) sale_order_ids = fields.Many2many( 'sale.order', @@ -77,10 +83,12 @@ class ApprovalPaymentTerm(models.Model): if (not user.id ==7 and user.id == 19 and not self.approve_sales_manager) or is_it: self.approve_sales_manager = True + self.state = 'waiting_approval_finance' return if (not user.id ==7 and user.id == 688 and not self.approve_finance) or is_it: self.approve_finance = True + self.state = 'waiting_approval_leader' return if (user.id == 7 and self.approve_finance) or is_it: -- cgit v1.2.3 From f6d21f2f6a8bbc597e70aa07a4f6c2fc43b4c176 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Sat, 12 Jul 2025 10:20:18 +0700 Subject: add change log widya only --- indoteknik_custom/models/approval_payment_term.py | 62 +++++++++++++++++++++++ 1 file changed, 62 insertions(+) (limited to 'indoteknik_custom/models/approval_payment_term.py') diff --git a/indoteknik_custom/models/approval_payment_term.py b/indoteknik_custom/models/approval_payment_term.py index cd54b53a..025f9ed4 100644 --- a/indoteknik_custom/models/approval_payment_term.py +++ b/indoteknik_custom/models/approval_payment_term.py @@ -53,6 +53,68 @@ class ApprovalPaymentTerm(models.Model): grand_total = fields.Float(string='Grand Total', compute="_compute_grand_total") + change_log_688 = fields.Text(string="Change Log", readonly=True, copy=False) + + def write(self, vals): + # Ambil nilai lama sebelum perubahan + old_values_dict = { + rec.id: rec.read(vals.keys())[0] + for rec in self + } + + res = super().write(vals) + + self._track_changes_for_user_688(vals, old_values_dict) + return res + + def _track_changes_for_user_688(self, vals, old_values_dict): + if self.env.user.id != 688: + return + + for rec in self: + changes = [] + old_values = old_values_dict.get(rec.id, {}) + + for field_name, new_value in vals.items(): + if field_name not in rec._fields or field_name == 'change_log_688': + continue + + field = rec._fields[field_name] + old_value = old_values.get(field_name) + + field_label = field.string # Ambil label user-friendly + + # Relational field + if field.type == 'many2one': + old_id = old_value[0] if old_value else False + is_different = old_id != new_value + if is_different: + old_display = old_value[1] if old_value else 'False' + new_display = rec.env[field.comodel_name].browse(new_value).display_name if new_value else 'False' + changes.append(f"[{field_label}] dari '{old_display}' ke '{new_display}'") + + else: + # Float khusus + if field.type == 'float': + is_different = not self._float_equal(old_value, new_value) + else: + is_different = old_value != new_value + + if is_different: + changes.append(f"[{field_label}] dari '{old_value}' ke '{new_value}'") + + if changes: + timestamp = fields.Datetime.now().strftime('%Y-%m-%d %H:%M:%S') + rec.change_log_688 = f"{timestamp} - Perubahan oleh Widya:\n" + "\n".join(changes) + + + @staticmethod + def _float_equal(val1, val2, eps=1e-6): + try: + return abs(float(val1 or 0.0) - float(val2 or 0.0)) < eps + except Exception: + return False + def _compute_grand_total(self): for rec in self: grand_total = sum(order.amount_total for order in rec.sale_order_ids) -- cgit v1.2.3 From 4dd6ef58e2c60df7cb25b65ae6ad23d3bee2ebc1 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Tue, 15 Jul 2025 11:13:04 +0700 Subject: add so number on purchasing job --- indoteknik_custom/models/approval_payment_term.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indoteknik_custom/models/approval_payment_term.py') diff --git a/indoteknik_custom/models/approval_payment_term.py b/indoteknik_custom/models/approval_payment_term.py index 025f9ed4..6c857b45 100644 --- a/indoteknik_custom/models/approval_payment_term.py +++ b/indoteknik_custom/models/approval_payment_term.py @@ -143,17 +143,17 @@ class ApprovalPaymentTerm(models.Model): user = self.env.user is_it = user.has_group('indoteknik_custom.group_role_it') - if (not user.id ==7 and user.id == 19 and not self.approve_sales_manager) or is_it: + if (not user.id ==7 and user.id == 19 and not self.approve_sales_manager) or (is_it and not self.approve_sales_manager): self.approve_sales_manager = True self.state = 'waiting_approval_finance' return - if (not user.id ==7 and user.id == 688 and not self.approve_finance) or is_it: + if (not user.id ==7 and user.id == 688 and not self.approve_finance) or (is_it and not self.approve_finance): self.approve_finance = True self.state = 'waiting_approval_leader' return - if (user.id == 7 and self.approve_finance) or is_it: + if (user.id == 7 and self.approve_finance) or (is_it and not self.approve_leader): self.approve_leader = True if not self.approve_finance and not is_it: -- cgit v1.2.3