Files
poa-pds/test.py
2025-08-06 12:24:45 +05:30

916 lines
42 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import sys
import requests
from PyQt6.QtWidgets import (
QApplication, QWidget, QVBoxLayout, QLabel, QLineEdit, QPushButton,
QHBoxLayout, QStackedWidget, QCheckBox, QTextEdit
)
from PyQt6.QtGui import QPixmap, QFont
from PyQt6.QtCore import Qt, QDateTime, QDate
# --- Login Screen ---
class LoginScreen(QWidget):
def __init__(self, stacked):
super().__init__()
self.stacked = stacked
self.init_ui()
def init_ui(self):
layout = QVBoxLayout()
logo = QLabel()
logo.setPixmap(QPixmap(
r'C:\Users\Administrator\Downloads\sfg printing\backup from airline device\SRIMATHI\cri_logo.png.png'
).scaled(100, 100, Qt.AspectRatioMode.KeepAspectRatio))
logo.setAlignment(Qt.AlignmentFlag.AlignCenter)
layout.addWidget(logo)
title_label = QLabel("Login Screen")
title_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
title_label.setStyleSheet("font-size: 18px; font-weight: bold; color: #002244; margin-bottom: 10px;")
layout.addWidget(title_label)
self.username = QLineEdit()
self.username.setPlaceholderText("Username")
layout.addWidget(self.username)
pw_layout = QHBoxLayout()
self.password = QLineEdit()
self.password.setPlaceholderText("Password")
self.password.setEchoMode(QLineEdit.EchoMode.Password)
pw_layout.addWidget(self.password)
self.eye_toggle = QCheckBox("Show")
self.eye_toggle.toggled.connect(lambda checked: self.password.setEchoMode(
QLineEdit.EchoMode.Normal if checked else QLineEdit.EchoMode.Password))
pw_layout.addWidget(self.eye_toggle)
layout.addLayout(pw_layout)
self.username.returnPressed.connect(self.password.setFocus)
self.password.returnPressed.connect(self.do_login)
login_btn = QPushButton("Login")
login_btn.clicked.connect(self.do_login)
layout.addWidget(login_btn)
logo2 = QLabel()
logo2.setPixmap(QPixmap(
r'C:\Users\Administrator\Downloads\sfg printing\backup from airline device\SRIMATHI\cri_farm_banner.jpg'
).scaled(200, 200, Qt.AspectRatioMode.KeepAspectRatio))
logo2.setAlignment(Qt.AlignmentFlag.AlignCenter)
layout.addWidget(logo2)
self.setLayout(layout)
def do_login(self):
if self.username.text() and self.password.text():
self.stacked.setCurrentIndex(1)
# --- Module Selector ---
class SelectorScreen(QWidget):
def __init__(self, stacked, bot_screen):
super().__init__()
self.stacked = stacked
self.bot_screen = bot_screen
self.init_ui()
self.load_module_list()
def init_ui(self):
self.layout = QVBoxLayout()
title_label = QLabel("Selector Screen")
title_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
title_label.setStyleSheet("font-size: 18px; font-weight: bold; color: #002244;")
self.layout.addWidget(title_label)
date_label = QLabel(QDate.currentDate().toString("dddd, MMMM d, yyyy"))
date_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
date_label.setFont(QFont("Arial", 14, QFont.Weight.Bold))
self.layout.addWidget(date_label)
self.button_container = QVBoxLayout()
self.layout.addLayout(self.button_container)
self.setLayout(self.layout)
def load_module_list(self):
url = 'https://pds.iotsignin.com/api/get/module-name/data'
headers = {
"Authorization": "Bearer sb-eba140ab-74bb-44a4-8d92-70a636940def!b1182|it-rt-dev-cri-stjllphr!b68:616d8991-307b-4ab1-be37-7894a8c6db9d$0p0fE2I7w1Ve23-lVSKQF0ka3mKrTVcKPJYELr-i4nE=",
"module-name": "Module List"
}
try:
response = requests.get(url, headers=headers, timeout=10)
if response.status_code == 200:
data = response.json()
for module in data.get("status_description", []):
self.add_module_button(module)
else:
self.show_error(f"Failed to load modules: {response.status_code}")
except Exception as e:
self.show_error(str(e))
def add_module_button(self, module_name):
btn = QPushButton(module_name)
btn.setStyleSheet(
"padding: 10px; background-color: #c2185b; color: white; font-size: 14px; border-radius: 8px;")
btn.clicked.connect(lambda _, name=module_name: self.goto_bot_screen(name))
self.button_container.addWidget(btn)
def show_error(self, msg):
error = QLabel(f"{msg}")
error.setStyleSheet("color: red;")
self.layout.addWidget(error)
def goto_bot_screen(self, module_name):
self.bot_screen.set_module_name(module_name)
self.stacked.setCurrentIndex(2)
# --- BotScreen: full chat-driven selection ---
class BotScreen(QWidget):
def __init__(self, stacked):
super().__init__()
self.stacked = stacked
self.module_name = ""
self.charts = []
self.plants = []
self.lines = []
self.filters = []
self.invoice_types = []
self.awaiting_chart_choice = False
self.awaiting_plant_choice = False
self.awaiting_line_choice = False
self.awaiting_order_input = False
self.awaiting_filter_choice = False
self.awaiting_invoice_choice = False
self.selected_chart = None
self.selected_plant = None
self.selected_line = None
self.selected_order = None
self.selected_filter = None
self.selected_invoice_type = None
self.init_ui()
def set_module_name(self, name):
self.module_name = name
self.clear_chat()
self.load_chart_data()
def init_ui(self):
main_layout = QVBoxLayout()
top_bar = QHBoxLayout()
logo = QLabel()
logo.setPixmap(QPixmap(
r'C:\Users\Administrator\Downloads\sfg printing\backup from airline device\SRIMATHI\cri_logo.png.png'
).scaled(40, 40, Qt.AspectRatioMode.KeepAspectRatio))
top_bar.addWidget(logo)
title = QLabel("CRI DIGITAL MANUFACTURING SOLUTIONS \n CRI BOT ASSISTANT")
title.setStyleSheet("font-size: 16px; font-weight: bold; color: black; padding: 10px; border-radius: 8px;")
top_bar.addWidget(title)
top_bar.addStretch()
back_btn = QPushButton("Back")
back_btn.clicked.connect(self.go_back)
top_bar.addWidget(back_btn)
refresh_btn = QPushButton("Refresh")
refresh_btn.clicked.connect(self.load_chart_data)
top_bar.addWidget(refresh_btn)
main_layout.addLayout(top_bar)
self.chart_info = QLabel("Waiting for chart data...")
self.chart_info.setWordWrap(True)
self.chart_info.setStyleSheet(
"background: white; color: black; font-size: 15px; padding: 14px; border-radius: 10px")
main_layout.addWidget(self.chart_info)
self.chat_area = QTextEdit()
self.chat_area.setReadOnly(True)
self.chat_area.setStyleSheet("background-color: white; color: black; padding: 10px; font-size: 14px;")
main_layout.addWidget(self.chat_area)
input_layout = QHBoxLayout()
self.user_input = QLineEdit()
self.user_input.setPlaceholderText("Type a number to select...")
input_layout.addWidget(self.user_input)
send_btn = QPushButton("Send")
send_btn.setStyleSheet(
"padding: 8px; background: #2e7d32; color: white; border-radius: 8px;")
send_btn.clicked.connect(self.send_message)
input_layout.addWidget(send_btn)
main_layout.addLayout(input_layout)
self.setLayout(main_layout)
def load_chart_data(self):
self.chart_info.setText("Loading chart data...")
url = 'https://pds.iotsignin.com/api/get/modulechart-name/data'
headers = {
"Authorization": "Bearer sb-eba140ab-74bb-44a4-8d92-70a636940def!b1182|it-rt-dev-cri-stjllphr!b68:616d8991-307b-4ab1-be37-7894a8c6db9d$0p0fE2I7w1Ve23-lVSKQF0ka3mKrTVcKPJYELr-i4nE=",
"module-name": self.module_name
}
try:
response = requests.get(url, headers=headers, timeout=10)
data = response.json()
status = data.get("status_code", "UNKNOWN")
desc = data.get("status_description", [])
self.chart_info.setText(f"API Status: {status}")
self.chat_area.append(f"<b>HTTP:</b> {response.status_code}")
self.chat_area.append(f"<b>Bot Module:</b> {self.module_name}")
if isinstance(desc, list) and desc:
self.charts = desc
else:
self.charts = [
"Production Line Count",
"Production Hourly Count",
"Production Line Stop Count",
"Production Order Count"
]
self.awaiting_chart_choice = True
self.show_choice_menu("chart", self.charts)
except Exception as e:
self.chart_info.setText("Failed to load chart data.")
self.chat_area.append(f"<b>Bot:</b> Error: {e}")
def show_choice_menu(self, item, items_list):
label_map = {
"chart": "chart",
"plant": "plant",
"line": "line",
"order": "production order",
"filter": "date filter",
"invoice": "invoice type",
}
# Ensure name extraction works for both simple str and dict/list cases.
lines = [
f"{i + 1}. {item_name['name'] if isinstance(item_name, dict) and 'name' in item_name else str(item_name)}"
for i, item_name in enumerate(items_list)
]
menu_txt = f"<b>Bot:</b> Please select a {label_map[item]}:<br>" + "<br>".join(lines)
self.chat_area.append(menu_txt)
def send_message(self):
msg = self.user_input.text().strip()
self.user_input.clear()
# --- Chart selection ---
if self.awaiting_chart_choice:
if msg.isdigit():
idx = int(msg) - 1
if 0 <= idx < len(self.charts):
self.selected_chart = self.charts[idx]
self.awaiting_chart_choice = False
self.chat_area.append(f"<b>Bot:</b> ✅ You selected: <b>{self.selected_chart}</b>")
self.fetch_and_display_plants()
else:
self.chat_area.append(f"<b>Bot:</b> ❌ Please select a number from 1 to {len(self.charts)}.")
else:
self.chat_area.append(f"<b>Bot:</b> ❌ Please enter a number (1-{len(self.charts)}).")
return
# --- Plant selection ---
if self.awaiting_plant_choice:
if msg.isdigit():
idx = int(msg) - 1
if 0 <= idx < len(self.plants):
self.selected_plant = self.plants[idx]
self.awaiting_plant_choice = False
self.chat_area.append(f"<b>Bot:</b> ✅ You selected: <b>{self.selected_plant}</b>")
# Normalize chart name and check for invoice / invoice quantity charts explicitly
selected_chart_name = (self.selected_chart or "").strip().lower()
if selected_chart_name == "invoice":
# Fetch invoice types for regular invoice dashboard
self.fetch_and_display_invoice_types()
elif selected_chart_name == "invoice quantity":
# For invoice quantity, also fetch invoice types first (if needed)
self.fetch_and_display_invoice_types()
# Alternatively: if invoice type is fixed or selection is not needed, you can
# proceed to date filter directly by calling
# self.fetch_and_display_invoice_filters() here if your flow allows
else:
# For other charts, fetch lines normally
self.fetch_and_display_lines()
else:
self.chat_area.append(f"<b>Bot:</b> ❌ Please select a number from 1 to {len(self.plants)}.")
else:
self.chat_area.append(f"<b>Bot:</b> ❌ Please enter a number (1{len(self.plants)}).")
return
# --- Line selection ---
if self.awaiting_line_choice:
if msg.isdigit():
idx = int(msg) - 1
if 0 <= idx < len(self.lines):
self.selected_line = self.lines[idx]
self.awaiting_line_choice = False
self.chat_area.append(f"<b>Bot:</b> ✅ You selected: <b>{self.selected_line}</b>")
chart_raw = self.selected_chart
chart_normalized = chart_raw.strip().lower() if chart_raw else ""
# 🚩 Only for Chart 4 (Production Order Count)
if chart_normalized == "production order count":
print(f"[DEBUG] self.selected_chart (raw): '{self.selected_chart}'")
self.awaiting_order_input = True # Set state for next prompt
self.chat_area.append("<b>Bot:</b> Please enter the production order number:")
else:
self.fetch_and_display_filters()
else:
self.chat_area.append(f"<b>Bot:</b> ❌ Please select a number from 1 to {len(self.lines)}.")
else:
self.chat_area.append(f"<b>Bot:</b> ❌ Please enter a number (1-{len(self.lines)}).")
return
# --- Production order entry (Chart 4 only) ---
if hasattr(self, 'awaiting_order_input') and self.awaiting_order_input:
order = msg.strip()
if not order.isdigit():
self.chat_area.append("<b>Bot:</b> ❌ Please enter a valid production order number (numbers only).")
else:
self.selected_order = order
self.awaiting_order_input = False
self.chat_area.append(f"<b>Bot:</b> ✅ Production order set: <b>{self.selected_order}</b>")
self.fetch_and_display_filters()
return
#-------if MODULE 2, chart 2 then this part will execute here---------
if self.awaiting_invoice_choice:
if msg.isdigit():
idx = int(msg) - 1
if 0 <= idx < len(self.invoice_types):
self.selected_invoice_type = self.invoice_types[idx]
self.awaiting_invoice_choice = False
self.chat_area.append(
f"<b>Bot:</b> ✅ You selected invoice type: <b>{self.selected_invoice_type}</b>"
)
# Normalize selected chart to distinguish between Invoice and Invoice Quantity dashboards
selected_chart_name = (self.selected_chart or "").strip().lower()
if selected_chart_name == "invoice":
# For "Invoice" chart, fetch invoice filters (date filters)
self.fetch_and_display_invoice_filters()
elif selected_chart_name == "invoice quantity":
# For "Invoice Quantity" chart, fetch invoice filters as well
self.fetch_and_display_invoice_filters()
else:
# If future charts, handle accordingly or fallback
self.chat_area.append(
"<b>Bot:</b> ❌ Unrecognized invoice chart selected."
)
else:
self.chat_area.append(
f"<b>Bot:</b> ❌ Please select a number from 1 to {len(self.invoice_types)}."
)
else:
self.chat_area.append(
f"<b>Bot:</b> ❌ Please enter a valid number (1{len(self.invoice_types)})."
)
return
# --- Date filter selection ---
if self.awaiting_filter_choice:
if msg.isdigit():
idx = int(msg) - 1
if 0 <= idx < len(self.filters):
self.selected_filter = self.filters[idx]
self.awaiting_filter_choice = False
self.chat_area.append(f"<b>Bot:</b> ✅ You selected filter: <b>{self.selected_filter}</b>")
# Show current date/time
now = QDateTime.currentDateTime()
fmt_date = now.toString("dddd, MMMM d, yyyy, hh:mm AP")
self.chat_area.append(f"<b>Current date:</b> {fmt_date}")
selected = (self.selected_chart or "").strip().lower()
if "invoice" in selected:
# NEW: Handle invoice dashboard: no line name needed
self.fetch_and_display_invoice_production_count()
elif selected == "production hourly count":
self.fetch_and_display_hourly_count()
elif selected == "production line stop count":
self.fetch_and_display_production_line_stop_count()
elif selected == "production order count":
self.fetch_and_display_production_order_count()
elif selected == "invoice":
self.fetch_and_display_invoice_production_count()
else:
self.fetch_and_display_production_count()
else:
self.chat_area.append(f"<b>Bot:</b> ❌ Please select a number from 1 to {len(self.filters)}.")
else:
self.chat_area.append(f"<b>Bot:</b> ❌ Please enter a valid number (1{len(self.filters)}).")
return
# handle user input
def fetch_and_display_plants(self):
url = 'https://pds.iotsignin.com/api/get/moduleplant-name/data'
headers = {
"Authorization": "Bearer sb-eba140ab-74bb-44a4-8d92-70a636940def!b1182|it-rt-dev-cri-stjllphr!b68:616d8991-307b-4ab1-be37-7894a8c6db9d$0p0fE2I7w1Ve23-lVSKQF0ka3mKrTVcKPJYELr-i4nE=",
"plant-name": "Plant List"
}
try:
response = requests.get(url, headers=headers, timeout=10)
data = response.json()
if data.get("status_code") == "SUCCESS":
plants = data.get("status_description", [])
if plants:
self.plants = plants
self.awaiting_plant_choice = True
self.show_choice_menu("plant", plants)
else:
self.chat_area.append("<b>Bot:</b> ❌ No plants found.")
else:
self.chat_area.append(f"<b>Bot:</b> ❌ Error: {data.get('status_description')}")
except Exception as e:
self.chat_area.append(f"<b>Bot:</b> ❌ Failed to load plants: {e}")
def fetch_and_display_lines(self):
url = 'https://pds.iotsignin.com/api/get/module-plantline-name/data'
headers = {
"Authorization": "Bearer sb-eba140ab-74bb-44a4-8d92-70a636940def!b1182|it-rt-dev-cri-stjllphr!b68:616d8991-307b-4ab1-be37-7894a8c6db9d$0p0fE2I7w1Ve23-lVSKQF0ka3mKrTVcKPJYELr-i4nE=",
"plant-name": self.selected_plant,
"chart-name": self.selected_chart
}
try:
response = requests.get(url, headers=headers, timeout=10)
data = response.json()
if data.get("status_code") == "SUCCESS":
lines = data.get("status_description", [])
if lines:
self.lines = lines
self.awaiting_line_choice = True
self.show_choice_menu("line", lines)
else:
self.chat_area.append("<b>Bot:</b> ❌ No lines found for the selected plant.")
else:
self.chat_area.append(f"<b>Bot:</b> ❌ Error: {data.get('status_description')}")
except Exception as e:
self.chat_area.append(f"<b>Bot:</b> ❌ Failed to load lines: {e}")
def fetch_and_display_filters(self):
selected_chart_lower = (self.selected_chart or "").strip().lower()
# URL remains the same unless invoice filters come from a different path
url = 'https://pds.iotsignin.com/api/get/module-line-filter-name/data'
# Base headers
headers = {
"Authorization": self.API_TOKEN
}
# Check if its an invoice chart by partial match
if "invoice" in selected_chart_lower:
# INVOICE FLOW: Skip line name, use invoice-type
url = 'https://pds.iotsignin.com/api/get/module-invoice-filter-name/data'
headers.update({
"module-name": self.module_name,
"chart-name": self.selected_chart,
"plant-name": self.selected_plant,
"invoice-type": self.selected_invoice_type
})
else:
# PRODUCTION FLOW: Use line name as before
headers.update({
"line-name": self.selected_line
})
try:
response = requests.get(url, headers=headers, timeout=10)
data = response.json()
if data.get("status_code") == "SUCCESS":
filters = data.get("status_description", [])
if filters:
self.filters = filters
self.awaiting_filter_choice = True
self.show_choice_menu("filter", filters)
self.fetch_and_display_invoice_production_count()
else:
self.chat_area.append("<b>Bot:</b> ❌ No date filters found for your selection.")
else:
self.chat_area.append(f"<b>Bot:</b> ❌ API Error: {data.get('status_description', 'Unknown error')}")
except Exception as e:
self.chat_area.append(f"<b>Bot:</b> ❌ Failed to load date filters: {e}")
def fetch_and_display_production_count(self):
url = 'https://pds.iotsignin.com/api/get/module-filter-value/data'
headers = {
"Authorization": "Bearer sb-eba140ab-74bb-44a4-8d92-70a636940def!b1182|it-rt-dev-cri-stjllphr!b68:616d8991-307b-4ab1-be37-7894a8c6db9d$0p0fE2I7w1Ve23-lVSKQF0ka3mKrTVcKPJYELr-i4nE=",
"module-name": self.module_name,
"chart-name": self.selected_chart,
"plant-name": self.selected_plant,
"line-name": self.selected_line,
"filter-name": self.selected_filter
}
try:
response = requests.get(url, headers=headers, timeout=10)
data = response.json()
if data.get("status_code") == "SUCCESS":
result = data.get("status_description")
if isinstance(result, dict):
self.chat_area.append(f"<b>Bot:</b> 📊 <b>Production Counts (All Lines):</b>")
for ln, count in result.items():
self.chat_area.append(f"{ln}: {count}")
else:
self.chat_area.append(f"<b>Bot:</b> 📈 <b>Production Count:</b> {result}")
else:
self.chat_area.append(f"<b>Bot:</b> ❌ Error getting production count: {data.get('status_description', 'Unknown')}")
except Exception as e:
self.chat_area.append(f"<b>Bot:</b> ❌ Failed to load production count: {e}")
API_TOKEN = "Bearer sb-eba140ab-74bb-44a4-8d92-70a636940def!b1182|it-rt-dev-cri-stjllphr!b68:616d8991-307b-4ab1-be37-7894a8c6db9d$0p0fE2I7w1Ve23-lVSKQF0ka3mKrTVcKPJYELr-i4nE="
#CHART -2 PRODUCTION HOURLY COUNT
def fetch_and_display_hourly_count(self):
url = "https://pds.iotsignin.com/api/get/module-filter-value/data"
# 👇 Pass everything only via HEADERS, not params
headers = {
"Authorization": "Bearer sb-eba140ab-74bb-44a4-8d92-70a636940def!b1182|it-rt-dev-cri-stjllphr!b68:616d8991-307b-4ab1-be37-7894a8c6db9d$0p0fE2I7w1Ve23-lVSKQF0ka3mKrTVcKPJYELr-i4nE=",
"Accept": "application/json",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
"module-name": "Production Dashboard",
"chart-name": "Production Hourly Count", # ✅ Chart name as header
"plant-name": self.selected_plant, # ✅ From previous input
"line-name": self.selected_line, # ✅ From previous input
"filter-name": self.selected_filter # ✅ e.g., "Today", "Yesterday"
}
try:
response = requests.get(url, headers=headers, timeout=10)
# ✅ Print raw HTTP response to console
print("📡 [DEBUG] HTTP Status:", response.status_code)
print("📡 [DEBUG] Raw API Response:\n", response.text)
print("-" * 50) # Divider in logs
# ✅ Display raw response in chat area
self.chat_area.append(f"<b>Raw API response:</b><br><pre>{response.text}</pre>")
# 🔒 Handle empty API response
if not response.text.strip():
print("[DEBUG] ❌ Empty response received.")
self.chat_area.append("<b>Bot:</b> ❌ API returned no data.")
return
# 🔒 Try parsing JSON
try:
data = response.json()
except Exception as json_err:
print(f"[DEBUG] ❌ JSON Parse Error: {json_err}")
self.chat_area.append(f"<b>Bot:</b> ❌ Failed to parse data: {json_err}")
return
if data.get("status_code") == "SUCCESS":
now = QDateTime.currentDateTime().toString("dddd, MMMM d, yyyy, h:mm AP t")
self.chat_area.append(
f"<b>📊 Production Hourly Count ({self.selected_filter})</b><br><b>Current date:</b> {now}<br><br>")
for dataset in data.get("datasets", []):
label = dataset.get("label", "Data")
rows = ""
for lbl, val in zip(data.get("labels", []), dataset.get("data", [])):
rows += f"{lbl} ➤ <b>{val}</b><br>"
self.chat_area.append(f"<b>{label}:</b><br>{rows}")
print("[DEBUG] ✅ Hourly count displayed successfully.")
else:
req_status = data.get("status_code")
print(f"[DEBUG] ❌ API returned status {req_status}")
self.chat_area.append(f"<b>Bot:</b> ❌ API returned status <code>{req_status}</code>")
# 🔒 Specific error handling
except requests.exceptions.HTTPError as errh:
print("[DEBUG] ❌ HTTP Error:", errh)
self.chat_area.append(f"<b>Bot:</b> ❌ HTTP Error: {errh}")
except requests.exceptions.ConnectionError:
print("[DEBUG] ❌ Connection Error.")
self.chat_area.append("<b>Bot:</b> ❌ Connection error.")
except requests.exceptions.Timeout:
print("[DEBUG] ❌ Timeout Error.")
self.chat_area.append("<b>Bot:</b> ❌ Request timed out.")
except Exception as e:
print(f"[DEBUG] ❌ General Error: {e}")
self.chat_area.append(f"<b>Bot:</b> ❌ Unexpected Error: {e}")
# PRODUCTION LINE STOP DATA
def fetch_and_display_production_line_stop_count(self):
# You must have these set by prior steps:
# self.selected_plant, self.selected_line, self.selected_filter
url = "https://pds.iotsignin.com/api/get/module-production-linestop/data"
headers = {
"Authorization": "Bearer sb-eba140ab-74bb-44a4-8d92-70a636940def!b1182|it-rt-dev-cri-stjllphr!b68:616d8991-307b-4ab1-be37-7894a8c6db9d$0p0fE2I7w1Ve23-lVSKQF0ka3mKrTVcKPJYELr-i4nE=",
"module-name": "Production Dashboard",
"chart-name": "Production Line Stop",
"plant-name": self.selected_plant,
"line-name": self.selected_line,
"filter-name": self.selected_filter # Example: "Today"
}
try:
response = requests.get(url, headers=headers, timeout=10)
self.chat_area.append(f"<b>Raw API response:</b><br><pre>{response.text}</pre>")
if response.status_code != 200:
self.chat_area.append(f"<b>Bot:</b> ❌ HTTP error {response.status_code}")
return
if not response.text.strip():
self.chat_area.append(f"<b>Bot:</b> ❌ No response from API.")
return
try:
data = response.json()
except Exception as e:
self.chat_area.append(f"<b>Bot:</b> ❌ Failed to parse API response: {e}")
return
current_date = QDateTime.currentDateTime().toString("dddd, MMMM d, yyyy, h:mm AP t")
if data.get("status_code") == "SUCCESS":
labels = data.get("labels", [])
values = data.get("data", [])
message = f"<b>Production Line Stop Counts</b><br><b>Current date:</b> {current_date}<br><br>"
for label, value in zip(labels, values):
message += f"<b>{label}:</b> {value}<br>"
self.chat_area.append(message)
else:
self.chat_area.append(f"<b>Bot:</b> ❌ No data found for this selection.")
except Exception as e:
self.chat_area.append(f"<b>Bot:</b> ❌ Error fetching report: {e}")
# CHART-4 PRODUCTION ORDER COUNT
def fetch_and_display_production_order_count(self):
url = "https://pds.iotsignin.com/api/get/module-production-order/data"
headers = {
"Authorization": "Bearer sb-eba140ab-74bb-44a4-8d92-70a636940def!b1182|it-rt-dev-cri-stjllphr!b68:616d8991-307b-4ab1-be37-7894a8c6db9d$0p0fE2I7w1Ve23-lVSKQF0ka3mKrTVcKPJYELr-i4nE=",
"module-name": "Production Dashboard",
"chart-name": "Production Order Count",
"plant-name": self.selected_plant,
"line-name": self.selected_line,
"production-order": self.selected_order,
"filter-name": self.selected_filter
}
try:
response = requests.get(url, headers=headers, timeout=10)
# Print raw API response in Python console for debugging
print("📡 [DEBUG] HTTP Status:", response.status_code)
print("📡 [DEBUG] Raw API Response:\n", response.text)
print("-" * 50)
# Display raw API response in chat for traceability
self.chat_area.append(f"<b>Raw API response:</b><br><pre>{response.text}</pre>")
if not response.text.strip():
print("[DEBUG] ❌ Empty API response received.")
self.chat_area.append("<b>Bot:</b> ❌ API returned no data.")
return
try:
data = response.json()
except Exception as json_err:
print(f"[DEBUG] ❌ JSON Parse Error: {json_err}")
self.chat_area.append(f"<b>Bot:</b> ❌ Failed to parse data: {json_err}")
return
status = data.get("status_code")
if status == "SUCCESS":
now = QDateTime.currentDateTime().toString("dddd, MMMM d, yyyy, h:mm AP t")
self.chat_area.append(
f"<b>Production Order Count ({self.selected_filter})</b><br><b>Current date:</b> {now}<br><br>")
datasets = data.get("datasets", [])
for dataset in datasets:
label = dataset.get("label", "Data")
self.chat_area.append(f"<b>{label}:</b>")
# Handle 'Today' and 'Yesterday' (dict)
if isinstance(dataset.get("data"), dict):
for timeslot, count in dataset.get("data", {}).items():
self.chat_area.append(f"{timeslot}: <b>{count}</b><br>")
# Handle 'This Week', 'This Month' (list)
elif isinstance(dataset.get("data"), list):
labels = data.get("labels", [])
for idx, value in enumerate(dataset.get("data")):
label_text = labels[idx] if idx < len(labels) else f"Data {idx + 1}"
self.chat_area.append(f"{label_text}: <b>{value}</b><br>")
else:
self.chat_area.append(f"Data: <b>{dataset.get('data')}</b>")
print("[DEBUG] ✅ Production order count handled/displayed.")
else:
print(f"[DEBUG] ❌ API status_code not SUCCESS: {status}")
self.chat_area.append(f"<b>Bot:</b> ❌ API returned status <code>{status}</code>")
except requests.exceptions.HTTPError as errh:
print("[DEBUG] ❌ HTTP Error:", errh)
self.chat_area.append(f"<b>Bot:</b> ❌ HTTP Error: {errh}")
except requests.exceptions.ConnectionError:
print("[DEBUG] ❌ Connection Error.")
self.chat_area.append("<b>Bot:</b> ❌ Connection error.")
except requests.exceptions.Timeout:
print("[DEBUG] ❌ Timeout Error.")
self.chat_area.append("<b>Bot:</b> ❌ Request timed out.")
except Exception as e:
print(f"[DEBUG] ❌ General Error: {e}")
self.chat_area.append(f"<b>Bot:</b> ❌ Unexpected Error: {e}")
def clear_chat(self):
self.chat_area.clear()
def go_back(self):
self.stacked.setCurrentIndex(1)
# MODULE -2 INVOICE DASHBOARD
#CHART-1 INVOICE
#to fetch the invoice types
def fetch_and_display_invoice_types(self):
url = "https://pds.iotsignin.com/api/get/module-invoice-type/data"
headers = {
"Authorization": "Bearer sb-eba140ab-74bb-44a4-8d92-70a636940def!b1182|it-rt-dev-cri-stjllphr!b68:616d8991-307b-4ab1-be37-7894a8c6db9d$0p0fE2I7w1Ve23-lVSKQF0ka3mKrTVcKPJYELr-i4nE=",
"invoice-type-list": "Invoice Type List"
}
try:
response = requests.get(url, headers=headers, timeout=10)
if response.status_code == 200:
data = response.json()
if data.get("status_code") == "SUCCESS":
self.invoice_types = data.get("status_description", [])
if self.invoice_types:
self.awaiting_invoice_choice = True
self.show_choice_menu("invoice", self.invoice_types)
else:
self.chat_area.append("<b>Bot:</b> ❌ No invoice types found.")
else:
error_msg = data.get("status_description", "Unknown error")
self.chat_area.append(f"<b>Bot:</b> ❌ Failed to get invoice types: {error_msg}")
else:
self.chat_area.append(f"<b>Bot:</b> ❌ HTTP Error {response.status_code} while fetching invoice types.")
except Exception as e:
self.chat_area.append(f"<b>Bot:</b> ❌ Error getting invoice types: <code>{str(e)}</code>")
# To fetch date filter
def fetch_and_display_invoice_filters(self):
url = "http://pds.iotsignin.com/api/get/module-invoice-filter/data"
headers = {
"Authorization": "Bearer sb-eba140ab-74bb-44a4-8d92-70a636940def!b1182|it-rt-dev-cri-stjllphr!b68:616d8991-307b-4ab1-be37-7894a8c6db9d$0p0fE2I7w1Ve23-lVSKQF0ka3mKrTVcKPJYELr-i4nE=",
"filter-name": "Filter List"
}
try:
response = requests.get(url, headers=headers, timeout=10)
if response.status_code != 200:
self.chat_area.append(f"<b>Bot:</b> ❌ HTTP Error {response.status_code} when fetching filters.")
return
data = response.json()
if data.get("status_code") == "SUCCESS":
filters = data.get("status_description", [])
if filters:
self.filters = filters
self.awaiting_filter_choice = True
self.show_choice_menu("filter", filters)
else:
self.chat_area.append("<b>Bot:</b> ❌ No invoice filters found.")
else:
self.chat_area.append(f"<b>Bot:</b> ❌ API Error: {data.get('status_description', 'Unknown error')}")
except Exception as e:
self.chat_area.append(f"<b>Bot:</b> ❌ Exception when fetching invoice filters: <code>{str(e)}</code>")
# to fetch production count
def fetch_and_display_invoice_production_count(self):
url = "https://pds.iotsignin.com/api/get/module-invoice-count/data"
headers = {
"Authorization": self.API_TOKEN,
"plant-name": self.selected_plant,
"invoice-name": self.selected_invoice_type,
"filter-name": self.selected_filter
}
try:
response = requests.get(url, headers=headers, timeout=10)
# Show raw API response for debugging
self.chat_area.append(f"<b>📡 Raw API Response:</b><br><pre>{response.text}</pre>")
if response.status_code != 200:
self.chat_area.append(f"<b>Bot:</b> ❌ HTTP Error {response.status_code} fetching invoice count.")
return
data = response.json()
status = data.get("status_code")
if status != "SUCCESS":
error_msg = data.get("status_description", "Unknown error")
self.chat_area.append(f"<b>Bot:</b> ❌ API Error: {error_msg}")
return
labels = data.get("labels", [])
datasets = data.get("datasets", [])
# Show current date/time
now = QDateTime.currentDateTime()
fmt_date = now.toString("dddd, MMMM d, yyyy, h:mm AP")
self.chat_area.append(f"<b>Current date:</b> {fmt_date}<br>")
# Multiple datasets means 'All Invoice' selection
if len(datasets) > 1:
for dataset in datasets:
label = dataset.get("label", "Dataset")
values = dataset.get("data", [])
self.chat_area.append(f"<b>{label}:</b><br>")
for lbl, val in zip(labels, values):
self.chat_area.append(f"{lbl}: <b>{val}</b><br>")
self.chat_area.append("<br>") # spacing between datasets
# Single dataset for specific invoice type
elif len(datasets) == 1:
dataset = datasets[0]
label = dataset.get("label", "Invoices")
values = dataset.get("data", [])
self.chat_area.append(f"<b>{label}:</b><br>")
for lbl, val in zip(labels, values):
self.chat_area.append(f"{lbl}: <b>{val}</b><br>")
else:
self.chat_area.append("<b>Bot:</b> ❌ No data found in API response.")
except Exception as e:
self.chat_area.append(f"<b>Bot:</b> ❌ Exception fetching invoice count: <code>{str(e)}</code>")
def fetch_and_display_invoice_quantity(self):
url = "https://pds.iotsignin.com/api/get/module-invoice-quantity/data"
headers = {
"Authorization": self.API_TOKEN,
"plant-name": self.selected_plant,
"invoice-name": self.selected_invoice_type,
"filter-name": self.selected_filter
}
try:
response = requests.get(url, headers=headers, timeout=10)
# Show raw response for debugging
self.chat_area.append(f"<b>📡 Raw API Response:</b><br><pre>{response.text}</pre>")
if response.status_code != 200:
self.chat_area.append(f"<b>Bot:</b> ❌ HTTP Error {response.status_code} fetching invoice quantity.")
return
data = response.json()
if data.get("status_code") != "SUCCESS":
error_msg = data.get("status_description", "Unknown error")
self.chat_area.append(f"<b>Bot:</b> ❌ API Error: {error_msg}")
return
labels = data.get("labels", [])
datasets = data.get("datasets", [])
# Display current date/time in desired format
now = QDateTime.currentDateTime()
fmt_date = now.toString("dddd, MMMM d, yyyy, h:mm AP")
self.chat_area.append(f"<b>Current date:</b> {fmt_date}<br>")
if len(datasets) > 1:
# Multiple datasets (e.g. All Invoice)
for dataset in datasets:
label = dataset.get("label", "Data")
values = dataset.get("data", [])
self.chat_area.append(f"<b>{label}:</b><br>")
for lbl, val in zip(labels, values):
self.chat_area.append(f"{lbl}: <b>{val}</b><br>")
self.chat_area.append("<br>")
elif len(datasets) == 1:
# Single dataset (single invoice type)
dataset = datasets[0]
label = dataset.get("label", "Invoice Quantity")
values = dataset.get("data", [])
self.chat_area.append(f"<b>{label}:</b><br>")
for lbl, val in zip(labels, values):
self.chat_area.append(f"{lbl}: <b>{val}</b><br>")
else:
self.chat_area.append("<b>Bot:</b> ❌ No invoice quantity data found.")
except Exception as e:
self.chat_area.append(f"<b>Bot:</b> ❌ Exception fetching invoice quantity: <code>{str(e)}</code>")
def main():
app = QApplication(sys.argv)
stacked = QStackedWidget()
bot_screen = BotScreen(stacked)
selector_screen = SelectorScreen(stacked, bot_screen)
stacked.addWidget(LoginScreen(stacked))
stacked.addWidget(selector_screen)
stacked.addWidget(bot_screen)
stacked.setFixedSize(420, 640)
stacked.show() ,
sys.exit(app.exec())
if __name__ == '__main__':
main()