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"HTTP: {response.status_code}") self.chat_area.append(f"Bot Module: {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"Bot: 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"Bot: Please select a {label_map[item]}:
" + "
".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"Bot: ✅ You selected: {self.selected_chart}") self.fetch_and_display_plants() else: self.chat_area.append(f"Bot: ❌ Please select a number from 1 to {len(self.charts)}.") else: self.chat_area.append(f"Bot: ❌ 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"Bot: ✅ You selected: {self.selected_plant}") # 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"Bot: ❌ Please select a number from 1 to {len(self.plants)}.") else: self.chat_area.append(f"Bot: ❌ 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"Bot: ✅ You selected: {self.selected_line}") 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("Bot: Please enter the production order number:") else: self.fetch_and_display_filters() else: self.chat_area.append(f"Bot: ❌ Please select a number from 1 to {len(self.lines)}.") else: self.chat_area.append(f"Bot: ❌ 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("Bot: ❌ Please enter a valid production order number (numbers only).") else: self.selected_order = order self.awaiting_order_input = False self.chat_area.append(f"Bot: ✅ Production order set: {self.selected_order}") 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"Bot: ✅ You selected invoice type: {self.selected_invoice_type}" ) # 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( "Bot: ❌ Unrecognized invoice chart selected." ) else: self.chat_area.append( f"Bot: ❌ Please select a number from 1 to {len(self.invoice_types)}." ) else: self.chat_area.append( f"Bot: ❌ 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"Bot: ✅ You selected filter: {self.selected_filter}") # Show current date/time now = QDateTime.currentDateTime() fmt_date = now.toString("dddd, MMMM d, yyyy, hh:mm AP") self.chat_area.append(f"Current date: {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"Bot: ❌ Please select a number from 1 to {len(self.filters)}.") else: self.chat_area.append(f"Bot: ❌ 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("Bot: ❌ No plants found.") else: self.chat_area.append(f"Bot: ❌ Error: {data.get('status_description')}") except Exception as e: self.chat_area.append(f"Bot: ❌ 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("Bot: ❌ No lines found for the selected plant.") else: self.chat_area.append(f"Bot: ❌ Error: {data.get('status_description')}") except Exception as e: self.chat_area.append(f"Bot: ❌ 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 it’s 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("Bot: ❌ No date filters found for your selection.") else: self.chat_area.append(f"Bot: ❌ API Error: {data.get('status_description', 'Unknown error')}") except Exception as e: self.chat_area.append(f"Bot: ❌ 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"Bot: 📊 Production Counts (All Lines):") for ln, count in result.items(): self.chat_area.append(f"{ln}: {count}") else: self.chat_area.append(f"Bot: 📈 Production Count: {result}") else: self.chat_area.append(f"Bot: ❌ Error getting production count: {data.get('status_description', 'Unknown')}") except Exception as e: self.chat_area.append(f"Bot: ❌ 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"Raw API response:
{response.text}
") # 🔒 Handle empty API response if not response.text.strip(): print("[DEBUG] ❌ Empty response received.") self.chat_area.append("Bot: ❌ 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"Bot: ❌ 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"📊 Production Hourly Count ({self.selected_filter})
Current date: {now}

") 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} ➤ {val}
" self.chat_area.append(f"{label}:
{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"Bot: ❌ API returned status {req_status}") # 🔒 Specific error handling except requests.exceptions.HTTPError as errh: print("[DEBUG] ❌ HTTP Error:", errh) self.chat_area.append(f"Bot: ❌ HTTP Error: {errh}") except requests.exceptions.ConnectionError: print("[DEBUG] ❌ Connection Error.") self.chat_area.append("Bot: ❌ Connection error.") except requests.exceptions.Timeout: print("[DEBUG] ❌ Timeout Error.") self.chat_area.append("Bot: ❌ Request timed out.") except Exception as e: print(f"[DEBUG] ❌ General Error: {e}") self.chat_area.append(f"Bot: ❌ 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"Raw API response:
{response.text}
") if response.status_code != 200: self.chat_area.append(f"Bot: ❌ HTTP error {response.status_code}") return if not response.text.strip(): self.chat_area.append(f"Bot: ❌ No response from API.") return try: data = response.json() except Exception as e: self.chat_area.append(f"Bot: ❌ 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"Production Line Stop Counts
Current date: {current_date}

