EMailed label return generation (alpha)

This commit is contained in:
2026-09-02 09:30:19 -05:00
parent 6655b02f4a
commit 826a70bdf6
13 changed files with 603 additions and 5 deletions
+71
View File
@@ -25,6 +25,7 @@ from PyQt6.QtWidgets import (
QFileDialog,
)
from app.return_labels import is_emailed_label_order
from app.services import SERVICE_REGISTRY
from app.services.odoo_export import export_orders_to_csv
from app.services.shipstation_send import export_order_to_shipstation_csv
@@ -33,9 +34,11 @@ from app.ui.settings_dialog import SettingsDialog
from app.ui.widgets.orders_table import OrdersTableView
from app.ui.widgets.dashboard import DashboardWidget
from app.ui.widgets.order_detail_dialog import OrderDetailDialog
from app.ui.widgets.return_label_dialog import ReturnLabelDialog
from app.workers import (
FetchOrdersWorker,
SendToShipStationWorker,
CreateReturnLabelWorker,
load_orders_by_view,
get_dashboard_stats,
mark_shipstation_sent,
@@ -52,6 +55,7 @@ class MainWindow(QMainWindow):
self._workers: dict[str, FetchOrdersWorker] = {}
self._import_actions: dict[str, QAction] = {}
self._send_worker: SendToShipStationWorker | None = None
self._return_label_worker: CreateReturnLabelWorker | None = None
self._build_ui()
self._refresh_everything()
@@ -106,6 +110,13 @@ class MainWindow(QMainWindow):
emergency_action.triggered.connect(self._on_emergency_send_clicked)
toolbar.addAction(emergency_action)
return_label_action = QAction("Create Return Label", self)
return_label_action.setToolTip(
"For emailed-return-label tickets (SH007/OK012) - select one in Active Orders first"
)
return_label_action.triggered.connect(self._on_create_return_label_clicked)
toolbar.addAction(return_label_action)
toolbar.addSeparator()
settings_action = QAction("Settings", self)
@@ -339,6 +350,66 @@ class MainWindow(QMainWindow):
"Upload this into ShipStation's Import Orders wizard.",
)
def _on_create_return_label_clicked(self) -> None:
order = self.orders_table.selected_order()
if order is None:
QMessageBox.information(
self,
"No ticket selected",
"Select a ticket in Active Orders first, then click Create Return Label.",
)
return
if not is_emailed_label_order(order.skus or []):
proceed = QMessageBox.question(
self,
"Not a return-label ticket",
f"This ticket's SKU(s) ({', '.join(order.skus or []) or 'none'}) don't match "
"the configured emailed-label SKUs. Continue anyway?",
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
QMessageBox.StandardButton.No,
)
if proceed != QMessageBox.StandardButton.Yes:
return
dialog = ReturnLabelDialog(order, self)
if dialog.exec() != QDialog.DialogCode.Accepted:
return
packages = dialog.get_packages()
charge_event = dialog.get_charge_event()
if not packages:
QMessageBox.warning(self, "No packages", "Add at least one package first.")
return
ticket_number = order.ticket_number or order.external_id
self.status_label.setText(f"Creating return label for {ticket_number}...")
worker = CreateReturnLabelWorker(order, packages, charge_event)
worker.finished_ok.connect(lambda result: self._on_return_label_ok(ticket_number, result))
worker.failed.connect(self._on_return_label_failed)
self._return_label_worker = worker # keep a reference so it isn't garbage collected
worker.start()
def _on_return_label_ok(self, ticket_number: str, result: dict) -> None:
mark_shipstation_sent(ticket_number)
self._refresh_everything()
label_id = result.get("label_id", "?")
tracking = result.get("tracking_number", "?")
self.status_label.setText(f"Return label created - {label_id}")
QMessageBox.information(
self,
"Return Label Created",
f"Label {label_id} created (tracking {tracking}).\n\n"
"Next: go to ShipStation's Returns tab, find this label, and use "
"Other Actions -> Send Return Label to email it to the customer through "
"your branded template.",
)
def _on_return_label_failed(self, message: str) -> None:
self.status_label.setText("Return label creation failed.")
QMessageBox.critical(self, "Return label creation failed", message)
def _on_reset_database_clicked(self) -> None:
confirm = QMessageBox.warning(
self,