diff options
| author | it-fixcomart <it@fixcomart.co.id> | 2025-07-28 15:09:55 +0700 |
|---|---|---|
| committer | it-fixcomart <it@fixcomart.co.id> | 2025-07-28 15:09:55 +0700 |
| commit | d15ce4e186e2b77f01e8dfd03886298cc733d4c1 (patch) | |
| tree | 1b32a4c29c4fcea85070fcecb5b77a7d55d30029 /indoteknik_custom/models/approval_payment_term.py | |
| parent | deba962d7368a5c4e30441b5a640102608e3dde6 (diff) | |
| parent | 36a53535dbdc5777266fd9276b4c557259dab6be (diff) | |
<hafid> merging odoo-backup
Diffstat (limited to 'indoteknik_custom/models/approval_payment_term.py')
| -rw-r--r-- | indoteknik_custom/models/approval_payment_term.py | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/indoteknik_custom/models/approval_payment_term.py b/indoteknik_custom/models/approval_payment_term.py new file mode 100644 index 00000000..6c857b45 --- /dev/null +++ b/indoteknik_custom/models/approval_payment_term.py @@ -0,0 +1,187 @@ +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') + 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', + string='Sale Orders', + copy=False, + tracking=True + ) + + total = fields.Char( + string='Sale Order Totals', + compute='_compute_total' + ) + + 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) + rec.grand_total = grand_total + + def _compute_total(self): + for rec in self: + 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') + 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 (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 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 and not self.approve_leader): + self.approve_leader = True + + if not self.approve_finance and not is_it: + raise UserError('Harus Approval Finance!!') + if not self.approve_leader and not is_it: + 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() + 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): + vals['number'] = self.env['ir.sequence'].next_by_code('approval.payment.term') or '0' + result = super(ApprovalPaymentTerm, self).create(vals) + return result |