" for label, value in zip(labels, values): message += f"{label}: {value}
" self.chat_area.append(message) else: self.chat_area.append(f"Bot: ❌ No data found for this selection.") except Exception as e: self.chat_area.append(f"Bot: ❌ 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"Raw API response:
{response.text}
") if not response.text.strip(): print("[DEBUG] ❌ Empty API response received.") self.chat_area.append("Bot: ❌ 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"Bot: ❌ 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"Production Order Count ({self.selected_filter})
Current date: {now}

") datasets = data.get("datasets", []) for dataset in datasets: label = dataset.get("label", "Data") self.chat_area.append(f"{label}:") # 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}: {count}
") # 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}: {value}
") else: self.chat_area.append(f"Data: {dataset.get('data')}") print("[DEBUG] ✅ Production order count handled/displayed.") else: print(f"[DEBUG] ❌ API status_code not SUCCESS: {status}") self.chat_area.append(f"Bot: ❌ API returned status {status}") except requests.exceptions.HTTPError as errh: print("[DEBUG] ❌ HTTP Error:", errh) self.chat_area.append(f"Bot: ❌ HTTP Error: {errh}") except requests.exceptions.ConnectionError: print("[DEBUG] ❌ Connection Error.") self.chat_area.append("Bot: ❌ Connection error.") except requests.exceptions.Timeout: print("[DEBUG] ❌ Timeout Error.") self.chat_area.append("Bot: ❌ Request timed out.") except Exception as e: print(f"[DEBUG] ❌ General Error: {e}") self.chat_area.append(f"Bot: ❌ 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("Bot: ❌ No invoice types found.") else: error_msg = data.get("status_description", "Unknown error") self.chat_area.append(f"Bot: ❌ Failed to get invoice types: {error_msg}") else: self.chat_area.append(f"Bot: ❌ HTTP Error {response.status_code} while fetching invoice types.") except Exception as e: self.chat_area.append(f"Bot: ❌ Error getting invoice types: {str(e)}") # 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"Bot: ❌ 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("Bot: ❌ No invoice filters found.") else: self.chat_area.append(f"Bot: ❌ API Error: {data.get('status_description', 'Unknown error')}") except Exception as e: self.chat_area.append(f"Bot: ❌ Exception when fetching invoice filters: {str(e)}") # 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"📡 Raw API Response:
{response.text}
") if response.status_code != 200: self.chat_area.append(f"Bot: ❌ 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"Bot: ❌ 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"Current date: {fmt_date}
") # 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"{label}:
") for lbl, val in zip(labels, values): self.chat_area.append(f"{lbl}: {val}
") self.chat_area.append("
") # 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"{label}:
") for lbl, val in zip(labels, values): self.chat_area.append(f"{lbl}: {val}
") else: self.chat_area.append("Bot: ❌ No data found in API response.") except Exception as e: self.chat_area.append(f"Bot: ❌ Exception fetching invoice count: {str(e)}") 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"📡 Raw API Response:
{response.text}
") if response.status_code != 200: self.chat_area.append(f"Bot: ❌ 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"Bot: ❌ 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"Current date: {fmt_date}
") 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"{label}:
") for lbl, val in zip(labels, values): self.chat_area.append(f"{lbl}: {val}
") self.chat_area.append("
") 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"{label}:
") for lbl, val in zip(labels, values): self.chat_area.append(f"{lbl}: {val}
") else: self.chat_area.append("Bot: ❌ No invoice quantity data found.") except Exception as e: self.chat_area.append(f"Bot: ❌ Exception fetching invoice quantity: {str(e)}") 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()