From 6805a54ddeb69e64b1ba5f2d0dd23158aeea29df Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Mon, 21 Jul 2025 14:23:06 +0700 Subject: fix bug --- indoteknik_custom/models/purchase_order.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indoteknik_custom/models/purchase_order.py b/indoteknik_custom/models/purchase_order.py index 4dc26d74..8e283c45 100755 --- a/indoteknik_custom/models/purchase_order.py +++ b/indoteknik_custom/models/purchase_order.py @@ -963,7 +963,7 @@ class PurchaseOrder(models.Model): # ) if not self.from_apo: - if not self.matches_so and not self.env.user.is_purchasing_manager and not self.env.user.is_leader: + if not self.matches_so and not self.env.user.is_purchasing_manager and not self.env.user.is_leader and not self.manufacturing_id: raise UserError("Tidak ada link dengan SO, harus di confirm oleh Purchasing Manager") send_email = False -- cgit v1.2.3 From 946e4b76e8280daad6d4849e9ced33a54d770a84 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Mon, 21 Jul 2025 14:50:24 +0700 Subject: push --- indoteknik_custom/models/purchase_order.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indoteknik_custom/models/purchase_order.py b/indoteknik_custom/models/purchase_order.py index 25f45f6f..5b9e1acb 100755 --- a/indoteknik_custom/models/purchase_order.py +++ b/indoteknik_custom/models/purchase_order.py @@ -970,7 +970,7 @@ class PurchaseOrder(models.Model): # ) if not self.from_apo: - if not self.matches_so and not self.env.user.is_purchasing_manager and not self.env.user.is_leader and not self.manufacturing_id: + if (not self.matches_so or not self.sale_order_id) and not self.env.user.is_purchasing_manager and not self.env.user.is_leader and not self.manufacturing_id: raise UserError("Tidak ada link dengan SO, harus di confirm oleh Purchasing Manager") send_email = False -- cgit v1.2.3 From 87f38f9fcb68f04a2cc8157744622c2d0ebf1eab Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Tue, 22 Jul 2025 10:54:44 +0700 Subject: notif open purchasing job --- indoteknik_custom/models/purchasing_job.py | 55 +++++++++++++++++++++++++- indoteknik_custom/security/ir.model.access.csv | 1 + indoteknik_custom/views/purchasing_job.xml | 10 ++++- 3 files changed, 64 insertions(+), 2 deletions(-) diff --git a/indoteknik_custom/models/purchasing_job.py b/indoteknik_custom/models/purchasing_job.py index 58f1c067..db733b5a 100644 --- a/indoteknik_custom/models/purchasing_job.py +++ b/indoteknik_custom/models/purchasing_job.py @@ -26,7 +26,46 @@ class PurchasingJob(models.Model): purchase_representative_id = fields.Many2one('res.users', string="Purchase Representative", readonly=True) note = fields.Char(string="Note Detail") date_po = fields.Datetime(string='Date PO', copy=False) - so_number = fields.Char(string='SO Number', copy=False) + so_number = fields.Text(string='SO Number', copy=False) + check_pj = fields.Boolean(compute='_get_check_pj', string='Linked') + + def action_open_job_detail(self): + self.ensure_one() + Seen = self.env['purchasing.job.seen'] + seen = Seen.search([ + ('user_id', '=', self.env.uid), + ('product_id', '=', self.product_id.id) + ], limit=1) + + if seen: + seen.so_snapshot = self.so_number + seen.seen_date = fields.Datetime.now() + else: + Seen.create({ + 'user_id': self.env.uid, + 'product_id': self.product_id.id, + 'so_snapshot': self.so_number, + }) + + return { + 'name': 'Purchasing Job Detail', + 'type': 'ir.actions.act_window', + 'res_model': 'v.purchasing.job', + 'res_id': self.id, + 'view_mode': 'form', + 'target': 'current', + } + + + @api.depends('so_number') + def _get_check_pj(self): + for rec in self: + seen = self.env['purchasing.job.seen'].search([ + ('user_id', '=', self.env.uid), + ('product_id', '=', rec.product_id.id) + ], limit=1) + rec.check_pj = bool(seen and seen.so_snapshot == rec.so_number) + def unlink(self): # Example: Delete related records from the underlying model @@ -199,3 +238,17 @@ class OutstandingSales(models.Model): and sp.name like '%OUT%' ) """) + +class PurchasingJobSeen(models.Model): + _name = 'purchasing.job.seen' + _description = 'User Seen SO Snapshot' + _rec_name = 'product_id' + + user_id = fields.Many2one('res.users', required=True, ondelete='cascade') + product_id = fields.Many2one('product.product', required=True, ondelete='cascade') + so_snapshot = fields.Text("Last Seen SO") + seen_date = fields.Datetime(default=fields.Datetime.now) + + _sql_constraints = [ + ('user_product_unique', 'unique(user_id, product_id)', 'User already tracked this product.') + ] diff --git a/indoteknik_custom/security/ir.model.access.csv b/indoteknik_custom/security/ir.model.access.csv index 2b970cfd..dd00c5ad 100755 --- a/indoteknik_custom/security/ir.model.access.csv +++ b/indoteknik_custom/security/ir.model.access.csv @@ -183,3 +183,4 @@ access_production_purchase_match,access.production.purchase.match,model_producti access_image_carousel,access.image.carousel,model_image_carousel,,1,1,1,1 access_v_sale_notin_matchpo,access.v.sale.notin.matchpo,model_v_sale_notin_matchpo,,1,1,1,1 access_approval_payment_term,access.approval.payment.term,model_approval_payment_term,,1,1,1,1 +access_purchasing_job_seen,purchasing.job.seen,model_purchasing_job_seen,,1,1,1,1 diff --git a/indoteknik_custom/views/purchasing_job.xml b/indoteknik_custom/views/purchasing_job.xml index 976f1485..e3866d84 100644 --- a/indoteknik_custom/views/purchasing_job.xml +++ b/indoteknik_custom/views/purchasing_job.xml @@ -4,7 +4,7 @@ v.purchasing.job.tree v.purchasing.job - + @@ -19,6 +19,14 @@ + + + + + + +

