From d956020b6b588e5216f1238b82f87b6fb35b2afc Mon Sep 17 00:00:00 2001 From: Miqdad Date: Wed, 3 Sep 2025 18:05:00 +0700 Subject: send bu out to tele --- indoteknik_custom/models/report_logbook_sj.py | 83 ++++++++++++++++++++++++ indoteknik_custom/views/report_logbook_sj.xml | 91 +++++++++++++++------------ 2 files changed, 133 insertions(+), 41 deletions(-) diff --git a/indoteknik_custom/models/report_logbook_sj.py b/indoteknik_custom/models/report_logbook_sj.py index 17119c12..85ab755d 100644 --- a/indoteknik_custom/models/report_logbook_sj.py +++ b/indoteknik_custom/models/report_logbook_sj.py @@ -2,6 +2,11 @@ from odoo import models, fields, api from odoo.exceptions import UserError from pytz import timezone from datetime import datetime +import requests +import json +import logging + +_logger = logging.getLogger(__name__) class ReportLogbookSJ(models.Model): _name = 'report.logbook.sj' @@ -60,6 +65,84 @@ class ReportLogbookSJ(models.Model): self.state = 'terima_semua' else: raise UserError('Hanya Accounting yang bisa Approve') + + + @api.model + def cron_daily_logbook_gap_to_telegram(self): + bot_mqdd = '8203414501:AAHy_XwiUAVrgRM2EJzW7sZx9npRLITZpb8' + chat_id_mqdd = '-4885333032' + apiURL = f'https://api.telegram.org/bot{bot_mqdd}/sendMessage' + + # ambil dari 1 Februari 2024 (UTC) + dt_from = datetime(2024, 2, 1, 0, 0, 0) + + self.env.cr.execute(""" + SELECT sp.id, sp.name + FROM stock_picking sp + LEFT JOIN report_logbook_sj_line rlsl + ON rlsl.picking_id = sp.id + OR (rlsl.name IS NOT NULL AND rlsl.name = sp.name) + WHERE sp.picking_type_id = 29 + AND sp.state = 'done' + AND sp.create_date >= %s + AND rlsl.id IS NULL + ORDER BY sp.create_date ASC limit 20 + """, (dt_from,)) + rows = self.env.cr.fetchall() + + if not rows: + return True + + header = "berikut merupakan nomor picking yang belum ada di Logbook SJ report:\n" + body = "\n".join(f"{name} ({pid})" for pid, name in rows if name) + text = header + body + + # kirim satu pesan (tanpa pemotongan) + try: + resp = requests.post(apiURL, json={'chat_id': chat_id_mqdd, 'text': text}, timeout=15) + resp.raise_for_status() + except requests.HTTPError: + _logger.error("Telegram response: %s", resp.text) # <— LIHAT DESKRIPSINYA DI LOG + raise + except Exception as e: + # log saja; biar cron tidak crash + logging.getLogger(__name__).exception("Gagal kirim Telegram: %s", e) + return True + + def action_send_to_telegram(self): + entries = [] + pickings = self.report_logbook_sj_line.mapped('picking_id') + for p in pickings: + if p: + entries.append((p.name, p.id)) + + fallback_names = [l.name for l in self.report_logbook_sj_line if not l.picking_id and l.name] + if fallback_names: + picks = self.env['stock.picking'].search([('name', 'in', list(set(fallback_names)))]) + name2id = {p.name: p.id for p in picks} + for n in fallback_names: + entries.append((n, name2id.get(n))) + + seen, unique_entries = set(), [] + for name, pid in entries: + key = pid or name + if key and key not in seen: + seen.add(key) + unique_entries.append((name, pid)) + + header = "berikut merupakan nomor picking yang belum ada di Logbook SJ report:\n" + body = "\n".join(f"{name} ({pid or '-'})" for name, pid in unique_entries) if unique_entries else "- (tidak ada)" + text = header + body + + bot_mqdd = '8203414501:AAHy_XwiUAVrgRM2EJzW7sZx9npRLITZpb8' + chat_id_mqdd = '-4885333032' + apiURL = f'https://api.telegram.org/bot{bot_mqdd}/sendMessage' + try: + hehe = requests.post(apiURL, json={'chat_id': chat_id_mqdd, 'text': text}) + _logger.info(hehe) + except Exception as e: + print(e) + class ReportLogbookSJLine(models.Model): _name = 'report.logbook.sj.line' diff --git a/indoteknik_custom/views/report_logbook_sj.xml b/indoteknik_custom/views/report_logbook_sj.xml index 94f6c2ab..6458af40 100644 --- a/indoteknik_custom/views/report_logbook_sj.xml +++ b/indoteknik_custom/views/report_logbook_sj.xml @@ -12,9 +12,10 @@ + - + report.logbook.sj.line.tree @@ -42,50 +43,48 @@
-
-
+
+ - - - - - - - - - - - - + + + - - - - - - -
- - -
+ + + + + + + +
+ + + + + + +
+ + +
- report.logbook.sj.search.view - report.logbook.sj - - - - - - + report.logbook.sj.search.view + report.logbook.sj + + + + + + Report Logbook SJ @@ -94,9 +93,19 @@ tree,form - + + + + + Daily Logbook SJ Gap → Telegram + + code + model.cron_daily_logbook_gap_to_telegram() + 1 + days + -1 + + False + + \ No newline at end of file -- cgit v1.2.3 From 4da5af474edea6a61453dcc8485cefaa7fe6dd42 Mon Sep 17 00:00:00 2001 From: Miqdad Date: Thu, 4 Sep 2025 15:26:48 +0700 Subject: Done x --- indoteknik_custom/__manifest__.py | 1 + indoteknik_custom/models/__init__.py | 3 +- indoteknik_custom/models/report_logbook_sj.py | 51 ++++------------------ indoteknik_custom/models/sj_tele.py | 59 ++++++++++++++++++++++++++ indoteknik_custom/security/ir.model.access.csv | 3 +- indoteknik_custom/views/sj_tele.xml | 15 +++++++ 6 files changed, 87 insertions(+), 45 deletions(-) create mode 100644 indoteknik_custom/models/sj_tele.py create mode 100644 indoteknik_custom/views/sj_tele.xml diff --git a/indoteknik_custom/__manifest__.py b/indoteknik_custom/__manifest__.py index 31685005..d852d2e1 100755 --- a/indoteknik_custom/__manifest__.py +++ b/indoteknik_custom/__manifest__.py @@ -177,6 +177,7 @@ 'views/tukar_guling_po.xml', # 'views/refund_sale_order.xml', 'views/update_date_planned_po_wizard_view.xml', + 'views/sj_tele.xml' ], 'demo': [], 'css': [], diff --git a/indoteknik_custom/models/__init__.py b/indoteknik_custom/models/__init__.py index 3a9f9312..c0aa7085 100755 --- a/indoteknik_custom/models/__init__.py +++ b/indoteknik_custom/models/__init__.py @@ -156,4 +156,5 @@ from . import refund_sale_order # from . import patch from . import tukar_guling from . import tukar_guling_po -from . import update_date_planned_po_wizard \ No newline at end of file +from . import update_date_planned_po_wizard +from . import sj_tele \ No newline at end of file diff --git a/indoteknik_custom/models/report_logbook_sj.py b/indoteknik_custom/models/report_logbook_sj.py index 85ab755d..6915ad9b 100644 --- a/indoteknik_custom/models/report_logbook_sj.py +++ b/indoteknik_custom/models/report_logbook_sj.py @@ -39,6 +39,10 @@ class ReportLogbookSJ(models.Model): count_line = fields.Char(string='Count Line', compute='_compute_count_line') + def write(self, vals): + self.action_send_to_telegram() + res = super(ReportLogbookSJ, self).write(vals) + @api.depends('report_logbook_sj_line') def _compute_count_line(self): for rec in self: @@ -67,49 +71,10 @@ class ReportLogbookSJ(models.Model): raise UserError('Hanya Accounting yang bisa Approve') - @api.model - def cron_daily_logbook_gap_to_telegram(self): - bot_mqdd = '8203414501:AAHy_XwiUAVrgRM2EJzW7sZx9npRLITZpb8' - chat_id_mqdd = '-4885333032' - apiURL = f'https://api.telegram.org/bot{bot_mqdd}/sendMessage' - - # ambil dari 1 Februari 2024 (UTC) - dt_from = datetime(2024, 2, 1, 0, 0, 0) - - self.env.cr.execute(""" - SELECT sp.id, sp.name - FROM stock_picking sp - LEFT JOIN report_logbook_sj_line rlsl - ON rlsl.picking_id = sp.id - OR (rlsl.name IS NOT NULL AND rlsl.name = sp.name) - WHERE sp.picking_type_id = 29 - AND sp.state = 'done' - AND sp.create_date >= %s - AND rlsl.id IS NULL - ORDER BY sp.create_date ASC limit 20 - """, (dt_from,)) - rows = self.env.cr.fetchall() - - if not rows: - return True - - header = "berikut merupakan nomor picking yang belum ada di Logbook SJ report:\n" - body = "\n".join(f"{name} ({pid})" for pid, name in rows if name) - text = header + body - - # kirim satu pesan (tanpa pemotongan) - try: - resp = requests.post(apiURL, json={'chat_id': chat_id_mqdd, 'text': text}, timeout=15) - resp.raise_for_status() - except requests.HTTPError: - _logger.error("Telegram response: %s", resp.text) # <— LIHAT DESKRIPSINYA DI LOG - raise - except Exception as e: - # log saja; biar cron tidak crash - logging.getLogger(__name__).exception("Gagal kirim Telegram: %s", e) - return True - def action_send_to_telegram(self): + user_logistic = self.env.ref('indoteknik_custom.group_role_logistic') + if self.user != user_logistic: + return entries = [] pickings = self.report_logbook_sj_line.mapped('picking_id') for p in pickings: @@ -130,7 +95,7 @@ class ReportLogbookSJ(models.Model): seen.add(key) unique_entries.append((name, pid)) - header = "berikut merupakan nomor picking yang belum ada di Logbook SJ report:\n" + header = f"Saya {self.env.user.name} sudah mengisi di Logbook SJ Report:\n" body = "\n".join(f"{name} ({pid or '-'})" for name, pid in unique_entries) if unique_entries else "- (tidak ada)" text = header + body diff --git a/indoteknik_custom/models/sj_tele.py b/indoteknik_custom/models/sj_tele.py new file mode 100644 index 00000000..c359d6d8 --- /dev/null +++ b/indoteknik_custom/models/sj_tele.py @@ -0,0 +1,59 @@ +from odoo import models, fields, api +import requests +import json +import logging + +_logger = logging.getLogger(__name__) + +class SjTele(models.Model): + _name = 'sj.tele' + _description = 'sj.tele' + + + picking_id = fields.Many2one('stock.picking', string='Picking') + picking_name = fields.Char(string='Picking Name') + create_date = fields.Datetime(string='Create Date') + + @api.model + def woi(self): + bot_mqdd = '8203414501:AAHy_XwiUAVrgRM2EJzW7sZx9npRLITZpb8' + chat_id_mqdd = '-4885333032' + apiURL = f'https://api.telegram.org/bot{bot_mqdd}/sendMessage' + + self.env.cr.execute(""" + SELECT + COALESCE(sp.id, st.picking_id) AS pid, + COALESCE(sp.name, st.picking_name) AS pname + FROM sj_tele st + LEFT JOIN stock_picking sp + ON sp.id = st.picking_id + LEFT JOIN report_logbook_sj_line rlsl + ON (rlsl.picking_id = COALESCE(sp.id, st.picking_id)) + OR (rlsl.name IS NOT NULL AND rlsl.name = COALESCE(sp.name, st.picking_name)) + WHERE rlsl.id IS NULL + AND COALESCE(sp.name, st.picking_name) IS NOT NULL + ORDER BY st.create_date ASC + LIMIT 20 + """) + rows = self.env.cr.fetchall() + + if not rows: + _logger.info("SJ Tele: tidak ada data untuk dikirim (staging kosong atau semua sudah di logbook).") + text = "Selamat anda menamatkan Logbook SJ Report" + try: + resp = requests.post(apiURL, json={'chat_id': chat_id_mqdd, 'text': text}, timeout=15) + except Exception as e: + logging.getLogger(__name__).exception("Gagal kirim Telegram: %s", e) + return True + + header = "Berikut merupakan nomor BU/OUT yang belum ada di Logbook SJ report:\n" + body = "\n".join(f"{name} ({pid})" for pid, name in rows if name) + text = header + body + try: + resp = requests.post(apiURL, json={'chat_id': chat_id_mqdd, 'text': text}, timeout=15) + except requests.HTTPError: + _logger.error("Telegram response: %s", resp.text) + raise + except Exception as e: + logging.getLogger(__name__).exception("Gagal kirim Telegram: %s", e) + return True \ 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 3a320510..0d2789b3 100755 --- a/indoteknik_custom/security/ir.model.access.csv +++ b/indoteknik_custom/security/ir.model.access.csv @@ -195,4 +195,5 @@ access_tukar_guling_mapping_koli_all_users,tukar.guling.mapping.koli.all.users,m access_purchase_order_update_date_wizard,access.purchase.order.update.date.wizard,model_purchase_order_update_date_wizard,base.group_user,1,1,1,1 access_sync_promise_date_wizard,access.sync.promise.date.wizard,model_sync_promise_date_wizard,base.group_user,1,1,1,1 access_sync_promise_date_wizard_line,access.sync.promise.date.wizard.line,model_sync_promise_date_wizard_line,base.group_user,1,1,1,1 -access_change_date_planned_wizard,access.change.date.planned.wizard,model_change_date_planned_wizard,,1,1,1,1 \ No newline at end of file +access_change_date_planned_wizard,access.change.date.planned.wizard,model_change_date_planned_wizard,,1,1,1,1 +access_sj_tele,access.sj.tele,model_sj_tele,base.group_system,1,1,1,1 \ No newline at end of file diff --git a/indoteknik_custom/views/sj_tele.xml b/indoteknik_custom/views/sj_tele.xml new file mode 100644 index 00000000..cefcc968 --- /dev/null +++ b/indoteknik_custom/views/sj_tele.xml @@ -0,0 +1,15 @@ + + + + SJ TELE + + code + model.woi() + 1 + days + -1 + + False + + + \ No newline at end of file -- cgit v1.2.3 From dd2bc67bbdaa771adf6bbedc01ba23a98ea03574 Mon Sep 17 00:00:00 2001 From: Miqdad Date: Thu, 4 Sep 2025 15:46:05 +0700 Subject: Gk jadi --- indoteknik_custom/models/report_logbook_sj.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/indoteknik_custom/models/report_logbook_sj.py b/indoteknik_custom/models/report_logbook_sj.py index 6915ad9b..e67ea724 100644 --- a/indoteknik_custom/models/report_logbook_sj.py +++ b/indoteknik_custom/models/report_logbook_sj.py @@ -39,10 +39,6 @@ class ReportLogbookSJ(models.Model): count_line = fields.Char(string='Count Line', compute='_compute_count_line') - def write(self, vals): - self.action_send_to_telegram() - res = super(ReportLogbookSJ, self).write(vals) - @api.depends('report_logbook_sj_line') def _compute_count_line(self): for rec in self: @@ -51,6 +47,8 @@ class ReportLogbookSJ(models.Model): @api.model def create(self, vals): vals['name'] = self.env['ir.sequence'].next_by_code('report.logbook.sj') or '0' + # if self.env.user.has_group('indoteknik_custom.group_role_logistic'): + # self.action_send_to_telegram() result = super(ReportLogbookSJ, self).create(vals) return result @@ -72,9 +70,7 @@ class ReportLogbookSJ(models.Model): def action_send_to_telegram(self): - user_logistic = self.env.ref('indoteknik_custom.group_role_logistic') - if self.user != user_logistic: - return + entries = [] pickings = self.report_logbook_sj_line.mapped('picking_id') for p in pickings: @@ -95,7 +91,7 @@ class ReportLogbookSJ(models.Model): seen.add(key) unique_entries.append((name, pid)) - header = f"Saya {self.env.user.name} sudah mengisi di Logbook SJ Report:\n" + header = f"{self.env.user.name} sudah mengisi di Logbook SJ Report:\n" body = "\n".join(f"{name} ({pid or '-'})" for name, pid in unique_entries) if unique_entries else "- (tidak ada)" text = header + body -- cgit v1.2.3 From 666232252b4f5c5626bb5f276f645d4989495fa1 Mon Sep 17 00:00:00 2001 From: Miqdad Date: Thu, 4 Sep 2025 18:38:12 +0700 Subject: Add SO --- indoteknik_custom/models/sj_tele.py | 60 +++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 33 deletions(-) diff --git a/indoteknik_custom/models/sj_tele.py b/indoteknik_custom/models/sj_tele.py index c359d6d8..50e47e78 100644 --- a/indoteknik_custom/models/sj_tele.py +++ b/indoteknik_custom/models/sj_tele.py @@ -11,49 +11,43 @@ class SjTele(models.Model): picking_id = fields.Many2one('stock.picking', string='Picking') + sale_id = fields.Many2one('sale.order', string='Sales Order') picking_name = fields.Char(string='Picking Name') create_date = fields.Datetime(string='Create Date') - @api.model - def woi(self): + def woi(self): bot_mqdd = '8203414501:AAHy_XwiUAVrgRM2EJzW7sZx9npRLITZpb8' chat_id_mqdd = '-4885333032' - apiURL = f'https://api.telegram.org/bot{bot_mqdd}/sendMessage' - - self.env.cr.execute(""" - SELECT - COALESCE(sp.id, st.picking_id) AS pid, - COALESCE(sp.name, st.picking_name) AS pname - FROM sj_tele st - LEFT JOIN stock_picking sp - ON sp.id = st.picking_id - LEFT JOIN report_logbook_sj_line rlsl - ON (rlsl.picking_id = COALESCE(sp.id, st.picking_id)) - OR (rlsl.name IS NOT NULL AND rlsl.name = COALESCE(sp.name, st.picking_name)) - WHERE rlsl.id IS NULL - AND COALESCE(sp.name, st.picking_name) IS NOT NULL - ORDER BY st.create_date ASC - LIMIT 20 - """) - rows = self.env.cr.fetchall() - - if not rows: - _logger.info("SJ Tele: tidak ada data untuk dikirim (staging kosong atau semua sudah di logbook).") - text = "Selamat anda menamatkan Logbook SJ Report" + api_base = f'https://api.telegram.org/bot{bot_mqdd}' + + data = self.search([], order='create_date asc', limit=15) + + if not data: + text = "Berikut merupakan nomor BU/OUT yang belum ada di Logbook SJ report:\n✅ tidak ada data (semua sudah tercatat)." try: - resp = requests.post(apiURL, json={'chat_id': chat_id_mqdd, 'text': text}, timeout=15) + r = requests.post(api_base + "/sendMessage", + json={'chat_id': chat_id_mqdd, 'text': text}, + timeout=20) + r.raise_for_status() except Exception as e: - logging.getLogger(__name__).exception("Gagal kirim Telegram: %s", e) + _logger.exception("Gagal kirim Telegram (no data): %s", e) return True + lines = [] + for rec in data: + name = rec.picking_name or (rec.picking_id.name if rec.picking_id else '') + pid = rec.picking_id.id if rec.picking_id else '-' + so = rec.sale_id.name if rec.sale_id else '-' + if name: + lines.append(f"{name} - {so} ({pid})") + header = "Berikut merupakan nomor BU/OUT yang belum ada di Logbook SJ report:\n" - body = "\n".join(f"{name} ({pid})" for pid, name in rows if name) - text = header + body + text = header + "\n".join(lines) + try: - resp = requests.post(apiURL, json={'chat_id': chat_id_mqdd, 'text': text}, timeout=15) - except requests.HTTPError: - _logger.error("Telegram response: %s", resp.text) - raise + r = requests.post(api_base + "/sendMessage", + json={'chat_id': chat_id_mqdd, 'text': text}) + r.raise_for_status() except Exception as e: - logging.getLogger(__name__).exception("Gagal kirim Telegram: %s", e) + _logger.exception("Gagal kirim Telegram: %s", e) return True \ No newline at end of file -- cgit v1.2.3 From cae2e6978066469505167da9469519ea2de14cab Mon Sep 17 00:00:00 2001 From: Miqdad Date: Fri, 5 Sep 2025 07:27:44 +0700 Subject: oke --- indoteknik_custom/models/sj_tele.py | 1 + 1 file changed, 1 insertion(+) diff --git a/indoteknik_custom/models/sj_tele.py b/indoteknik_custom/models/sj_tele.py index 50e47e78..9559a541 100644 --- a/indoteknik_custom/models/sj_tele.py +++ b/indoteknik_custom/models/sj_tele.py @@ -13,6 +13,7 @@ class SjTele(models.Model): picking_id = fields.Many2one('stock.picking', string='Picking') sale_id = fields.Many2one('sale.order', string='Sales Order') picking_name = fields.Char(string='Picking Name') + sale_name = fields.Char(string='Sale Name') create_date = fields.Datetime(string='Create Date') def woi(self): -- cgit v1.2.3 From ba8b646073ee09b962d58b24b340f47d18aa611f Mon Sep 17 00:00:00 2001 From: IT Fixcomart Date: Fri, 5 Sep 2025 00:54:20 +0000 Subject: sj_tele.py edited online with Bitbucket --- indoteknik_custom/models/sj_tele.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/indoteknik_custom/models/sj_tele.py b/indoteknik_custom/models/sj_tele.py index 9559a541..246c0f43 100644 --- a/indoteknik_custom/models/sj_tele.py +++ b/indoteknik_custom/models/sj_tele.py @@ -37,8 +37,8 @@ class SjTele(models.Model): lines = [] for rec in data: name = rec.picking_name or (rec.picking_id.name if rec.picking_id else '') - pid = rec.picking_id.id if rec.picking_id else '-' - so = rec.sale_id.name if rec.sale_id else '-' + pid = rec.picking_id.id if rec.picking_id else '' + so = rec.sale_id.name or rec.sale_name or '' if name: lines.append(f"{name} - {so} ({pid})") -- cgit v1.2.3 From f82137850801cb8d4c8cb482f607b68181ef1cb6 Mon Sep 17 00:00:00 2001 From: Miqdad Date: Sat, 6 Sep 2025 08:33:49 +0700 Subject: carte --- indoteknik_custom/models/sj_tele.py | 27 ++++++++++++++++++++++++++- indoteknik_custom/views/sj_tele.xml | 2 +- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/indoteknik_custom/models/sj_tele.py b/indoteknik_custom/models/sj_tele.py index 246c0f43..c8f7c0c6 100644 --- a/indoteknik_custom/models/sj_tele.py +++ b/indoteknik_custom/models/sj_tele.py @@ -1,7 +1,8 @@ from odoo import models, fields, api +from odoo.exceptions import UserError import requests import json -import logging +import logging, subprocess _logger = logging.getLogger(__name__) @@ -16,6 +17,30 @@ class SjTele(models.Model): sale_name = fields.Char(string='Sale Name') create_date = fields.Datetime(string='Create Date') + @api.model + def run_pentaho_carte(self): + carte = "http://127.0.0.1:8080" + job_kjb = r"C:/Users/ThinkPad/Desktop/tes.kjb" + params = {"job": job_kjb, "level": "Basic", "block": "Y"} + try: + r = requests.get( + f"{carte}/kettle/executeJob/", + params=params, + auth=("cluster", "cluster"), + timeout=900, + ) + r.raise_for_status() + # kalau Carte mengembalikan ERROR, anggap gagal + if "ERROR" in r.text: + raise UserError(f"Carte error: {r.text}") + except Exception as e: + _logger.exception("Carte call failed: %s", e) + raise UserError(f"Gagal memanggil Carte: {e}") + + self.env['sj.tele'].sudo().woi() + + return True + def woi(self): bot_mqdd = '8203414501:AAHy_XwiUAVrgRM2EJzW7sZx9npRLITZpb8' chat_id_mqdd = '-4885333032' diff --git a/indoteknik_custom/views/sj_tele.xml b/indoteknik_custom/views/sj_tele.xml index cefcc968..2e1e5120 100644 --- a/indoteknik_custom/views/sj_tele.xml +++ b/indoteknik_custom/views/sj_tele.xml @@ -4,7 +4,7 @@ SJ TELE code - model.woi() + model.run_pentaho_carte() 1 days -1 -- cgit v1.2.3 From ea6364616f5a6ecbcf933249aeb95a7f3c8b4555 Mon Sep 17 00:00:00 2001 From: Miqdad Date: Sat, 6 Sep 2025 11:33:02 +0700 Subject: Comment --- indoteknik_custom/models/sj_tele.py | 45 ++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/indoteknik_custom/models/sj_tele.py b/indoteknik_custom/models/sj_tele.py index c8f7c0c6..c00279ec 100644 --- a/indoteknik_custom/models/sj_tele.py +++ b/indoteknik_custom/models/sj_tele.py @@ -3,6 +3,7 @@ from odoo.exceptions import UserError import requests import json import logging, subprocess +import time _logger = logging.getLogger(__name__) @@ -17,29 +18,31 @@ class SjTele(models.Model): sale_name = fields.Char(string='Sale Name') create_date = fields.Datetime(string='Create Date') - @api.model - def run_pentaho_carte(self): - carte = "http://127.0.0.1:8080" - job_kjb = r"C:/Users/ThinkPad/Desktop/tes.kjb" - params = {"job": job_kjb, "level": "Basic", "block": "Y"} - try: - r = requests.get( - f"{carte}/kettle/executeJob/", - params=params, - auth=("cluster", "cluster"), - timeout=900, - ) - r.raise_for_status() - # kalau Carte mengembalikan ERROR, anggap gagal - if "ERROR" in r.text: - raise UserError(f"Carte error: {r.text}") - except Exception as e: - _logger.exception("Carte call failed: %s", e) - raise UserError(f"Gagal memanggil Carte: {e}") + # @api.model + # def run_pentaho_carte(self): + # carte = "http://127.0.0.1:8080" + # job_kjb = r"C:/Users/Indoteknik/Desktop/tes.kjb" + # params = {"job": job_kjb, "level": "Basic", "block": "Y"} + # try: + # r = requests.get( + # f"{carte}/kettle/executeJob/", + # params=params, + # auth=("cluster", "cluster"), + # timeout=900, + # ) + # r.raise_for_status() + # # kalau Carte mengembalikan ERROR, anggap gagal + # if "ERROR" in r.text: + # raise UserError(f"Carte error: {r.text}") + # except Exception as e: + # _logger.exception("Carte call failed: %s", e) + # raise UserError(f"Gagal memanggil Carte: {e}") + + # time.sleep(3) - self.env['sj.tele'].sudo().woi() + # self.env['sj.tele'].sudo().woi() - return True + # return True def woi(self): bot_mqdd = '8203414501:AAHy_XwiUAVrgRM2EJzW7sZx9npRLITZpb8' -- cgit v1.2.3 From 76676d8b0c41672d11ae392500dfb5a6db1cfd91 Mon Sep 17 00:00:00 2001 From: Miqdad Date: Sat, 6 Sep 2025 11:33:57 +0700 Subject: fix called method --- indoteknik_custom/views/sj_tele.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indoteknik_custom/views/sj_tele.xml b/indoteknik_custom/views/sj_tele.xml index 2e1e5120..cefcc968 100644 --- a/indoteknik_custom/views/sj_tele.xml +++ b/indoteknik_custom/views/sj_tele.xml @@ -4,7 +4,7 @@ SJ TELE code - model.run_pentaho_carte() + model.woi() 1 days -1 -- cgit v1.2.3 From 7f49cfa92bed67bea8359433ff5c08cb069f284e Mon Sep 17 00:00:00 2001 From: Miqdad Date: Tue, 9 Sep 2025 11:49:54 +0700 Subject: add tanggal kirim sj --- indoteknik_custom/models/sj_tele.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/indoteknik_custom/models/sj_tele.py b/indoteknik_custom/models/sj_tele.py index c00279ec..8864a313 100644 --- a/indoteknik_custom/models/sj_tele.py +++ b/indoteknik_custom/models/sj_tele.py @@ -4,6 +4,7 @@ import requests import json import logging, subprocess import time +from collections import OrderedDict _logger = logging.getLogger(__name__) @@ -17,6 +18,7 @@ class SjTele(models.Model): picking_name = fields.Char(string='Picking Name') sale_name = fields.Char(string='Sale Name') create_date = fields.Datetime(string='Create Date') + date_doc_kirim = fields.Datetime(string='Tanggal Kirim SJ') # @api.model # def run_pentaho_carte(self): @@ -62,13 +64,32 @@ class SjTele(models.Model): _logger.exception("Gagal kirim Telegram (no data): %s", e) return True + lines = [] + groups = OrderedDict() + for rec in data: name = rec.picking_name or (rec.picking_id.name if rec.picking_id else '') pid = rec.picking_id.id if rec.picking_id else '' - so = rec.sale_id.name or rec.sale_name or '' + so = rec.sale_id.name or rec.sale_name or '' + dttm = (rec.picking_id.date_doc_kirim if (rec.picking_id and rec.picking_id.date_doc_kirim) + else getattr(rec, 'date_doc_kirim', None)) + + # format header tanggal (string), tanpa konversi Waktu/WIB + if dttm: + date_header = dttm if isinstance(dttm, str) else fields.Datetime.to_string(dttm) + date_header = date_header[:10] + else: + date_header = '(Tidak ada tanggal kirim SJ)' + if name: - lines.append(f"{name} - {so} ({pid})") + groups.setdefault(date_header, []).append(f"- ({pid}) - {name} - {so}") + + # build output berurutan per tanggal + for header_date, items in groups.items(): + lines.append(header_date) + lines.extend(items) + header = "Berikut merupakan nomor BU/OUT yang belum ada di Logbook SJ report:\n" text = header + "\n".join(lines) -- cgit v1.2.3 From 064cdf03526540e0cde6b6740fc97764c003adff Mon Sep 17 00:00:00 2001 From: Miqdad Date: Sun, 14 Sep 2025 00:42:04 +0700 Subject: MO kalau sudah jadi PO tidak perlu approval purchasing manager --- indoteknik_custom/models/manufacturing.py | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/indoteknik_custom/models/manufacturing.py b/indoteknik_custom/models/manufacturing.py index aea01362..3e4f386d 100644 --- a/indoteknik_custom/models/manufacturing.py +++ b/indoteknik_custom/models/manufacturing.py @@ -7,22 +7,24 @@ _logger = logging.getLogger(__name__) class Manufacturing(models.Model): _inherit = 'mrp.production' unbuild_counter = fields.Integer(string='Unbuild Counter', default=0, help='For restrict unbuild more than once') - + def action_confirm(self): if self._name != 'mrp.production': return super(Manufacturing, self).action_confirm() - if not self.env.user.is_purchasing_manager: - raise UserError("Hanya bisa di confirm oleh Purchasing Manager") - - # if self.location_src_id.id != 75: - # raise UserError('Component Location hanya bisa di AS/Stock') - # elif self.location_dest_id.id != 75: - # raise UserError('Finished Product Location hanya bisa di AS/Stock') - - result = super(Manufacturing, self).action_confirm() - return result - + for mo in self: + has_po_flag = bool(getattr(mo, 'is_po', False)) + has_po_link = bool(self.env['purchase.order'].search([ + ('manufacturing_id', '=', mo.id), + ('state', '!=', 'cancel') + ], limit=1)) + mo_has_po = has_po_flag or has_po_link + + if not mo_has_po and not self.env.user.is_purchasing_manager: + raise UserError("Hanya bisa di confirm oleh Purchasing Manager") + + return super(Manufacturing, self).action_confirm() + def button_mark_done(self): if self._name != 'mrp.production': return super(Manufacturing, self).button_mark_done() -- cgit v1.2.3 From 7748c35d64c802ff5fc3d93aaf41c465b1f78e10 Mon Sep 17 00:00:00 2001 From: Miqdad Date: Mon, 15 Sep 2025 09:18:54 +0700 Subject: Update add date doc kirim --- indoteknik_custom/models/sj_tele.py | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/indoteknik_custom/models/sj_tele.py b/indoteknik_custom/models/sj_tele.py index c00279ec..43709f45 100644 --- a/indoteknik_custom/models/sj_tele.py +++ b/indoteknik_custom/models/sj_tele.py @@ -4,19 +4,21 @@ import requests import json import logging, subprocess import time +from collections import OrderedDict + +logger = logging.getLogger(__name__) -_logger = logging.getLogger(__name__) class SjTele(models.Model): _name = 'sj.tele' _description = 'sj.tele' - picking_id = fields.Many2one('stock.picking', string='Picking') sale_id = fields.Many2one('sale.order', string='Sales Order') picking_name = fields.Char(string='Picking Name') sale_name = fields.Char(string='Sale Name') create_date = fields.Datetime(string='Create Date') + date_doc_kirim = fields.Datetime(string='Tanggal Kirim SJ') # @api.model # def run_pentaho_carte(self): @@ -37,7 +39,7 @@ class SjTele(models.Model): # except Exception as e: # _logger.exception("Carte call failed: %s", e) # raise UserError(f"Gagal memanggil Carte: {e}") - + # time.sleep(3) # self.env['sj.tele'].sudo().woi() @@ -63,12 +65,29 @@ class SjTele(models.Model): return True lines = [] + groups = OrderedDict() + for rec in data: name = rec.picking_name or (rec.picking_id.name if rec.picking_id else '') - pid = rec.picking_id.id if rec.picking_id else '' + pid = rec.picking_id.id if rec.picking_id else '' so = rec.sale_id.name or rec.sale_name or '' + dttm = (rec.picking_id.date_doc_kirim if (rec.picking_id and rec.picking_id.date_doc_kirim) + else getattr(rec, 'date_doc_kirim', None)) + + # format header tanggal (string), tanpa konversi Waktu/WIB + if dttm: + date_header = dttm if isinstance(dttm, str) else fields.Datetime.to_string(dttm) + date_header = date_header[:10] + else: + date_header = '(Tidak ada tanggal kirim SJ)' + if name: - lines.append(f"{name} - {so} ({pid})") + groups.setdefault(date_header, []).append(f"- ({pid}) - {name} - {so}") + + # build output berurutan per tanggal + for header_date, items in groups.items(): + lines.append(header_date) + lines.extend(items) header = "Berikut merupakan nomor BU/OUT yang belum ada di Logbook SJ report:\n" text = header + "\n".join(lines) @@ -78,5 +97,5 @@ class SjTele(models.Model): json={'chat_id': chat_id_mqdd, 'text': text}) r.raise_for_status() except Exception as e: - _logger.exception("Gagal kirim Telegram: %s", e) + logger.exception("Gagal kirim Telegram: %s", e) return True \ No newline at end of file -- cgit v1.2.3 From 3bc157731d03e9beb41dab993461b2bd6dcb1953 Mon Sep 17 00:00:00 2001 From: Miqdad Date: Mon, 15 Sep 2025 10:12:37 +0700 Subject: balikin --- indoteknik_custom/models/manufacturing.py | 32 +++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/indoteknik_custom/models/manufacturing.py b/indoteknik_custom/models/manufacturing.py index 3e4f386d..f986fd4f 100644 --- a/indoteknik_custom/models/manufacturing.py +++ b/indoteknik_custom/models/manufacturing.py @@ -4,6 +4,7 @@ import logging _logger = logging.getLogger(__name__) + class Manufacturing(models.Model): _inherit = 'mrp.production' unbuild_counter = fields.Integer(string='Unbuild Counter', default=0, help='For restrict unbuild more than once') @@ -12,18 +13,16 @@ class Manufacturing(models.Model): if self._name != 'mrp.production': return super(Manufacturing, self).action_confirm() - for mo in self: - has_po_flag = bool(getattr(mo, 'is_po', False)) - has_po_link = bool(self.env['purchase.order'].search([ - ('manufacturing_id', '=', mo.id), - ('state', '!=', 'cancel') - ], limit=1)) - mo_has_po = has_po_flag or has_po_link + if not self.env.user.is_purchasing_manager: + raise UserError("Hanya bisa di confirm oleh Purchasing Manager") - if not mo_has_po and not self.env.user.is_purchasing_manager: - raise UserError("Hanya bisa di confirm oleh Purchasing Manager") + # if self.location_src_id.id != 75: + # raise UserError('Component Location hanya bisa di AS/Stock') + # elif self.location_dest_id.id != 75: + # raise UserError('Finished Product Location hanya bisa di AS/Stock') - return super(Manufacturing, self).action_confirm() + result = super(Manufacturing, self).action_confirm() + return result def button_mark_done(self): if self._name != 'mrp.production': @@ -31,29 +30,30 @@ class Manufacturing(models.Model): # Check product category if self.product_id.categ_id.name != 'Finish Good': raise UserError('Tidak bisa di complete karna product category bukan Unit / Finish Good') - + if self.sale_order and self.sale_order.state != 'sale': raise UserError( ('Tidak bisa Mark as Done.\nSales Order "%s" (Nomor: %s) belum dikonfirmasi.') % (self.sale_order.partner_id.name, self.sale_order.name) ) - + for line in self.move_raw_ids: # if line.quantity_done > 0 and line.quantity_done != self.product_uom_qty: # raise UserError('Qty Consume per Line tidak sama dengan Qty to Produce') if line.forecast_availability != line.product_uom_qty: - raise UserError('Qty Reserved belum sesuai dengan yang seharusnya, product: %s' % line.product_id.display_name) + raise UserError( + 'Qty Reserved belum sesuai dengan yang seharusnya, product: %s' % line.product_id.display_name) result = super(Manufacturing, self).button_mark_done() return result - + def button_unbuild(self): if self._name != 'mrp.production': return super(Manufacturing, self).button_unbuild() - + if self.unbuild_counter >= 1: raise UserError('Tidak bisa unbuild lebih dari 1 kali') - + self.unbuild_counter = self.unbuild_counter + 1 result = super(Manufacturing, self).button_unbuild() -- cgit v1.2.3 From 248c42efcc30cb55d1827bb7b1e438753ffd0898 Mon Sep 17 00:00:00 2001 From: Miqdad Date: Mon, 15 Sep 2025 11:07:40 +0700 Subject: done --- indoteknik_custom/models/purchase_order.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/indoteknik_custom/models/purchase_order.py b/indoteknik_custom/models/purchase_order.py index 18811b85..98cf6ff1 100755 --- a/indoteknik_custom/models/purchase_order.py +++ b/indoteknik_custom/models/purchase_order.py @@ -1066,8 +1066,11 @@ class PurchaseOrder(models.Model): # sticky=True # ) + has_bom = self.product_bom_id.id + has_manufacturing = self.manufacturing_id.id + 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 has_bom and not has_manufacturing: raise UserError("Tidak ada link dengan SO, harus di confirm oleh Purchasing Manager") send_email = False -- cgit v1.2.3 From 1afdf5c126bc41ece2e197610a340aab1d102c58 Mon Sep 17 00:00:00 2001 From: Miqdad Date: Mon, 15 Sep 2025 12:37:32 +0700 Subject: add line no --- indoteknik_custom/models/logbook_sj.py | 5 ++- indoteknik_custom/models/report_logbook_sj.py | 58 ++++++++++++++++++++++++++- indoteknik_custom/views/report_logbook_sj.xml | 2 + 3 files changed, 62 insertions(+), 3 deletions(-) diff --git a/indoteknik_custom/models/logbook_sj.py b/indoteknik_custom/models/logbook_sj.py index 75b2622f..0cda9c8b 100644 --- a/indoteknik_custom/models/logbook_sj.py +++ b/indoteknik_custom/models/logbook_sj.py @@ -24,6 +24,7 @@ class LogbookSJ(models.TransientModel): } report_logbook = self.env['report.logbook.sj'].create([parameters_header]) + seq=1 for line in logbook_line: picking = self.env['stock.picking'].search([('picking_code', '=', line.name)], limit=1) if not picking: @@ -43,9 +44,11 @@ class LogbookSJ(models.TransientModel): 'tracking_no': stock.delivery_tracking_no, 'partner_id': parent_id, 'report_logbook_sj_id': report_logbook.id, - 'note': line.note + 'note': line.note, + 'line_num': seq } self.env['report.logbook.sj.line'].create([data]) + seq += 1 report_logbook_ids.append(report_logbook.id) line.unlink() diff --git a/indoteknik_custom/models/report_logbook_sj.py b/indoteknik_custom/models/report_logbook_sj.py index 17119c12..66edbf99 100644 --- a/indoteknik_custom/models/report_logbook_sj.py +++ b/indoteknik_custom/models/report_logbook_sj.py @@ -1,3 +1,5 @@ +from operator import index + from odoo import models, fields, api from odoo.exceptions import UserError from pytz import timezone @@ -60,9 +62,30 @@ class ReportLogbookSJ(models.Model): self.state = 'terima_semua' else: raise UserError('Hanya Accounting yang bisa Approve') - + + + def write(self, vals): + res = super(ReportLogbookSJ, self).write(vals) + if 'report_logbook_sj_line' in vals or any(f in vals for f in ()): + self._resequence_lines() + return res + + def _resequence_lines(self): + for rec in self: + lines = rec.report_logbook_sj_line.sorted(key=lambda l: (l.line_num or 0, l.id)) + for idx, line in enumerate(lines, start=1): + if line.line_num != idx: + line.line_num = idx + + @api.onchange('report_logbook_sj_line') + def _onchange_report_logbook_sj_line(self): + self._resequence_lines() + +from odoo import models, fields, api + class ReportLogbookSJLine(models.Model): _name = 'report.logbook.sj.line' + _order = 'sequence, id' # urut default di UI & ORM (drag pakai sequence) name = fields.Char(string='SJ Number') driver_id = fields.Many2one(comodel_name='res.users', string='Driver') @@ -70,10 +93,41 @@ class ReportLogbookSJLine(models.Model): arrival_date = fields.Char(string='Arrival Date') carrier_id = fields.Many2one('delivery.carrier', string='Shipping Method') tracking_no = fields.Char(string='Tracking No') - logbook_sj_id = fields.Many2one('report.logbook.sj', string='Logbook SJ') # Corrected model name + + # NOTE: field ini duplikat relasi; pakai salah satu saja. + # kamu boleh hapus logbook_sj_id kalau tidak dipakai di tempat lain. + logbook_sj_id = fields.Many2one('report.logbook.sj', string='Logbook SJ') + partner_id = fields.Many2one('res.partner', string='Customer') picking_id = fields.Many2one('stock.picking', string='Picking') sale_id = fields.Many2one('sale.order', string='Sale Order') + report_logbook_sj_id = fields.Many2one('report.logbook.sj', string='Logbook SJ') not_exist = fields.Boolean(string='Not Exist') note = fields.Char(string='Note') + + sequence = fields.Integer(string='Sequence', default=0, index=True) + + line_num = fields.Integer(string='No', compute='_compute_line_num', store=False) + + @api.depends( + 'report_logbook_sj_id.report_logbook_sj_line', + 'report_logbook_sj_id.report_logbook_sj_line.sequence' + ) + def _compute_line_num(self): + for parent in self.mapped('report_logbook_sj_id'): + lines = parent.report_logbook_sj_line.sorted(key=lambda l: (l.sequence or 0, l.id)) + for i, l in enumerate(lines, start=1): + l.line_num = i + for rec in self.filtered(lambda r: not r.report_logbook_sj_id): + rec.line_num = 0 + + @api.model + def create(self, vals): + if not vals.get('sequence') and vals.get('report_logbook_sj_id'): + last = self.search( + [('report_logbook_sj_id', '=', vals['report_logbook_sj_id'])], + order='sequence desc, id desc', limit=1 + ) + vals['sequence'] = (last.sequence or 0) + 1 + return super().create(vals) diff --git a/indoteknik_custom/views/report_logbook_sj.xml b/indoteknik_custom/views/report_logbook_sj.xml index 94f6c2ab..f2920b78 100644 --- a/indoteknik_custom/views/report_logbook_sj.xml +++ b/indoteknik_custom/views/report_logbook_sj.xml @@ -21,6 +21,8 @@ report.logbook.sj.line + + -- cgit v1.2.3 From cc51c51ac0e89e3edf762b1a7a809ce8304dc53c Mon Sep 17 00:00:00 2001 From: Miqdad Date: Mon, 15 Sep 2025 12:55:59 +0700 Subject: add line no --- indoteknik_custom/views/report_logbook_sj.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indoteknik_custom/views/report_logbook_sj.xml b/indoteknik_custom/views/report_logbook_sj.xml index f2920b78..2b7cfa22 100644 --- a/indoteknik_custom/views/report_logbook_sj.xml +++ b/indoteknik_custom/views/report_logbook_sj.xml @@ -21,7 +21,7 @@ report.logbook.sj.line - + -- cgit v1.2.3 From 59115214600bedab111baa556be7f410893faec9 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Mon, 15 Sep 2025 14:05:26 +0700 Subject: push --- indoteknik_custom/report/purchase_report.xml | 93 ++++++++++++++-------------- 1 file changed, 47 insertions(+), 46 deletions(-) diff --git a/indoteknik_custom/report/purchase_report.xml b/indoteknik_custom/report/purchase_report.xml index 168428a6..333b807a 100644 --- a/indoteknik_custom/report/purchase_report.xml +++ b/indoteknik_custom/report/purchase_report.xml @@ -29,44 +29,44 @@ - +
+ style="width:100%; display:block;"/>
- -
+
+ -

