123 lines
4.0 KiB
Python
123 lines
4.0 KiB
Python
import csv
|
|
import time
|
|
from services.core.loading_service import run_with_progress
|
|
from database.models.product import Product
|
|
|
|
from PyQt5.QtWidgets import (
|
|
QWidget, QVBoxLayout, QPushButton, QFileDialog,
|
|
QTableWidget, QTableWidgetItem, QHBoxLayout, QMessageBox
|
|
)
|
|
|
|
|
|
class ImportTab(QWidget):
|
|
def __init__(self):
|
|
super().__init__()
|
|
layout = QVBoxLayout()
|
|
|
|
# --- Action buttons ---
|
|
btn_layout = QHBoxLayout()
|
|
|
|
self.btn_import_csv = QPushButton("Import from CSV")
|
|
self.btn_import_csv.clicked.connect(self.import_csv)
|
|
btn_layout.addWidget(self.btn_import_csv)
|
|
|
|
self.btn_import_api = QPushButton("Import from API")
|
|
self.btn_import_api.clicked.connect(self.import_api)
|
|
btn_layout.addWidget(self.btn_import_api)
|
|
|
|
self.btn_save = QPushButton("Save to Database")
|
|
self.btn_save.clicked.connect(self.save_to_db)
|
|
self.btn_save.setEnabled(False)
|
|
btn_layout.addWidget(self.btn_save)
|
|
|
|
layout.addLayout(btn_layout)
|
|
|
|
# --- Table preview ---
|
|
self.table = QTableWidget()
|
|
layout.addWidget(self.table)
|
|
|
|
self.setLayout(layout)
|
|
self.preview_data = [] # store imported data
|
|
|
|
def import_csv(self):
|
|
file_path, _ = QFileDialog.getOpenFileName(self, "Select CSV File", "", "CSV Files (*.csv)")
|
|
if not file_path:
|
|
return
|
|
|
|
try:
|
|
# đọc CSV chuẩn với DictReader
|
|
with open(file_path, newline='', encoding="utf-8-sig") as csvfile:
|
|
reader = csv.DictReader(csvfile)
|
|
headers = reader.fieldnames
|
|
rows = list(reader)
|
|
|
|
if not headers or not rows:
|
|
QMessageBox.warning(self, "Warning", "CSV file is empty or invalid.")
|
|
return
|
|
|
|
self.table.setColumnCount(len(headers))
|
|
self.table.setHorizontalHeaderLabels(headers)
|
|
|
|
# Hiển thị preview (giới hạn 200 dòng để tránh lag)
|
|
preview_limit = min(len(rows), 200)
|
|
self.table.setRowCount(preview_limit)
|
|
|
|
for i in range(preview_limit):
|
|
for j, header in enumerate(headers):
|
|
value = rows[i].get(header, "")
|
|
self.table.setItem(i, j, QTableWidgetItem(value))
|
|
|
|
self.table.resizeColumnsToContents()
|
|
self.preview_data = rows
|
|
self.btn_save.setEnabled(True)
|
|
|
|
except Exception as e:
|
|
QMessageBox.critical(self, "Error", f"Failed to read CSV: {e}")
|
|
|
|
def import_api(self):
|
|
QMessageBox.information(self, "Info", "API import feature will be developed later 😉")
|
|
|
|
def save_to_db(self):
|
|
if not self.preview_data:
|
|
QMessageBox.warning(self, "Warning", "No data to save.")
|
|
return
|
|
|
|
# Xác nhận trước khi import
|
|
reply = QMessageBox.question(
|
|
self,
|
|
"Confirm Import",
|
|
f"Are you sure you want to import {len(self.preview_data)} rows?",
|
|
QMessageBox.Yes | QMessageBox.No
|
|
)
|
|
if reply != QMessageBox.Yes:
|
|
return
|
|
|
|
def handler(item):
|
|
try:
|
|
# time.sleep(0.05) # có thể bỏ nếu không cần debug progress
|
|
Product.insert_from_import(item)
|
|
return True
|
|
except Exception as e:
|
|
print(f"Failed to import row: {e}")
|
|
return False
|
|
|
|
success, fail = run_with_progress(
|
|
self.preview_data,
|
|
handler=handler,
|
|
message="Importing data...",
|
|
parent=self
|
|
)
|
|
|
|
QMessageBox.information(
|
|
self,
|
|
"Import Completed",
|
|
f"Successfully imported {success}/{len(self.preview_data)} rows.\nFailed: {fail} rows."
|
|
)
|
|
|
|
# ✅ Clear preview sau khi import xong
|
|
self.preview_data.clear()
|
|
self.table.clearContents()
|
|
self.table.setRowCount(0)
|
|
self.table.setColumnCount(0)
|
|
self.btn_save.setEnabled(False)
|