+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ +
+ + + + Refund Sales Order + refund.sale.order + tree,form + + + + + diff --git a/indoteknik_custom/views/sale_order.xml b/indoteknik_custom/views/sale_order.xml index 2a159307..bb8bdc08 100755 --- a/indoteknik_custom/views/sale_order.xml +++ b/indoteknik_custom/views/sale_order.xml @@ -35,7 +35,32 @@ string="UangMuka" type="action" attrs="{'invisible': [('approval_status', '!=', 'approved')]}"/> - + + + + + + + + + + Refund + + + code + action = records.open_form_multi_create_refund() + + + Sale Order: Notification to Salesperson -- cgit v1.2.3 From 4d0ba0dc130697e6dec1422efa7339b5e6445b53 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Wed, 23 Jul 2025 15:11:52 +0700 Subject: fix --- indoteknik_custom/models/account_move.py | 192 +++++++++++++++---------------- 1 file changed, 96 insertions(+), 96 deletions(-) diff --git a/indoteknik_custom/models/account_move.py b/indoteknik_custom/models/account_move.py index db52f398..1a6fad1c 100644 --- a/indoteknik_custom/models/account_move.py +++ b/indoteknik_custom/models/account_move.py @@ -109,102 +109,102 @@ class AccountMove(models.Model): # result.append((move.id, move.display_name)) # return result - def send_due_invoice_reminder(self): - today = fields.Date.today() - target_dates = [ - today - timedelta(days=7), - today - timedelta(days=3), - today, - today + timedelta(days=3), - today + timedelta(days=7), - ] - - partner = self.env['res.partner'].search([('name', 'ilike', 'BANGUNAN TEKNIK GRUP')], limit=1) - if not partner: - _logger.info("Partner tidak ditemukan.") - return - - invoices = self.env['account.move'].search([ - ('move_type', '=', 'out_invoice'), - ('state', '=', 'posted'), - ('payment_state', 'not in', ['paid','in_payment', 'reversed']), - ('invoice_date_due', 'in', target_dates), - ('partner_id', '=', partner.id), - ]) - - _logger.info(f"Invoices tahap 1: {invoices}") - - invoices = invoices.filtered( - lambda inv: inv.invoice_payment_term_id and 'tempo' in (inv.invoice_payment_term_id.name or '').lower() - ) - _logger.info(f"Invoices tahap 2: {invoices}") - - if not invoices: - _logger.info(f"Tidak ada invoice yang due untuk partner: {partner.name}") - return - - grouped = {} - for inv in invoices: - grouped.setdefault(inv.partner_id, []).append(inv) - - template = self.env.ref('indoteknik_custom.mail_template_invoice_due_reminder') - - for partner, invs in grouped.items(): - if not partner.email: - _logger.info(f"Partner {partner.name} tidak memiliki email") - continue - - invoice_table_rows = "" - for inv in invs: - days_to_due = (inv.invoice_date_due - today).days if inv.invoice_date_due else 0 - invoice_table_rows += f""" - - {inv.name} - {fields.Date.to_string(inv.invoice_date) or '-'} - {fields.Date.to_string(inv.invoice_date_due) or '-'} - {days_to_due} - {formatLang(self.env, inv.amount_total, currency_obj=inv.currency_id)} - {inv.ref or '-'} - - """ - - subject = f"Reminder Invoice Due - {partner.name}" - body_html = re.sub( - r"]*>.*?", - f"{invoice_table_rows}", - template.body_html, - flags=re.DOTALL - ).replace('${object.name}', partner.name) \ - .replace('${object.partner_id.name}', partner.name) - # .replace('${object.email}', partner.email or '') - - values = { - 'subject': subject, - 'email_to': 'andrifebriyadiputra@gmail.com', # Ubah ke partner.email untuk produksi - 'email_from': 'finance@indoteknik.co.id', - 'body_html': body_html, - 'reply_to': f'invoice+account.move_{invs[0].id}@indoteknik.co.id', - } - - _logger.info(f"VALUES: {values}") - - template.send_mail(invs[0].id, force_send=True, email_values=values) - - # Default System User - user_system = self.env['res.users'].browse(25) - system_id = user_system.partner_id.id if user_system else False - _logger.info(f"System User: {user_system.name} ({user_system.id})") - _logger.info(f"System User ID: {system_id}") - - for inv in invs: - inv.message_post( - subject=subject, - body=body_html, - subtype_id=self.env.ref('mail.mt_note').id, - author_id=system_id, - ) - - _logger.info(f"Reminder terkirim ke {partner.name} ({values['email_to']}) → {len(invs)} invoice") + # def send_due_invoice_reminder(self): + # today = fields.Date.today() + # target_dates = [ + # today - timedelta(days=7), + # today - timedelta(days=3), + # today, + # today + timedelta(days=3), + # today + timedelta(days=7), + # ] + + # partner = self.env['res.partner'].search([('name', 'ilike', 'BANGUNAN TEKNIK GRUP')], limit=1) + # if not partner: + # _logger.info("Partner tidak ditemukan.") + # return + + # invoices = self.env['account.move'].search([ + # ('move_type', '=', 'out_invoice'), + # ('state', '=', 'posted'), + # ('payment_state', 'not in', ['paid','in_payment', 'reversed']), + # ('invoice_date_due', 'in', target_dates), + # ('partner_id', '=', partner.id), + # ]) + + # _logger.info(f"Invoices tahap 1: {invoices}") + + # invoices = invoices.filtered( + # lambda inv: inv.invoice_payment_term_id and 'tempo' in (inv.invoice_payment_term_id.name or '').lower() + # ) + # _logger.info(f"Invoices tahap 2: {invoices}") + + # if not invoices: + # _logger.info(f"Tidak ada invoice yang due untuk partner: {partner.name}") + # return + + # grouped = {} + # for inv in invoices: + # grouped.setdefault(inv.partner_id, []).append(inv) + + # template = self.env.ref('indoteknik_custom.mail_template_invoice_due_reminder') + + # for partner, invs in grouped.items(): + # if not partner.email: + # _logger.info(f"Partner {partner.name} tidak memiliki email") + # continue + + # invoice_table_rows = "" + # for inv in invs: + # days_to_due = (inv.invoice_date_due - today).days if inv.invoice_date_due else 0 + # invoice_table_rows += f""" + # + # {inv.name} + # {fields.Date.to_string(inv.invoice_date) or '-'} + # {fields.Date.to_string(inv.invoice_date_due) or '-'} + # {days_to_due} + # {formatLang(self.env, inv.amount_total, currency_obj=inv.currency_id)} + # {inv.ref or '-'} + # + # """ + + # subject = f"Reminder Invoice Due - {partner.name}" + # body_html = re.sub( + # r"]*>.*?", + # f"{invoice_table_rows}", + # template.body_html, + # flags=re.DOTALL + # ).replace('${object.name}', partner.name) \ + # .replace('${object.partner_id.name}', partner.name) + # # .replace('${object.email}', partner.email or '') + + # values = { + # 'subject': subject, + # 'email_to': 'andrifebriyadiputra@gmail.com', # Ubah ke partner.email untuk produksi + # 'email_from': 'finance@indoteknik.co.id', + # 'body_html': body_html, + # 'reply_to': f'invoice+account.move_{invs[0].id}@indoteknik.co.id', + # } + + # _logger.info(f"VALUES: {values}") + + # template.send_mail(invs[0].id, force_send=True, email_values=values) + + # # Default System User + # user_system = self.env['res.users'].browse(25) + # system_id = user_system.partner_id.id if user_system else False + # _logger.info(f"System User: {user_system.name} ({user_system.id})") + # _logger.info(f"System User ID: {system_id}") + + # for inv in invs: + # inv.message_post( + # subject=subject, + # body=body_html, + # subtype_id=self.env.ref('mail.mt_note').id, + # author_id=system_id, + # ) + + # _logger.info(f"Reminder terkirim ke {partner.name} ({values['email_to']}) → {len(invs)} invoice") @api.onchange('invoice_date') -- cgit v1.2.3 From 6a804c8d3604d7654fce48ce9e1aa1cb7c95ae87 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Wed, 23 Jul 2025 16:39:30 +0700 Subject: Label Refund Type --- indoteknik_custom/models/refund_sale_order.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/indoteknik_custom/models/refund_sale_order.py b/indoteknik_custom/models/refund_sale_order.py index 5c9c4d83..559ca07a 100644 --- a/indoteknik_custom/models/refund_sale_order.py +++ b/indoteknik_custom/models/refund_sale_order.py @@ -58,6 +58,8 @@ class RefundSaleOrder(models.Model): ('lainnya', 'Lainnya') ], string='Refund Type', required=True) + refund_type_display = fields.Char(string="Refund Type Label", compute="_compute_refund_type_display") + line_ids = fields.One2many('refund.sale.order.line', 'refund_id', string='Refund Lines') invoice_line_ids = fields.One2many( comodel_name='account.move.line', @@ -104,6 +106,11 @@ class RefundSaleOrder(models.Model): is_locked = fields.Boolean(string="Locked", compute="_compute_is_locked") + @api.depends('refund_type') + def _compute_refund_type_display(self): + for rec in self: + rec.refund_type_display = dict(self.fields_get(allfields=['refund_type'])['refund_type']['selection']).get(rec.refund_type, '') + @api.model def create(self, vals): -- cgit v1.2.3 From e661868aa6a593114de434dcd0d1b01d8ca3b426 Mon Sep 17 00:00:00 2001 From: "Indoteknik ." Date: Wed, 23 Jul 2025 16:52:53 +0700 Subject: (andri) fix total margin SO keitung 2x --- indoteknik_custom/models/sale_order_line.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/indoteknik_custom/models/sale_order_line.py b/indoteknik_custom/models/sale_order_line.py index 2a0160e8..5e9fc362 100644 --- a/indoteknik_custom/models/sale_order_line.py +++ b/indoteknik_custom/models/sale_order_line.py @@ -173,8 +173,8 @@ class SaleOrderLine(models.Model): # minus with delivery if covered by indoteknik if line.order_id.shipping_cost_covered == 'indoteknik': sales_price -= line.delivery_amt_line - if line.order_id.fee_third_party > 0: - sales_price -= line.fee_third_party_line + # if line.order_id.fee_third_party > 0: + # sales_price -= line.fee_third_party_line purchase_price = line.purchase_price if line.purchase_tax_id.price_include: -- cgit v1.2.3