+

PURCHASE ORDER

-

+

No.

- - - - - +
Term Of Payment: Order Date: Responsible:
+ + + +
Term Of Payment: Order Date: Responsible:
- +
- -
- Alamat Pengiriman:
+
+ Alamat Pengiriman
PT Indoteknik (Bandengan 1 Depan)
Jl. Bandengan Utara Komp A 8 B
RT. Penjaringan, Kec. Penjaringan, Jakarta (BELAKANG INDOMARET)
JK 14440 - Indonesia
- Nama Vendor:
+
+ Nama Vendor


- @@ -75,38 +75,37 @@
- +
- - - - - - + + + + + + - - - - - + - - - - - - + @@ -116,34 +115,36 @@
DescriptionQuantityUnit PriceTaxesSubtotal
No. & DescriptionQuantityUnit PriceTaxesSubtotal
+ +
+ . + + + +
+
- - - - +
Subtotal
+ + + - - + + - - - + + +
Subtotal
TaxesTaxes
Total
Total
-
+

- + + + -- cgit v1.2.3 From a7baa3c7f42d33064039cdea7ce6d3ae6d515f81 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Mon, 15 Sep 2025 14:30:12 +0700 Subject: push --- indoteknik_custom/report/purchase_report.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indoteknik_custom/report/purchase_report.xml b/indoteknik_custom/report/purchase_report.xml index 333b807a..f3d203fc 100644 --- a/indoteknik_custom/report/purchase_report.xml +++ b/indoteknik_custom/report/purchase_report.xml @@ -105,7 +105,7 @@ - +
-- cgit v1.2.3 From 7b35f872704d12fc7ba60581d4f10ce4ded00763 Mon Sep 17 00:00:00 2001 From: Miqdad Date: Mon, 15 Sep 2025 15:06:34 +0700 Subject: lepas validasi --- indoteknik_custom/models/tukar_guling.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/indoteknik_custom/models/tukar_guling.py b/indoteknik_custom/models/tukar_guling.py index d718ba0f..f435dd9f 100644 --- a/indoteknik_custom/models/tukar_guling.py +++ b/indoteknik_custom/models/tukar_guling.py @@ -492,14 +492,14 @@ class TukarGuling(models.Model): self.ensure_one() self._check_not_allow_tukar_guling_on_bu_pick() - existing_tukar_guling = self.env['tukar.guling'].search([ - ('operations', '=', self.operations.id), - ('id', '!=', self.id), - ('state', '!=', 'cancel'), - ], limit=1) - - if existing_tukar_guling: - raise UserError("BU ini sudah pernah diretur oleh dokumen %s." % existing_tukar_guling.name) + # existing_tukar_guling = self.env['tukar.guling'].search([ + # ('operations', '=', self.operations.id), + # ('id', '!=', self.id), + # ('state', '!=', 'cancel'), + # ], limit=1) + # + # if existing_tukar_guling: + # raise UserError("BU ini sudah pernah diretur oleh dokumen %s." % existing_tukar_guling.name) picking = self.operations if picking.picking_type_id.id == 30 and self.return_type == 'tukar_guling': raise UserError("❌ BU/PICK tidak boleh di retur tukar guling") -- cgit v1.2.3 From eca46bd7ed2df2bf1552ffdbd72a84345c77de81 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Mon, 15 Sep 2025 15:25:34 +0700 Subject: push --- indoteknik_custom/report/purchase_report.xml | 41 ++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/indoteknik_custom/report/purchase_report.xml b/indoteknik_custom/report/purchase_report.xml index f3d203fc..80112947 100644 --- a/indoteknik_custom/report/purchase_report.xml +++ b/indoteknik_custom/report/purchase_report.xml @@ -77,6 +77,7 @@ + @@ -84,28 +85,57 @@ + + - + + + + + + + + + + - - + @@ -114,6 +144,7 @@
No. & Description QuantityTaxes Subtotal
- . - + + + + + + + + +
+ N/A +
+
+ + +
+ + . + +
+
+ -- cgit v1.2.3 From f1af7fc1ccafea19653c03c272c2c64cd9c97218 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Mon, 15 Sep 2025 15:35:36 +0700 Subject: push --- indoteknik_custom/report/purchase_report.xml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/indoteknik_custom/report/purchase_report.xml b/indoteknik_custom/report/purchase_report.xml index 80112947..4e1e7afb 100644 --- a/indoteknik_custom/report/purchase_report.xml +++ b/indoteknik_custom/report/purchase_report.xml @@ -80,6 +80,7 @@ + @@ -92,11 +93,6 @@ + + + @@ -137,7 +137,7 @@ - -- cgit v1.2.3 From d7647af478bfe2c1b60f00ff2e13327c0ec09be2 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Mon, 15 Sep 2025 16:01:38 +0700 Subject: push --- indoteknik_custom/models/sale_order.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py index c767dd04..8f49b579 100755 --- a/indoteknik_custom/models/sale_order.py +++ b/indoteknik_custom/models/sale_order.py @@ -2644,7 +2644,7 @@ class SaleOrder(models.Model): if user.is_leader or user.is_sales_manager: return True - if user.id in (3401, 20, 3988): # admin (fida, nabila, ninda) + if user.id in (3401, 20, 3988, 17340): # admin (fida, nabila, ninda) return True if self.env.context.get("ask_approval") and user.id in (3401, 20, 3988): -- cgit v1.2.3 From 1ca068669ba7e255e8a69d981aba513dcfeedd40 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Mon, 15 Sep 2025 16:23:48 +0700 Subject: fix validasi refund --- indoteknik_custom/models/refund_sale_order.py | 20 ++++++++++++++++++-- indoteknik_custom/views/refund_sale_order.xml | 2 +- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/indoteknik_custom/models/refund_sale_order.py b/indoteknik_custom/models/refund_sale_order.py index f511ed5d..9b14243b 100644 --- a/indoteknik_custom/models/refund_sale_order.py +++ b/indoteknik_custom/models/refund_sale_order.py @@ -56,6 +56,7 @@ class RefundSaleOrder(models.Model): refund_type = fields.Selection([ ('barang_kosong_sebagian', 'Refund Barang Kosong Sebagian'), + ('barang_kosong_indent', 'Refund Barang Kosong Jika ada Indent'), ('barang_kosong', 'Refund Barang Kosong Full'), ('uang', 'Refund Lebih Bayar'), ('retur_half', 'Refund Retur Sebagian'), @@ -77,7 +78,7 @@ class RefundSaleOrder(models.Model): 'account.move', string="Journal Payment", copy=False, - help="Pilih transaksi salah transfer dari jurnal Uang Muka (journal_id=11) yang tidak terkait SO." + help="Pilih transaksi salah transfer dari jurnal Uang Muka yang tidak terkait SO." ) tukar_guling_count = fields.Integer( @@ -297,6 +298,14 @@ 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 can_refund > amount_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') @@ -393,9 +402,16 @@ class RefundSaleOrder(models.Model): 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 amount_refund = vals.get('amount_refund', rec.amount_refund) + if amount_refund > can_refund: + raise ValidationError( + _("Maksimal refund yang bisa dilakukan adalah sebesar %s. " + "Silakan sesuaikan jumlah refund.") % (can_refund) + ) + if amount_refund <= 0: raise ValidationError("Total Refund harus lebih dari 0.") @@ -829,7 +845,7 @@ class RefundSaleOrder(models.Model): # Normalisasi refund_type_label = refund_type_label.upper() - if refund.refund_type in ['barang_kosong', 'barang_kosong_sebagian']: + if refund.refund_type in ['barang_kosong', 'barang_kosong_sebagian', 'barang_kosong_indent']: refund_type_label = "REFUND BARANG KOSONG" elif refund.refund_type in ['retur_half', 'retur']: refund_type_label = "REFUND RETUR BARANG" diff --git a/indoteknik_custom/views/refund_sale_order.xml b/indoteknik_custom/views/refund_sale_order.xml index 0c6cd371..51f3deab 100644 --- a/indoteknik_custom/views/refund_sale_order.xml +++ b/indoteknik_custom/views/refund_sale_order.xml @@ -92,7 +92,7 @@ -- cgit v1.2.3 From ada4b39703d079a92da5c6ad96ad715df13b67de Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Mon, 15 Sep 2025 17:08:09 +0700 Subject: fix validasi refund --- indoteknik_custom/models/refund_sale_order.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indoteknik_custom/models/refund_sale_order.py b/indoteknik_custom/models/refund_sale_order.py index 9b14243b..51d42514 100644 --- a/indoteknik_custom/models/refund_sale_order.py +++ b/indoteknik_custom/models/refund_sale_order.py @@ -300,7 +300,7 @@ class RefundSaleOrder(models.Model): amount_refund = vals.get('amount_refund', 0.0) can_refund = sisa_uang_masuk - total_invoice - if can_refund > amount_refund or can_refund == 0.0: + 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) -- cgit v1.2.3 From 4c305c1ac192d5610dedbc90723281dd09bc0a97 Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Mon, 15 Sep 2025 17:14:22 +0700 Subject: fix validasi refund --- indoteknik_custom/models/refund_sale_order.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/indoteknik_custom/models/refund_sale_order.py b/indoteknik_custom/models/refund_sale_order.py index 51d42514..55128080 100644 --- a/indoteknik_custom/models/refund_sale_order.py +++ b/indoteknik_custom/models/refund_sale_order.py @@ -56,7 +56,6 @@ class RefundSaleOrder(models.Model): refund_type = fields.Selection([ ('barang_kosong_sebagian', 'Refund Barang Kosong Sebagian'), - ('barang_kosong_indent', 'Refund Barang Kosong Jika ada Indent'), ('barang_kosong', 'Refund Barang Kosong Full'), ('uang', 'Refund Lebih Bayar'), ('retur_half', 'Refund Retur Sebagian'), @@ -845,7 +844,7 @@ class RefundSaleOrder(models.Model): # Normalisasi refund_type_label = refund_type_label.upper() - if refund.refund_type in ['barang_kosong', 'barang_kosong_sebagian', 'barang_kosong_indent']: + if refund.refund_type in ['barang_kosong', 'barang_kosong_sebagian']: refund_type_label = "REFUND BARANG KOSONG" elif refund.refund_type in ['retur_half', 'retur']: refund_type_label = "REFUND RETUR BARANG" -- cgit v1.2.3 From 78a4f924fa9ba38c58954b5840632806b04fff19 Mon Sep 17 00:00:00 2001 From: Miqdad Date: Mon, 15 Sep 2025 18:08:20 +0700 Subject: kembaliinn validasi --- indoteknik_custom/models/tukar_guling.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/indoteknik_custom/models/tukar_guling.py b/indoteknik_custom/models/tukar_guling.py index f435dd9f..d718ba0f 100644 --- a/indoteknik_custom/models/tukar_guling.py +++ b/indoteknik_custom/models/tukar_guling.py @@ -492,14 +492,14 @@ class TukarGuling(models.Model): self.ensure_one() self._check_not_allow_tukar_guling_on_bu_pick() - # existing_tukar_guling = self.env['tukar.guling'].search([ - # ('operations', '=', self.operations.id), - # ('id', '!=', self.id), - # ('state', '!=', 'cancel'), - # ], limit=1) - # - # if existing_tukar_guling: - # raise UserError("BU ini sudah pernah diretur oleh dokumen %s." % existing_tukar_guling.name) + existing_tukar_guling = self.env['tukar.guling'].search([ + ('operations', '=', self.operations.id), + ('id', '!=', self.id), + ('state', '!=', 'cancel'), + ], limit=1) + + if existing_tukar_guling: + raise UserError("BU ini sudah pernah diretur oleh dokumen %s." % existing_tukar_guling.name) picking = self.operations if picking.picking_type_id.id == 30 and self.return_type == 'tukar_guling': raise UserError("❌ BU/PICK tidak boleh di retur tukar guling") -- cgit v1.2.3 From abb95335ee639c1d5b6d3eb0e7f65f452c77706c Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 16 Sep 2025 09:27:19 +0700 Subject: fix status website --- indoteknik_api/models/sale_order.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indoteknik_api/models/sale_order.py b/indoteknik_api/models/sale_order.py index c59dead9..23be358a 100644 --- a/indoteknik_api/models/sale_order.py +++ b/indoteknik_api/models/sale_order.py @@ -75,7 +75,7 @@ class SaleOrder(models.Model): if sale_order.state == 'sale': bu_pickings = [ p for p in sale_order.picking_ids - if p.picking_type_id and p.picking_type_id.id == 29 + if p.picking_type_id and p.picking_type_id.id == 29 and p.state != 'cancel' ] # Hitung status masing-masing picking -- cgit v1.2.3 From 7fe2c169a448df17c9395dfae20c524e94aa8bfc Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Tue, 16 Sep 2025 09:27:32 +0700 Subject: push --- indoteknik_custom/models/purchase_order.py | 2 +- indoteknik_custom/models/purchase_order_line.py | 1 + indoteknik_custom/report/purchase_report.xml | 10 ++-------- indoteknik_custom/views/purchase_order.xml | 10 ++++++---- 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/indoteknik_custom/models/purchase_order.py b/indoteknik_custom/models/purchase_order.py index 98cf6ff1..4636c243 100755 --- a/indoteknik_custom/models/purchase_order.py +++ b/indoteknik_custom/models/purchase_order.py @@ -137,7 +137,7 @@ class PurchaseOrder(models.Model): def _compute_date_planned(self): """ date_planned = the earliest date_planned across all order lines. """ for order in self: - order.date_planned = False + order.date_planned = order.date_planned @api.constrains('date_planned') def constrains_date_planned(self): diff --git a/indoteknik_custom/models/purchase_order_line.py b/indoteknik_custom/models/purchase_order_line.py index 315795d5..a3c3a33b 100755 --- a/indoteknik_custom/models/purchase_order_line.py +++ b/indoteknik_custom/models/purchase_order_line.py @@ -50,6 +50,7 @@ class PurchaseOrderLine(models.Model): cost_service_per_item = fields.Float(string='Biaya Jasa Per Item', compute='_compute_doc_delivery_amt') contribution_cost_service = fields.Float(string='Contribution Cost Service', compute='_compute_doc_delivery_amt') ending_price = fields.Float(string='Ending Price', compute='_compute_doc_delivery_amt') + show_description = fields.Boolean(string='Show Description', help="Show Description when print po", default=True) def _compute_doc_delivery_amt(self): for line in self: diff --git a/indoteknik_custom/report/purchase_report.xml b/indoteknik_custom/report/purchase_report.xml index 6666235a..555adff4 100644 --- a/indoteknik_custom/report/purchase_report.xml +++ b/indoteknik_custom/report/purchase_report.xml @@ -93,12 +93,6 @@ - + - diff --git a/indoteknik_custom/views/purchase_order.xml b/indoteknik_custom/views/purchase_order.xml index 821f3295..a3a5e05c 100755 --- a/indoteknik_custom/views/purchase_order.xml +++ b/indoteknik_custom/views/purchase_order.xml @@ -112,6 +112,7 @@ + {'no_create': True} @@ -181,19 +182,20 @@ - {'readonly': ['|', ('state', 'in', ['purchase', 'done', 'cancel']), ('has_active_invoice', '=', True)]} + + {'readonly': [('has_active_invoice', '=', True)]} - {'readonly': [], 'required': True} + {'readonly': [('state', 'in', ['purchase', 'done', 'cancel'])], 'required': True} - {'readonly': []} + {'readonly': [('state', 'in', ['purchase', 'done', 'cancel'])]} - {'required': True} + {'readonly': [('state', 'in', ['purchase', 'done', 'cancel'])], 'required': True} -- cgit v1.2.3 From 41b9e8084b388dca0b5b18daf0dfe9537db1ed1c Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 16 Sep 2025 10:08:42 +0700 Subject: push --- indoteknik_api/controllers/api_v1/sale_order.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indoteknik_api/controllers/api_v1/sale_order.py b/indoteknik_api/controllers/api_v1/sale_order.py index accc7531..1a75c830 100644 --- a/indoteknik_api/controllers/api_v1/sale_order.py +++ b/indoteknik_api/controllers/api_v1/sale_order.py @@ -198,7 +198,7 @@ class SaleOrder(controller.Controller): if status in ['dikemas', 'dikirim', 'selesai', 'partial']: filtered_orders = [] for sale_order in sale_orders: - bu_pickings = [p for p in sale_order.picking_ids if p.picking_type_id and p.picking_type_id.id == 29] + bu_pickings = [p for p in sale_order.picking_ids if p.picking_type_id and p.picking_type_id.id == 29 and p.state != 'cancel'] total = len(bu_pickings) done_pickings = [p for p in bu_pickings if p.state == 'done'] done_with_driver = [p for p in done_pickings if p.sj_return_date] -- cgit v1.2.3 From f48a848147216d1cbf736d6926ab7aebffb0deba Mon Sep 17 00:00:00 2001 From: Miqdad Date: Tue, 16 Sep 2025 11:31:42 +0700 Subject: add help and change return type --- indoteknik_custom/models/tukar_guling.py | 24 ++++++++++++------------ indoteknik_custom/models/tukar_guling_po.py | 24 ++++++++++++------------ indoteknik_custom/views/tukar_guling_po.xml | 2 +- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/indoteknik_custom/models/tukar_guling.py b/indoteknik_custom/models/tukar_guling.py index d718ba0f..c683f75a 100644 --- a/indoteknik_custom/models/tukar_guling.py +++ b/indoteknik_custom/models/tukar_guling.py @@ -61,7 +61,7 @@ class TukarGuling(models.Model): notes = fields.Text('Notes') return_type = fields.Selection(String='Return Type', selection=[ ('tukar_guling', 'Tukar Guling'), # -> barang yang sama - ('revisi_so', 'Revisi SO')], required=True, tracking=3) + ('retur_so', 'Retur SO')], required=True, tracking=3, help='Retur SO (ORT-SRT),\n Tukar Guling (ORT-SRT-PICK-OUT)') state = fields.Selection(string='Status', selection=[ ('draft', 'Draft'), ('approval_sales', ' Approval Sales'), @@ -169,7 +169,7 @@ class TukarGuling(models.Model): raise UserError("❌ Picking type harus BU/OUT atau BU/PICK") for rec in self: if rec.operations and rec.operations.picking_type_id.id == 30: - rec.return_type = 'revisi_so' + rec.return_type = 'retur_so' if self.operations: from_return_picking = self.env.context.get('from_return_picking', False) or \ @@ -315,7 +315,7 @@ class TukarGuling(models.Model): @api.constrains('return_type', 'operations') def _check_required_bu_fields(self): for record in self: - if record.return_type in ['revisi_so', 'tukar_guling'] and not record.operations: + if record.return_type in ['retur_so', 'tukar_guling'] and not record.operations: raise ValidationError("Operations harus diisi") @api.constrains('line_ids', 'state') @@ -352,16 +352,16 @@ class TukarGuling(models.Model): # ('state', '!=', 'cancel') # ]) > 0 - # def _check_invoice_on_revisi_so(self): + # def _check_invoice_on_retur_so(self): # for record in self: - # if record.return_type == 'revisi_so' and record.origin: + # if record.return_type == 'retur_so' and record.origin: # invoices = self.env['account.move'].search([ # ('invoice_origin', 'ilike', record.origin), # ('state', 'not in', ['draft', 'cancel']) # ]) # if invoices: # raise ValidationError( - # _("Tidak bisa memilih Return Type 'Revisi SO' karena dokumen %s sudah dibuat invoice.") % record.origin + # _("Tidak bisa memilih Return Type 'Retur SO' karena dokumen %s sudah dibuat invoice.") % record.origin # ) @@ -414,7 +414,7 @@ class TukarGuling(models.Model): self.ensure_one() if self.operations.picking_type_id.id not in [29, 30]: raise UserError("❌ Picking type harus BU/OUT atau BU/PICK") - # self._check_invoice_on_revisi_so() + # self._check_invoice_on_retur_so() operasi = self.operations.picking_type_id.id tipe = self.return_type pp = vals.get('return_type', tipe) @@ -530,7 +530,7 @@ class TukarGuling(models.Model): raise UserError( _("Qty di Koli tidak sesuai dengan qty retur untuk produk %s") % line.product_id.display_name ) - # self._check_invoice_on_revisi_so() + # self._check_invoice_on_retur_so() self._validate_product_lines() if self.state != 'draft': @@ -553,7 +553,7 @@ class TukarGuling(models.Model): self.state = 'done' # OUT revisi SO - elif self.operations.picking_type_id.id == 29 and self.return_type == 'revisi_so': + elif self.operations.picking_type_id.id == 29 and self.return_type == 'retur_so': total_ort = self.env['stock.picking'].search_count([ ('tukar_guling_id', '=', self.id), ('picking_type_id', '=', 74), @@ -567,7 +567,7 @@ class TukarGuling(models.Model): self.state = 'done' # PICK revisi SO - elif self.operations.picking_type_id.id == 30 and self.return_type == 'revisi_so': + elif self.operations.picking_type_id.id == 30 and self.return_type == 'retur_so': done_ort = self.env['stock.picking'].search([ ('tukar_guling_id', '=', self.id), ('picking_type_id', '=', 74), @@ -581,7 +581,7 @@ class TukarGuling(models.Model): def action_approve(self): self.ensure_one() self._validate_product_lines() - # self._check_invoice_on_revisi_so() + # self._check_invoice_on_retur_so() self._check_not_allow_tukar_guling_on_bu_pick() operasi = self.operations.picking_type_id.id @@ -631,7 +631,7 @@ class TukarGuling(models.Model): elif rec.state == 'approval_finance': if not rec.env.user.has_group('indoteknik_custom.group_role_fat'): raise UserError("Hanya Finance Manager yang boleh approve tahap ini.") - # rec._check_invoice_on_revisi_so() + # rec._check_invoice_on_retur_so() rec.set_opt() rec.state = 'approval_logistic' rec.date_finance = now diff --git a/indoteknik_custom/models/tukar_guling_po.py b/indoteknik_custom/models/tukar_guling_po.py index f2f37606..f61b3828 100644 --- a/indoteknik_custom/models/tukar_guling_po.py +++ b/indoteknik_custom/models/tukar_guling_po.py @@ -38,9 +38,9 @@ class TukarGulingPO(models.Model): ) ba_num = fields.Char('Nomor BA', tracking=3) return_type = fields.Selection([ - ('revisi_po', 'Revisi PO'), + ('retur_po', 'Retur PO'), ('tukar_guling', 'Tukar Guling'), - ], string='Return Type', required=True, tracking=3) + ], string='Return Type', required=True, tracking=3, help='Retur PO (VRT-PRT),\n Tukar Guling (VRT-PRT-INPUT-PUT') notes = fields.Text('Notes', tracking=3) tukar_guling_po_id = fields.Many2one('tukar.guling.po', string='Tukar Guling PO', ondelete='cascade') line_ids = fields.One2many('tukar.guling.line.po', 'tukar_guling_po_id', string='Product Lines', tracking=3) @@ -143,9 +143,9 @@ class TukarGulingPO(models.Model): return res - # def _check_bill_on_revisi_po(self): + # def _check_bill_on_retur_po(self): # for record in self: - # if record.return_type == 'revisi_po' and record.origin: + # if record.return_type == 'retur_po' and record.origin: # bills = self.env['account.move'].search([ # ('invoice_origin', 'ilike', record.origin), # ('move_type', '=', 'in_invoice'), # hanya vendor bill @@ -153,7 +153,7 @@ class TukarGulingPO(models.Model): # ]) # if bills: # raise ValidationError( - # _("Tidak bisa memilih Return Type 'Revisi PO' karena PO %s sudah dibuat vendor bill. Harus Cancel Jika ingin melanjutkan") % record.origin + # _("Tidak bisa memilih Return Type 'Retur PO' karena PO %s sudah dibuat vendor bill. Harus Cancel Jika ingin melanjutkan") % record.origin # ) @api.onchange('operations') @@ -284,7 +284,7 @@ class TukarGulingPO(models.Model): @api.constrains('return_type', 'operations') def _check_required_bu_fields(self): for record in self: - if record.return_type in ['revisi_po', 'tukar_guling'] and not record.operations: + if record.return_type in ['retur_po', 'tukar_guling'] and not record.operations: raise ValidationError("Operations harus diisi") @api.constrains('line_ids', 'state') @@ -350,7 +350,7 @@ class TukarGulingPO(models.Model): def write(self, vals): if self.operations.picking_type_id.id not in [75, 28]: raise UserError("❌ Tidak bisa retur bukan BU/INPUT atau BU/PUT!") - # self._check_bill_on_revisi_po() + # self._check_bill_on_retur_po() tipe = vals.get('return_type', self.return_type) if self.operations and self.operations.picking_type_id.id == 28 and tipe == 'tukar_guling': @@ -418,7 +418,7 @@ class TukarGulingPO(models.Model): def action_submit(self): self.ensure_one() - # self._check_bill_on_revisi_po() + # self._check_bill_on_retur_po() self._validate_product_lines() self._check_not_allow_tukar_guling_on_bu_input() @@ -463,7 +463,7 @@ class TukarGulingPO(models.Model): def action_approve(self): self.ensure_one() self._validate_product_lines() - # self._check_bill_on_revisi_po() + # self._check_bill_on_retur_po() self._check_not_allow_tukar_guling_on_bu_input() if not self.operations: @@ -485,7 +485,7 @@ class TukarGulingPO(models.Model): elif rec.state == 'approval_finance': if not rec.env.user.has_group('indoteknik_custom.group_role_fat'): raise UserError("Hanya Finance yang boleh approve tahap ini.") - # rec._check_bill_on_revisi_po() + # rec._check_bill_on_retur_po() rec.set_opt() rec.state = 'approval_logistic' rec.date_finance = now @@ -501,7 +501,7 @@ class TukarGulingPO(models.Model): def update_doc_state(self): # bu input rev po - if self.operations.picking_type_id.id == 28 and self.return_type == 'revisi_po': + if self.operations.picking_type_id.id == 28 and self.return_type == 'retur_po': prt = self.env['stock.picking'].search([ ('tukar_guling_po_id', '=', self.id), ('state', '=', 'done'), @@ -510,7 +510,7 @@ class TukarGulingPO(models.Model): if self.state == 'approved' and prt: self.state = 'done' # bu put rev po - elif self.operations.picking_type_id.id == 75 and self.return_type == 'revisi_po': + elif self.operations.picking_type_id.id == 75 and self.return_type == 'retur_po': total_prt = self.env['stock.picking'].search_count([ ('tukar_guling_po_id', '=', self.id), ('picking_type_id.id', '=', 76) diff --git a/indoteknik_custom/views/tukar_guling_po.xml b/indoteknik_custom/views/tukar_guling_po.xml index 548a209f..4a9ab25d 100644 --- a/indoteknik_custom/views/tukar_guling_po.xml +++ b/indoteknik_custom/views/tukar_guling_po.xml @@ -87,7 +87,7 @@ -- cgit v1.2.3 From bd6165ebb7c6df46117f7ec1cd50a27e7db5a39d Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Tue, 16 Sep 2025 13:09:18 +0700 Subject: command validation cbd on override create invoice --- indoteknik_custom/models/sale_order.py | 8 ++++---- indoteknik_custom/views/sale_order.xml | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py index 8f49b579..136663ba 100755 --- a/indoteknik_custom/models/sale_order.py +++ b/indoteknik_custom/models/sale_order.py @@ -1674,7 +1674,7 @@ class SaleOrder(models.Model): rec.expected_ready_to_ship = eta_date @api.depends("order_line.product_id", "date_order") - def _compute_etrts_date(self): # Function to calculate Estimated Ready To Ship Date + def _compute_etrts_date(self): self._calculate_etrts_date() @@ -1844,9 +1844,9 @@ class SaleOrder(models.Model): def override_allow_create_invoice(self): if not self.env.user.is_accounting: raise UserError('Hanya Finance Accounting yang dapat klik tombol ini') - for term in self.payment_term_id.line_ids: - if term.days > 0: - raise UserError('Hanya dapat digunakan pada Cash Before Delivery') + # for term in self.payment_term_id.line_ids: + # if term.days > 0: + # raise UserError('Hanya dapat digunakan pada Cash Before Delivery') for line in self.order_line: line.qty_to_invoice = line.product_uom_qty diff --git a/indoteknik_custom/views/sale_order.xml b/indoteknik_custom/views/sale_order.xml index 44da3e13..8d56bbbd 100755 --- a/indoteknik_custom/views/sale_order.xml +++ b/indoteknik_custom/views/sale_order.xml @@ -297,9 +297,9 @@ - - - + + + -- cgit v1.2.3 From 4c3f0c136489c0f6d04b6f9464f788c0afff496d Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Tue, 16 Sep 2025 13:30:47 +0700 Subject: push --- indoteknik_custom/report/purchase_report.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indoteknik_custom/report/purchase_report.xml b/indoteknik_custom/report/purchase_report.xml index 555adff4..e1e9f498 100644 --- a/indoteknik_custom/report/purchase_report.xml +++ b/indoteknik_custom/report/purchase_report.xml @@ -61,7 +61,7 @@ -- cgit v1.2.3 From 3fad759d7d974e6f86bc6994320cf8f63194cdec Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Tue, 16 Sep 2025 13:33:48 +0700 Subject: push --- indoteknik_custom/report/purchase_report.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/indoteknik_custom/report/purchase_report.xml b/indoteknik_custom/report/purchase_report.xml index e1e9f498..d0b73118 100644 --- a/indoteknik_custom/report/purchase_report.xml +++ b/indoteknik_custom/report/purchase_report.xml @@ -101,12 +101,12 @@ - + + + -- cgit v1.2.3 From dba361e5b7a44b9ad2c0c7fa54355707f63fd49a Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Tue, 16 Sep 2025 17:11:14 +0700 Subject: fix bug --- indoteknik_custom/models/report_logbook_sj.py | 40 -------------------------- indoteknik_custom/security/ir.model.access.csv | 6 +++- 2 files changed, 5 insertions(+), 41 deletions(-) diff --git a/indoteknik_custom/models/report_logbook_sj.py b/indoteknik_custom/models/report_logbook_sj.py index b45eab03..3b07ff02 100644 --- a/indoteknik_custom/models/report_logbook_sj.py +++ b/indoteknik_custom/models/report_logbook_sj.py @@ -86,46 +86,6 @@ class ReportLogbookSJ(models.Model): def _onchange_report_logbook_sj_line(self): self._resequence_lines() -from odoo import models, fields, api - - - - def action_send_to_telegram(self): - - entries = [] - pickings = self.report_logbook_sj_line.mapped('picking_id') - for p in pickings: - if p: - entries.append((p.name, p.id)) - - fallback_names = [l.name for l in self.report_logbook_sj_line if not l.picking_id and l.name] - if fallback_names: - picks = self.env['stock.picking'].search([('name', 'in', list(set(fallback_names)))]) - name2id = {p.name: p.id for p in picks} - for n in fallback_names: - entries.append((n, name2id.get(n))) - - seen, unique_entries = set(), [] - for name, pid in entries: - key = pid or name - if key and key not in seen: - seen.add(key) - unique_entries.append((name, pid)) - - header = f"{self.env.user.name} sudah mengisi di Logbook SJ Report:\n" - body = "\n".join(f"{name} ({pid or '-'})" for name, pid in unique_entries) if unique_entries else "- (tidak ada)" - text = header + body - - bot_mqdd = '8203414501:AAHy_XwiUAVrgRM2EJzW7sZx9npRLITZpb8' - chat_id_mqdd = '-4885333032' - apiURL = f'https://api.telegram.org/bot{bot_mqdd}/sendMessage' - try: - hehe = requests.post(apiURL, json={'chat_id': chat_id_mqdd, 'text': text}) - _logger.info(hehe) - except Exception as e: - print(e) - - class ReportLogbookSJLine(models.Model): _name = 'report.logbook.sj.line' _order = 'sequence, id' # urut default di UI & ORM (drag pakai sequence) diff --git a/indoteknik_custom/security/ir.model.access.csv b/indoteknik_custom/security/ir.model.access.csv index 0d2789b3..423fe138 100755 --- a/indoteknik_custom/security/ir.model.access.csv +++ b/indoteknik_custom/security/ir.model.access.csv @@ -183,8 +183,13 @@ 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_purchase_order_update_date_wizard,access.purchase.order.update.date.wizard,model_purchase_order_update_date_wizard,,1,1,1,1 +access_change_date_planned_wizard,access.change.date.planned.wizard,model_change_date_planned_wizard,,1,1,1,1 access_refund_sale_order,access.refund.sale.order,model_refund_sale_order,base.group_user,1,1,1,1 access_refund_sale_order_line,access.refund.sale.order.line,model_refund_sale_order_line,base.group_user,1,1,1,1 +access_reimburse,access.reimburse,model_reimburse,,1,1,1,1 +access_reimburse_line,access.reimburse.line,model_reimburse_line,,1,1,1,1 + access_purchasing_job_seen,purchasing.job.seen,model_purchasing_job_seen,,1,1,1,1 access_tukar_guling_all_users,tukar.guling.all.users,model_tukar_guling,base.group_user,1,1,1,1 @@ -192,7 +197,6 @@ access_tukar_guling_line_all_users,tukar.guling.line.all.users,model_tukar_gulin access_tukar_guling_po_all_users,tukar.guling.po.all.users,model_tukar_guling_po,base.group_user,1,1,1,1 access_tukar_guling_line_po_all_users,tukar.guling.line.po.all.users,model_tukar_guling_line_po,base.group_user,1,1,1,1 access_tukar_guling_mapping_koli_all_users,tukar.guling.mapping.koli.all.users,model_tukar_guling_mapping_koli,base.group_user,1,1,1,1 -access_purchase_order_update_date_wizard,access.purchase.order.update.date.wizard,model_purchase_order_update_date_wizard,base.group_user,1,1,1,1 access_sync_promise_date_wizard,access.sync.promise.date.wizard,model_sync_promise_date_wizard,base.group_user,1,1,1,1 access_sync_promise_date_wizard_line,access.sync.promise.date.wizard.line,model_sync_promise_date_wizard_line,base.group_user,1,1,1,1 access_change_date_planned_wizard,access.change.date.planned.wizard,model_change_date_planned_wizard,,1,1,1,1 -- cgit v1.2.3 From 491da856fd2e663fb2560d56f3bc596f0197acee Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Tue, 16 Sep 2025 17:14:44 +0700 Subject: push --- indoteknik_custom/security/ir.model.access.csv | 2 -- 1 file changed, 2 deletions(-) diff --git a/indoteknik_custom/security/ir.model.access.csv b/indoteknik_custom/security/ir.model.access.csv index 423fe138..3325e894 100755 --- a/indoteknik_custom/security/ir.model.access.csv +++ b/indoteknik_custom/security/ir.model.access.csv @@ -187,8 +187,6 @@ access_purchase_order_update_date_wizard,access.purchase.order.update.date.wizar access_change_date_planned_wizard,access.change.date.planned.wizard,model_change_date_planned_wizard,,1,1,1,1 access_refund_sale_order,access.refund.sale.order,model_refund_sale_order,base.group_user,1,1,1,1 access_refund_sale_order_line,access.refund.sale.order.line,model_refund_sale_order_line,base.group_user,1,1,1,1 -access_reimburse,access.reimburse,model_reimburse,,1,1,1,1 -access_reimburse_line,access.reimburse.line,model_reimburse_line,,1,1,1,1 access_purchasing_job_seen,purchasing.job.seen,model_purchasing_job_seen,,1,1,1,1 -- cgit v1.2.3 From 4e8e3a2e287c8c78a9aef72f216211b41f3d5bca Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Tue, 16 Sep 2025 17:16:48 +0700 Subject: push --- indoteknik_custom/views/report_logbook_sj.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/indoteknik_custom/views/report_logbook_sj.xml b/indoteknik_custom/views/report_logbook_sj.xml index 14bfecfb..46260cd5 100644 --- a/indoteknik_custom/views/report_logbook_sj.xml +++ b/indoteknik_custom/views/report_logbook_sj.xml @@ -46,7 +46,6 @@
-- cgit v1.2.3 From 57ed1cd4179c2b578dd966b1105011709d0b3e4c Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Tue, 16 Sep 2025 17:20:22 +0700 Subject: push --- indoteknik_custom/report/purchase_report.xml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/indoteknik_custom/report/purchase_report.xml b/indoteknik_custom/report/purchase_report.xml index bf5006ec..150b7af2 100644 --- a/indoteknik_custom/report/purchase_report.xml +++ b/indoteknik_custom/report/purchase_report.xml @@ -61,9 +61,8 @@
No. & DescriptionImage Quantity Unit Price Taxes - - - -
N/A @@ -111,6 +107,12 @@
+ + -- cgit v1.2.3 From 4f5ecec0221d49b2626582438acd5b90d15c21b3 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Mon, 15 Sep 2025 15:47:27 +0700 Subject: push --- indoteknik_custom/report/purchase_report.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/indoteknik_custom/report/purchase_report.xml b/indoteknik_custom/report/purchase_report.xml index 4e1e7afb..6666235a 100644 --- a/indoteknik_custom/report/purchase_report.xml +++ b/indoteknik_custom/report/purchase_report.xml @@ -110,7 +110,7 @@ + style="width:100px; height:100px; object-fit:contain; border:1px solid #ddd; border-radius:6px; background:#fff;"/>
+
- -
- N/A -
-
-
@@ -135,9 +129,9 @@
+
Alamat Pengiriman
PT Indoteknik (Bandengan 1 Depan)
- Jl. Bandengan Utara Komp A 8 B
+ Jl. Bandengan Utara No. 89, RT 003
RT. Penjaringan, Kec. Penjaringan, Jakarta (BELAKANG INDOMARET)
JK 14440 - Indonesia
- - -- cgit v1.2.3 From 19a286c49f2ae626d9d6c12829d7bc094ba563b2 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Tue, 16 Sep 2025 14:13:10 +0700 Subject: push --- indoteknik_custom/models/purchase_order.py | 14 ++++++++++++++ indoteknik_custom/views/purchase_order.xml | 3 ++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/indoteknik_custom/models/purchase_order.py b/indoteknik_custom/models/purchase_order.py index 4636c243..e7e5c382 100755 --- a/indoteknik_custom/models/purchase_order.py +++ b/indoteknik_custom/models/purchase_order.py @@ -6,6 +6,7 @@ import logging from pytz import timezone, utc import io import base64 +from odoo.tools import lazy_property try: from odoo.tools.misc import xlsxwriter except ImportError: @@ -115,6 +116,19 @@ class PurchaseOrder(models.Model): compute='_compute_complete_bu_in_count' ) + show_description = fields.Boolean( + string='Show Description' + ) + + @api.onchange('show_description') + def onchange_show_description(self): + if self.show_description == True: + for line in self.order_line: + line.show_description = True + else: + for line in self.order_line: + line.show_description = False + def _compute_complete_bu_in_count(self): for order in self: if order.state not in ['done', 'cancel']: diff --git a/indoteknik_custom/views/purchase_order.xml b/indoteknik_custom/views/purchase_order.xml index a3a5e05c..a0ac9824 100755 --- a/indoteknik_custom/views/purchase_order.xml +++ b/indoteknik_custom/views/purchase_order.xml @@ -99,6 +99,7 @@ + @@ -112,7 +113,7 @@ - + {'no_create': True} -- cgit v1.2.3 From 9e6ab83ccd890c2ddd4e74cc0ed650d35a12f31e Mon Sep 17 00:00:00 2001 From: it-fixcomart Date: Tue, 16 Sep 2025 16:18:24 +0700 Subject: journal payment tempo --- indoteknik_custom/models/refund_sale_order.py | 118 +++++++++++++++++++++----- indoteknik_custom/models/sale_order.py | 22 ++++- 2 files changed, 117 insertions(+), 23 deletions(-) diff --git a/indoteknik_custom/models/refund_sale_order.py b/indoteknik_custom/models/refund_sale_order.py index 55128080..4ee76006 100644 --- a/indoteknik_custom/models/refund_sale_order.py +++ b/indoteknik_custom/models/refund_sale_order.py @@ -113,7 +113,7 @@ class RefundSaleOrder(models.Model): string='Customer', required=True ) - advance_move_names = fields.Html(string="Group Journal SO", compute="_compute_advance_move_names") + advance_move_names = fields.Html(string="Group Journal Payment", compute="_compute_advance_move_names") uang_masuk_type = fields.Selection([ ('pdf', 'PDF'), ('image', 'Image'), @@ -237,6 +237,7 @@ class RefundSaleOrder(models.Model): refund_type = vals.get('refund_type') 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']: raise UserError("Refund type Hanya Bisa Lebih Bayar, Barang Kosong Sebagian, atau Retur jika ada invoice") @@ -276,18 +277,46 @@ class RefundSaleOrder(models.Model): ('journal_id', '=', 11), ('state', '=', 'posted'), ]) - total_uang_muka = sum(moves.mapped('amount_total_signed')) if moves else 0.0 - total_midtrans = sum(self.env['sale.order'].browse(so_ids).mapped('gross_amount')) if so_ids else 0.0 - total_pembayaran = total_uang_muka + total_midtrans + piutangbca = self.env['account.move'].search([ + ('ref', 'in', invoices.mapped('name')), + ('journal_id', '=', 4), + ('state', '=', 'posted'), + ]) + piutangmdr = self.env['account.move'].search([ + ('ref', 'in', invoices.mapped('name')), + ('journal_id', '=', 7), + ('state', '=', 'posted'), + ]) + has_moves = bool(moves) + has_piutangmdr = bool(piutangmdr) + has_piutangbca = bool(piutangbca) + ssos = self.env['sale.order'].browse(so_ids) + has_settlement = any(so.payment_status == 'settlement' for so in ssos) + + sisa_uang_masuk = 0.0 + if has_moves and has_settlement: + sisa_uang_masuk = sum(moves.mapped('amount_total_signed')) + sum(ssos.mapped('gross_amount')) + elif has_moves: + sisa_uang_masuk = sum(moves.mapped('amount_total_signed')) + elif has_settlement: + sisa_uang_masuk = sum(ssos.mapped('gross_amount')) + elif has_piutangbca: + sisa_uang_masuk = sum(piutangbca.mapped('amount_total_signed')) + elif has_piutangmdr: + sisa_uang_masuk = sum(piutangmdr.mapped('amount_total_signed')) + else: + raise UserError( + "❌ Tidak bisa melakukan refund karena SO tidak memiliki Record Uang Masuk " + "(Journal Uang Muka / Payment Invoices / Midtrans Payment)." + ) + existing_refunds = self.env['refund.sale.order'].search([ ('sale_order_ids', 'in', so_ids) ], order='id desc', limit=1) if existing_refunds: sisa_uang_masuk = existing_refunds.remaining_refundable - else: - sisa_uang_masuk = total_pembayaran if sisa_uang_masuk < 0: raise UserError("❌ Tidak ada sisa transaksi untuk di-refund.") @@ -452,15 +481,34 @@ class RefundSaleOrder(models.Model): def _compute_advance_move_names(self): for rec in self: move_links = [] + + invoice_ids = rec.sale_order_ids.mapped('invoice_ids') + moves = self.env['account.move'].search([ ('sale_id', 'in', rec.sale_order_ids.ids), ('journal_id', '=', 11), - ('state', '=', 'posted') + ('state', '=', 'posted'), ]) - for move in moves: + + piutangbca = self.env['account.move'].search([ + ('ref', 'in', invoice_ids.mapped('name')), + ('journal_id', '=', 4), + ('state', '=', 'posted'), + ]) + + piutangmdr = self.env['account.move'].search([ + ('ref', 'in', invoice_ids.mapped('name')), + ('journal_id', '=', 7), + ('state', '=', 'posted'), + ]) + + all_moves = moves | piutangbca | piutangmdr + + for move in all_moves: url = f"/web#id={move.id}&model=account.move&view_type=form" name = html_escape(move.name or 'Unnamed') move_links.append(f'{name}') + rec.advance_move_names = ', '.join(move_links) if move_links else "-" @api.depends('sale_order_ids.user_id') @@ -496,9 +544,35 @@ class RefundSaleOrder(models.Model): ('journal_id', '=', 11), ('state', '=', 'posted'), ]) - total_uang_muka = sum(moves.mapped('amount_total_signed')) if moves else 0.0 - total_midtrans = sum(self.env['sale.order'].browse(so_ids).mapped('gross_amount')) if so_ids else 0.0 - self.uang_masuk = (total_uang_muka + total_midtrans) - amount_refund_before + piutangbca = self.env['account.move'].search([ + ('ref', 'in', all_invoices.mapped('name')), + ('journal_id', '=', 4), + ('state', '=', 'posted'), + ]) + piutangmdr = self.env['account.move'].search([ + ('ref', 'in', all_invoices.mapped('name')), + ('journal_id', '=', 7), + ('state', '=', 'posted'), + ]) + has_moves = bool(moves) + has_piutangmdr = bool(piutangmdr) + has_piutangbca = bool(piutangbca) + ssos = self.env['sale.order'].browse(so_ids) + has_settlement = any(so.payment_status == 'settlement' for so in ssos) + + sisa_uang_masuk = 0.0 + if has_moves and has_settlement: + sisa_uang_masuk = sum(moves.mapped('amount_total_signed')) + sum(ssos.mapped('gross_amount')) + elif has_moves: + sisa_uang_masuk = sum(moves.mapped('amount_total_signed')) + elif has_settlement: + sisa_uang_masuk = sum(ssos.mapped('gross_amount')) + elif has_piutangbca: + sisa_uang_masuk = sum(piutangbca.mapped('amount_total_signed')) + elif has_piutangmdr: + sisa_uang_masuk = sum(piutangmdr.mapped('amount_total_signed')) + + self.uang_masuk = sisa_uang_masuk - amount_refund_before self.invoice_ids = all_invoices @@ -519,7 +593,6 @@ class RefundSaleOrder(models.Model): """ Validasi SO harus punya uang masuk (Journal Uang Muka / Midtrans) """ for rec in self: invalid_orders = [] - total_uang_masuk = 0.0 for so in rec.sale_order_ids: # cari journal uang muka @@ -528,21 +601,24 @@ class RefundSaleOrder(models.Model): ('journal_id', '=', 11), # Journal Uang Muka ('state', '=', 'posted'), ]) + piutangbca = self.env['account.move'].search([ + ('ref', 'in', rec.invoice_ids.mapped('name')), + ('journal_id', '=', 4), + ('state', '=', 'posted'), + ]) + piutangmdr = self.env['account.move'].search([ + ('ref', 'in', rec.invoice_ids.mapped('name')), + ('journal_id', '=', 7), + ('state', '=', 'posted'), + ]) - if not moves and so.payment_status != 'settlement': + if not moves and so.payment_status != 'settlement' and not piutangbca and not piutangmdr: invalid_orders.append(so.name) - if moves: - total_uang_muka = sum(moves.mapped('amount_total_signed')) or 0.0 - total_uang_masuk += total_uang_muka - else: - # fallback Midtrans gross_amount - total_uang_masuk += so.gross_amount or 0.0 - if invalid_orders: raise ValidationError( f"Tidak dapat membuat refund untuk SO {', '.join(invalid_orders)} " - "karena tidak memiliki Record Uang Masuk (Journal Uang Muka/Midtrans).\n" + "karena tidak memiliki Record Uang Masuk (Journal Uang Muka/Payment Invoice/Midtrans).\n" "Pastikan semua SO yang dipilih sudah memiliki Record pembayaran yang valid." ) diff --git a/indoteknik_custom/models/sale_order.py b/indoteknik_custom/models/sale_order.py index 76d4d7e7..9cdd9a7b 100755 --- a/indoteknik_custom/models/sale_order.py +++ b/indoteknik_custom/models/sale_order.py @@ -3306,16 +3306,31 @@ class SaleOrder(models.Model): f"❌ SO {self.name} Belum melakukan kirim barang " f"({', '.join(not_done_pickings.mapped('name'))}). Selesaikan Pengiriman untuk melakukan refund." ) + + invoice_ids = self.invoice_ids.filtered(lambda inv: inv.state != 'cancel') + moves = self.env['account.move'].search([ ('sale_id', '=', self.id), ('journal_id', '=', 11), ('state', '=', 'posted'), ]) + piutangbca = self.env['account.move'].search([ + ('ref', 'in', invoice_ids.mapped('name')), + ('journal_id', '=', 4), + ('state', '=', 'posted'), + ]) + piutangmdr = self.env['account.move'].search([ + ('ref', 'in', invoice_ids.mapped('name')), + ('journal_id', '=', 7), + ('state', '=', 'posted'), + ]) # Default 0 total_uang_muka = 0.0 has_moves = bool(moves) + has_piutangmdr = bool(piutangmdr) + has_piutangbca = bool(piutangbca) has_settlement = self.payment_status == 'settlement' if has_moves and has_settlement: @@ -3324,12 +3339,15 @@ class SaleOrder(models.Model): total_uang_muka = sum(moves.mapped('amount_total_signed')) elif has_settlement: total_uang_muka = self.gross_amount + elif has_piutangbca: + total_uang_muka = sum(piutangbca.mapped('amount_total_signed')) + elif has_piutangmdr: + total_uang_muka = sum(piutangmdr.mapped('amount_total_signed')) else: raise UserError( "Tidak bisa melakukan refund karena SO tidak memiliki Record Uang Masuk " - "(Journal Uang Muka/Midtrans Payment)." + "(Journal Uang Muka/Payment Invoices/Midtrans Payment)." ) - invoice_ids = self.invoice_ids.filtered(lambda inv: inv.state != 'cancel') total_refunded = sum(self.refund_ids.mapped('amount_refund')) sisa_uang_muka = total_uang_muka - total_refunded -- cgit v1.2.3 From 89f5ec71ff2de871e596967e82b5d49a433851ca Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Tue, 16 Sep 2025 17:07:27 +0700 Subject: push --- indoteknik_custom/report/purchase_report.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/indoteknik_custom/report/purchase_report.xml b/indoteknik_custom/report/purchase_report.xml index d0b73118..bf5006ec 100644 --- a/indoteknik_custom/report/purchase_report.xml +++ b/indoteknik_custom/report/purchase_report.xml @@ -60,8 +60,8 @@
Alamat Pengiriman
- PT Indoteknik (Bandengan 1 Depan)
- Jl. Bandengan Utara No. 89, RT 003
+ PT. Indoteknik Dotcom Gemilang
+ Jl. Bandengan Utara 85A No.8-9, RT.3/RW.16
RT. Penjaringan, Kec. Penjaringan, Jakarta (BELAKANG INDOMARET)
JK 14440 - Indonesia
Alamat Pengiriman
PT. Indoteknik Dotcom Gemilang
- Jl. Bandengan Utara 85A No.8-9, RT.3/RW.16
- RT. Penjaringan, Kec. Penjaringan, Jakarta (BELAKANG INDOMARET)
- JK 14440 - Indonesia + Jl. Bandengan Utara Raya No. 85A, 8-9 RT.3/RW.16, Penjaringan, Kecamatan Penjaringan, Jkt Utara
+ Daerah Khusus Ibukota Jakarta 14440
Nama Vendor
-- cgit v1.2.3 From 6791235591714e4ac45a6729409716bcba9e8fea Mon Sep 17 00:00:00 2001 From: Miqdad Date: Tue, 16 Sep 2025 21:31:42 +0700 Subject: add try in get tracking detail stock picking --- indoteknik_custom/models/stock_picking.py | 50 ++++++++++++++++++------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/indoteknik_custom/models/stock_picking.py b/indoteknik_custom/models/stock_picking.py index a48e0ed1..78a49ee4 100644 --- a/indoteknik_custom/models/stock_picking.py +++ b/indoteknik_custom/models/stock_picking.py @@ -1743,27 +1743,37 @@ class StockPicking(models.Model): } if self.biteship_id: - histori = self.get_manifest_biteship() - day_start = order.estimated_arrival_days_start - day_end = order.estimated_arrival_days - if sale_order_delay: - if sale_order_delay.status == 'delayed': - day_start = day_start + sale_order_delay.days_delayed - day_end = day_end + sale_order_delay.days_delayed - elif sale_order_delay.status == 'early': - day_start = day_start - sale_order_delay.days_delayed - day_end = day_end - sale_order_delay.days_delayed - - eta_start = order.date_order + timedelta(days=day_start) - eta_end = order.date_order + timedelta(days=day_end) - formatted_eta = f"{eta_start.strftime('%d %b')} - {eta_end.strftime('%d %b %Y')}" - response['eta'] = formatted_eta - response['manifests'] = histori.get("manifests", []) - response['delivered'] = histori.get("delivered", - False) or self.sj_return_date != False or self.driver_arrival_date != False - response['status'] = self._map_status_biteship(histori.get("delivered")) + try: + histori = self.get_manifest_biteship() + day_start = order.estimated_arrival_days_start + day_end = order.estimated_arrival_days + if sale_order_delay: + if sale_order_delay.status == 'delayed': + day_start += sale_order_delay.days_delayed + day_end += sale_order_delay.days_delayed + elif sale_order_delay.status == 'early': + day_start -= sale_order_delay.days_delayed + day_end -= sale_order_delay.days_delayed + + eta_start = order.date_order + timedelta(days=day_start) + eta_end = order.date_order + timedelta(days=day_end) + formatted_eta = f"{eta_start.strftime('%d %b')} - {eta_end.strftime('%d %b %Y')}" + + response['eta'] = formatted_eta + response['manifests'] = histori.get("manifests", []) + response['delivered'] = ( + histori.get("delivered", False) + or self.sj_return_date != False + or self.driver_arrival_date != False + ) + response['status'] = self._map_status_biteship(histori.get("delivered")) - return response + return response + + except Exception as e: + # Kalau ada error di biteship, log dan fallback ke Odoo + _logger.warning("Biteship error pada DO %s: %s", self.name, str(e)) + # biarkan lanjut ke kondisi di bawah (pakai Odoo waybill_id) if not self.waybill_id or len(self.waybill_id.manifest_ids) == 0: response['delivered'] = self.sj_return_date != False or self.driver_arrival_date != False -- cgit v1.2.3