summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indoteknik_custom/models/sourcing_job_order.py304
-rw-r--r--indoteknik_custom/models/users.py1
-rw-r--r--indoteknik_custom/views/users.xml1
3 files changed, 210 insertions, 96 deletions
diff --git a/indoteknik_custom/models/sourcing_job_order.py b/indoteknik_custom/models/sourcing_job_order.py
index ce0bc4ec..66d03703 100644
--- a/indoteknik_custom/models/sourcing_job_order.py
+++ b/indoteknik_custom/models/sourcing_job_order.py
@@ -8,6 +8,7 @@ from pytz import timezone
import base64
import xlrd, xlwt
import io
+from collections import defaultdict
_logger = logging.getLogger(__name__)
@@ -259,6 +260,52 @@ class SourcingJobOrder(models.Model):
}
}
+ def action_send_untaken_to_telegram(self):
+ bot_sjo = '8335015210:AAGbObP0jQf7ptyqJhYdBYn5Rm0CWOd_yIM'
+ chat_group_sjo = '-5081839952'
+ # chat_group_sjo = '-5147961921'
+ api_base = f'https://api.telegram.org/bot{bot_sjo}'
+
+ lines = self.env['sourcing.job.order.line'].search(
+ [('state', '=', 'draft')],
+ order='create_date asc'
+ )
+
+ if not lines:
+ text = "✅ Tidak ada Sourcing Job Line yang berstatus Untaken saat ini."
+ else:
+ text = "⚠️ *Daftar SJO Line yang masih Untaken:*\n\n"
+
+ line_counter = defaultdict(int)
+
+ for line in lines:
+ sjo_id = line.order_id.id
+ line_counter[sjo_id] += 1
+
+ sjo_number = line.order_id.name if line.order_id else '-'
+ line_no = line_no = line_counter[sjo_id]
+ product_name = line.product_name or '-'
+ salesperson = line.show_salesperson.user_id.name if line.show_salesperson.user_id else '-'
+
+ text += f"{sjo_number} | Line {line_no} | {product_name} | {salesperson}\n"
+
+ payload = {
+ 'chat_id': chat_group_sjo,
+ 'text': text,
+ 'parse_mode': 'Markdown'
+ }
+
+ try:
+ response = requests.post(f"{api_base}/sendMessage", data=payload, timeout=20)
+ if response.status_code == 200:
+ _logger.info("✅ Telegram notification sent successfully")
+ else:
+ _logger.error(f"❌ Failed to send Telegram message: {response.text}")
+ except Exception as e:
+ _logger.error(f"⚠️ Error while sending Telegram message: {str(e)}")
+
+ return True
+
class SourcingJobOrderLine(models.Model):
_name = 'sourcing.job.order.line'
@@ -292,7 +339,7 @@ class SourcingJobOrderLine(models.Model):
descriptions = fields.Text(string='Deskripsi / Spesifikasi')
reason = fields.Text(string='Reason Unavailable')
sla = fields.Char(string='SLA Product')
- quantity = fields.Float(string='Quantity Product', required=True)
+ quantity = fields.Float(string='Quantity Product', required=True, default=1)
price = fields.Float(string='Purchase Price')
now_price = fields.Float(string='Current Purchase Price', readonly=True)
last_updated_price = fields.Datetime(string='Last Update Price', readonly=True)
@@ -525,82 +572,83 @@ class SourcingJobOrderLine(models.Model):
if rec.order_id.state != 'draft':
continue
- def action_multi_ask_approval(self):
- bot_sjo = '8335015210:AAGbObP0jQf7ptyqJhYdBYn5Rm0CWOd_yIM'
- chat_sjo = '6076436058'
- api_base = f'https://api.telegram.org/bot{bot_sjo}/sendMessage'
-
- order_ids = self.mapped('order_id')
- if len(order_ids) != 1:
- raise UserError("❌ Semua line harus berasal dari Sourcing Job yang sama.")
-
- order_ids = self.mapped('order_id')
- if len(order_ids) != 1:
- raise UserError("❌ Semua line harus berasal dari Sourcing Job yang sama.")
-
- job = order_ids[0]
-
- md_users = self.mapped('md_person_ids')
- if len(md_users) != 1 or md_users[0] != self.env.user:
- raise UserError("❌ Hanya MD yang memegang semua line ini yang bisa request approval.")
-
- for line in self:
- if line.state != 'sourcing':
- raise UserError(f"⚠️ Produk '{line.product_name_md}' bukan status Sourcing.")
-
- if (
- not line.vendor_id
- or not line.product_name_md
- or not brand_id
- or not line.price or line.price <= 0
- or not line.tax_id
- or not line.subtotal or line.subtotal <= 0
- or not line.product_type
- or not line.product_category
- or not line.product_class
- ):
- raise UserError(f"❌ Data produk '{line.product_name_md}' belum lengkap.")
-
- activity_type = self.env.ref('mail.mail_activity_data_todo')
-
- approved_lines_text = ""
-
- for line in self:
- line.state = 'sent'
-
- line.activity_schedule(
- activity_type_id=activity_type.id,
- user_id=job.create_uid.id,
- note=f"{self.env.user.name} meminta approval untuk produk '{line.product_name_md}' di SJO '{job.name}'.",
- )
-
- approved_lines_text += f"<li>{line.product_name_md} - {line.price or 0}</li>"
-
- line.message_post(
- body=f"📤 <b>Request approval dikirim (Multi)</b>",
- subtype_xmlid="mail.mt_comment",
- )
-
- job.message_post(
- body=(
- f"📤 <b>Multi Request Approval</b><br/>"
- f"<ul>{approved_lines_text}</ul>"
- f"<b>MD:</b> {self.env.user.name}"
- ),
- subtype_xmlid="mail.mt_comment",
- )
-
- self.env.user.notify_success(
- message=f"{len(self)} produk berhasil dikirim untuk approval.",
- title="Multi Request Sent"
- )
-
- # return {'type': 'ir.actions.client', 'tag': 'reload'}
+ # def action_multi_ask_approval(self):
+ # bot_sjo = '8335015210:AAGbObP0jQf7ptyqJhYdBYn5Rm0CWOd_yIM'
+ # chat_sjo = '6076436058'
+ # api_base = f'https://api.telegram.org/bot{bot_sjo}/sendMessage'
+
+ # order_ids = self.mapped('order_id')
+ # if len(order_ids) != 1:
+ # raise UserError("❌ Semua line harus berasal dari Sourcing Job yang sama.")
+
+ # order_ids = self.mapped('order_id')
+ # if len(order_ids) != 1:
+ # raise UserError("❌ Semua line harus berasal dari Sourcing Job yang sama.")
+
+ # job = order_ids[0]
+
+ # md_users = self.mapped('md_person_ids')
+ # if len(md_users) != 1 or md_users[0] != self.env.user:
+ # raise UserError("❌ Hanya MD yang memegang semua line ini yang bisa request approval.")
+
+ # for line in self:
+ # if line.state != 'sourcing':
+ # raise UserError(f"⚠️ Produk '{line.product_name_md}' bukan status Sourcing.")
+
+ # if (
+ # not line.vendor_id
+ # or not line.product_name_md
+ # or not brand_id
+ # or not line.price or line.price <= 0
+ # or not line.tax_id
+ # or not line.subtotal or line.subtotal <= 0
+ # or not line.product_type
+ # or not line.product_category
+ # or not line.product_class
+ # ):
+ # raise UserError(f"❌ Data produk '{line.product_name_md}' belum lengkap.")
+
+ # activity_type = self.env.ref('mail.mail_activity_data_todo')
+
+ # approved_lines_text = ""
+
+ # for line in self:
+ # line.state = 'sent'
+
+ # line.activity_schedule(
+ # activity_type_id=activity_type.id,
+ # user_id=line.show_salesperson.id,
+ # note=f"{self.env.user.name} meminta approval untuk produk '{line.product_name_md}' di SJO '{job.name}'.",
+ # )
+
+ # approved_lines_text += f"<li>{line.product_name_md} - {line.price or 0}</li>"
+
+ # line.message_post(
+ # body=f"📤 <b>Request approval dikirim (Multi)</b>",
+ # subtype_xmlid="mail.mt_comment",
+ # )
+
+ # job.message_post(
+ # body=(
+ # f"📤 <b>Multi Request Approval</b><br/>"
+ # f"<ul>{approved_lines_text}</ul>"
+ # f"<b>MD:</b> {self.env.user.name}"
+ # ),
+ # subtype_xmlid="mail.mt_comment",
+ # )
+
+ # self.env.user.notify_success(
+ # message=f"{len(self)} produk berhasil dikirim untuk approval.",
+ # title="Multi Request Sent"
+ # )
+
+ # # return {'type': 'ir.actions.client', 'tag': 'reload'}
def action_ask_approval(self):
bot_sjo = '8335015210:AAGbObP0jQf7ptyqJhYdBYn5Rm0CWOd_yIM'
- chat_sjo = '6076436058'
+ chat_sjo = self.show_salesperson.chat_id_telegram or False
+ # chat_sjo = '6076436058'
api_base = f'https://api.telegram.org/bot{bot_sjo}/sendMessage'
for line in self:
@@ -653,14 +701,14 @@ class SourcingJobOrderLine(models.Model):
line.activity_schedule(
activity_type_id=activity_type.id,
- user_id=job.create_uid.id,
+ user_id=line.show_salesperson.id,
note=f"{self.env.user.name} meminta approval untuk produk '{line.product_name_md}' di SJO '{job.name}'.",
)
line.message_post(
body=(
f"📤 <b>Request approval dikirim</b><br/>"
- f"Kepada: <b>{job.create_uid.name}</b><br/>"
+ f"Kepada: <b>{line.show_salesperson.name}</b><br/>"
f"Produk: <b>{line.product_name_md}</b>"
),
subtype_xmlid="mail.mt_comment"
@@ -680,35 +728,36 @@ class SourcingJobOrderLine(models.Model):
)
self.env.user.notify_success(
- message=f"Request approval untuk '{line.product_name_md}' dikirim ke {job.create_uid.name}",
+ message=f"Request approval untuk '{line.product_name_md}' dikirim ke {line.show_salesperson.name}",
title="Request Sent",
)
base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
url = f"{base_url}/web#id={job.id}&model=sourcing.job.order&view_type=form"
+
+ if chat_sjo:
+ try:
+ msg_text = (
+ f"📢 <b>Request Approval Produk</b>\n\n"
+ f"🧾 <b>Sourcing Job:</b> <a href='{url}'>📎 {job.name}</a>\n"
+ f"📦 <b>Produk:</b> {line.product_name_md}\n"
+ f"👤 <b>MD:</b> {self.env.user.name}\n"
+ f"💰 <b>Harga:</b> {line.price or 0}\n"
+ f"📅 <b>Tanggal:</b> {fields.Datetime.now().strftime('%d-%m-%Y %H:%M')}\n\n"
+ f"Silakan review di Odoo."
+ )
- try:
- msg_text = (
- f"📢 <b>Request Approval Produk</b>\n\n"
- f"🧾 <b>Sourcing Job:</b> <a href='{url}'>📎 {job.name}</a>\n"
- f"📦 <b>Produk:</b> {line.product_name_md}\n"
- f"👤 <b>MD:</b> {self.env.user.name}\n"
- f"💰 <b>Harga:</b> {line.price or 0}\n"
- f"📅 <b>Tanggal:</b> {fields.Datetime.now().strftime('%d-%m-%Y %H:%M')}\n\n"
- f"Silakan review di Odoo."
- )
-
- payload = {
- 'chat_id': chat_sjo,
- 'text': msg_text,
- 'parse_mode': 'HTML'
- }
+ payload = {
+ 'chat_id': chat_sjo,
+ 'text': msg_text,
+ 'parse_mode': 'HTML'
+ }
- response = requests.post(api_base, data=payload, timeout=10)
- response.raise_for_status()
+ response = requests.post(api_base, data=payload, timeout=10)
+ response.raise_for_status()
- except Exception as e:
- _logger.warning(f"Gagal kirim telegram approval line: {e}")
+ except Exception as e:
+ _logger.warning(f"Gagal kirim telegram approval line: {e}")
return {'type': 'ir.actions.client', 'tag': 'reload'}
@@ -717,6 +766,11 @@ class SourcingJobOrderLine(models.Model):
PurchasePricelist = self.env['purchase.pricelist']
SaleOrderLine = self.env['sale.order.line']
+ bot_sjo = '8335015210:AAGbObP0jQf7ptyqJhYdBYn5Rm0CWOd_yIM'
+ chat_sjo = '-5081839952'
+ # chat_sjo = '-5147961921'
+ api_base = f'https://api.telegram.org/bot{bot_sjo}/sendMessage'
+
for rec in self:
job = rec.order_id
@@ -852,6 +906,32 @@ class SourcingJobOrderLine(models.Model):
title="Approved"
)
+ base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
+ url = f"{base_url}/web#id={job.id}&model=sourcing.job.order&view_type=form"
+
+ try:
+ msg_text = (
+ f"📢 <b>✅ Sourcing Approved</b>\n\n"
+ f"🧾 <b>Sourcing Job:</b> <a href='{url}'>📎 {job.name}</a>\n"
+ f"📦 <b>Produk:</b> {rec.product_name_md}\n"
+ f"👤 <b>Approved By:</b> {rec.show_salesperson.name}\n"
+ f"👤 <b>MD:</b> {rec.md_person_ids.name}\n"
+ f"💰 <b>Harga:</b> {rec.price or 0}\n"
+ f"📅 <b>Tanggal:</b> {fields.Datetime.now().strftime('%d-%m-%Y %H:%M')}\n\n"
+ )
+
+ payload = {
+ 'chat_id': chat_sjo,
+ 'text': msg_text,
+ 'parse_mode': 'HTML'
+ }
+
+ response = requests.post(api_base, data=payload, timeout=10)
+ response.raise_for_status()
+
+ except Exception as e:
+ _logger.warning(f"Gagal kirim telegram approved line: {e}")
+
so = self.mapped('so_id')[:1]
if so:
return {
@@ -1524,11 +1604,42 @@ class SourcingRejectWizard(models.TransientModel):
def action_confirm_reject(self):
self.ensure_one()
+ bot_sjo = '8335015210:AAGbObP0jQf7ptyqJhYdBYn5Rm0CWOd_yIM'
+ chat_sjo = '-5081839952'
+ api_base = f'https://api.telegram.org/bot{bot_sjo}/sendMessage'
+
line = self.line_id
job = line.order_id
line.state = 'sourcing'
+ base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
+ url = f"{base_url}/web#id={job.id}&model=sourcing.job.order&view_type=form"
+
+ try:
+ msg_text = (
+ f"🚫 <b>Approval Sourcing Ditolak</b>\n\n"
+ f"🧾 <b>Sourcing Job:</b> <a href='{url}'>📎 {job.name}</a>\n"
+ f"📦 <b>Produk:</b> {line.product_name}\n"
+ f"👤 <b>Sales:</b> {line.show_salesperson.name if line.show_salesperson else '-'}\n"
+ f"👤 <b>MD:</b> {line.md_person_ids.name if line.md_person_ids else '-'}\n"
+ f"❌ <b>Ditolak Oleh:</b> {self.env.user.name}\n"
+ f"📝 <b>Alasan Reject:</b>\n{self.reason}\n\n"
+ f"📅 <b>Tanggal:</b> {fields.Datetime.now().strftime('%d-%m-%Y %H:%M')}"
+ )
+
+ payload = {
+ 'chat_id': chat_sjo,
+ 'text': msg_text,
+ 'parse_mode': 'HTML'
+ }
+
+ response = requests.post(api_base, data=payload, timeout=10)
+ response.raise_for_status()
+
+ except Exception as e:
+ _logger.warning(f"Gagal kirim telegram reject line: {e}")
+
activities = self.env['mail.activity'].search([
('res_model', '=', line._name),
('res_id', '=', line.id),
@@ -1599,4 +1710,5 @@ class ReopenCancelLineWizard(models.TransientModel):
line.write({
'state': 'draft',
'md_person_ids': False,
+ 'reason': False,
}) \ No newline at end of file
diff --git a/indoteknik_custom/models/users.py b/indoteknik_custom/models/users.py
index d95b56e7..f646c75b 100644
--- a/indoteknik_custom/models/users.py
+++ b/indoteknik_custom/models/users.py
@@ -14,6 +14,7 @@ class Users(models.Model):
is_admin_reconcile = fields.Boolean(string='Admin Reconcile', help='Berhak Mengedit Journal Reconcile')
is_inbound = fields.Boolean(string='Operator Inbound')
is_outbound = fields.Boolean(string='Operator Outbound')
+ chat_id_telegram = fields.Char(string='ChatId Telegram')
def notify_internal_users(self, message, title):
users = self.search([('share', '=', False)])
diff --git a/indoteknik_custom/views/users.xml b/indoteknik_custom/views/users.xml
index 6519aeaa..13561e2b 100644
--- a/indoteknik_custom/views/users.xml
+++ b/indoteknik_custom/views/users.xml
@@ -16,6 +16,7 @@
<field name="is_admin_reconcile"/>
<field name="is_outbound"/>
<field name="is_inbound"/>
+ <field name="chat_id_telegram" groups="indoteknik_custom.group_role_it"/>
</field>
</field>
</record>