Spaces:
Sleeping
Sleeping
Update src/streamlit_app.py
Browse files- src/streamlit_app.py +27 -19
src/streamlit_app.py
CHANGED
|
@@ -4,6 +4,7 @@ import json
|
|
| 4 |
from datetime import datetime
|
| 5 |
import io
|
| 6 |
import os
|
|
|
|
| 7 |
|
| 8 |
# --- Inizializzazione Session State ---
|
| 9 |
if 'file_uploader_key' not in st.session_state:
|
|
@@ -39,6 +40,9 @@ st.markdown(
|
|
| 39 |
unsafe_allow_html=True
|
| 40 |
)
|
| 41 |
|
|
|
|
|
|
|
|
|
|
| 42 |
# Funzione di conversione
|
| 43 |
def convert_json_to_excel_data(json_file_content: str):
|
| 44 |
try:
|
|
@@ -57,9 +61,19 @@ def convert_json_to_excel_data(json_file_content: str):
|
|
| 57 |
order_date_formatted = None
|
| 58 |
if order_date_str:
|
| 59 |
try:
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
except ValueError:
|
| 64 |
order_date_formatted = order_date_str
|
| 65 |
st.warning(f"Attenzione: Impossibile parsare la data '{order_date_str}' per un file. Verrà usata la stringa originale.")
|
|
@@ -68,7 +82,7 @@ def convert_json_to_excel_data(json_file_content: str):
|
|
| 68 |
|
| 69 |
processed_data_for_this_file = []
|
| 70 |
for item in details:
|
| 71 |
-
#
|
| 72 |
cancel_pos_oda_val = item.get('cancelPosOdA')
|
| 73 |
if cancel_pos_oda_val is None or \
|
| 74 |
(isinstance(cancel_pos_oda_val, bool) and not cancel_pos_oda_val) or \
|
|
@@ -86,8 +100,8 @@ def convert_json_to_excel_data(json_file_content: str):
|
|
| 86 |
'supplier.partnerRef.code': partner_code,
|
| 87 |
'supplier.partnerRef.company.code': company_code,
|
| 88 |
'docDate': order_date_formatted,
|
| 89 |
-
'status': 'CREATED',
|
| 90 |
-
'positions.status': positions_status_value,
|
| 91 |
'positions.positionId': item.get('positionId'),
|
| 92 |
'positions.stock.item.itemNumber': item.get('itemCode'),
|
| 93 |
'positions.stock.quantity': item.get('quantity'),
|
|
@@ -96,9 +110,8 @@ def convert_json_to_excel_data(json_file_content: str):
|
|
| 96 |
'positions.stock.accountingInfo.availability': item.get('availability'),
|
| 97 |
'positions.stock.item.company.code': company_code,
|
| 98 |
'positions.spare.string1': item.get('refOrder'),
|
| 99 |
-
'positions.reason.code': item.get('reasonCode'),
|
| 100 |
'positions.reason.company.code': company_code,
|
| 101 |
-
# RIMOZIONE COMPLETA DI 'positions.stock.cancelPosOda'
|
| 102 |
}
|
| 103 |
processed_data_for_this_file.append(row)
|
| 104 |
|
|
@@ -167,9 +180,6 @@ if uploaded_files:
|
|
| 167 |
|
| 168 |
# --- Post-processing per la formattazione Excel ---
|
| 169 |
|
| 170 |
-
# Rimuoviamo la riga per cancelPosOda in quanto non serve più
|
| 171 |
-
# final_df['positions.stock.cancelPosOda'] = final_df['positions.stock.cancelPosOda'].apply(lambda x: str(x).capitalize())
|
| 172 |
-
|
| 173 |
# Definizione delle colonne di testata
|
| 174 |
header_columns = [
|
| 175 |
'site.code', 'docNumber', 'company.code', 'supplier.partnerRef.code',
|
|
@@ -205,7 +215,7 @@ if uploaded_files:
|
|
| 205 |
'supplier.partnerRef.company.code',
|
| 206 |
'docDate',
|
| 207 |
'status',
|
| 208 |
-
'positions.status',
|
| 209 |
'positions.positionId',
|
| 210 |
'positions.stock.item.itemNumber',
|
| 211 |
'positions.stock.quantity',
|
|
@@ -214,9 +224,8 @@ if uploaded_files:
|
|
| 214 |
'positions.stock.accountingInfo.availability',
|
| 215 |
'positions.stock.item.company.code',
|
| 216 |
'positions.spare.string1',
|
| 217 |
-
'positions.reason.code',
|
| 218 |
'positions.reason.company.code',
|
| 219 |
-
# RIMOZIONE COMPLETA DI 'positions.stock.cancelPosOda' dalla lista delle colonne
|
| 220 |
]
|
| 221 |
|
| 222 |
# Assicurati che il DataFrame abbia tutte le colonne nell'ordine desiderato
|
|
@@ -234,7 +243,7 @@ if uploaded_files:
|
|
| 234 |
'supplier.partnerRef.company.code': 25,
|
| 235 |
'docDate': 20,
|
| 236 |
'status': 10,
|
| 237 |
-
'positions.status': 12,
|
| 238 |
'positions.positionId': 12,
|
| 239 |
'positions.stock.item.itemNumber': 25,
|
| 240 |
'positions.stock.quantity': 10,
|
|
@@ -245,18 +254,17 @@ if uploaded_files:
|
|
| 245 |
'positions.spare.string1': 15,
|
| 246 |
'positions.reason.code': 15,
|
| 247 |
'positions.reason.company.code': 25,
|
| 248 |
-
# RIMOZIONE COMPLETA DI 'positions.stock.cancelPosOda' dalla lista delle larghezze
|
| 249 |
}
|
| 250 |
|
| 251 |
# Scrivi i nomi delle colonne nella riga 2 (indice 1 in xlsxwriter)
|
| 252 |
for col_num, col_name in enumerate(final_df.columns.values):
|
| 253 |
-
worksheet.write(1, col_num, col_name)
|
| 254 |
|
| 255 |
# Imposta le larghezze delle colonne
|
| 256 |
if col_name in col_widths:
|
| 257 |
worksheet.set_column(col_num, col_num, col_widths[col_name])
|
| 258 |
else:
|
| 259 |
-
worksheet.set_column(col_num, col_num, 15)
|
| 260 |
|
| 261 |
# Scrivi i dati a partire dalla riga 3 (indice 2 in xlsxwriter)
|
| 262 |
final_df.to_excel(writer, sheet_name=sheet_name_excel, index=False, header=False, startrow=2)
|
|
@@ -278,7 +286,7 @@ if uploaded_files:
|
|
| 278 |
else:
|
| 279 |
st.info("Nessun dato valido estratto dai file selezionati.")
|
| 280 |
else:
|
| 281 |
-
st.info("Carica i tuoi file JSON per iniziare.
|
| 282 |
|
| 283 |
# --- Funzione per il reset ---
|
| 284 |
def clear_inputs():
|
|
|
|
| 4 |
from datetime import datetime
|
| 5 |
import io
|
| 6 |
import os
|
| 7 |
+
from zoneinfo import ZoneInfo # Importa ZoneInfo da zoneinfo
|
| 8 |
|
| 9 |
# --- Inizializzazione Session State ---
|
| 10 |
if 'file_uploader_key' not in st.session_state:
|
|
|
|
| 40 |
unsafe_allow_html=True
|
| 41 |
)
|
| 42 |
|
| 43 |
+
# Definizione del fuso orario per l'Italia (Europe/Rome gestisce automaticamente DST)
|
| 44 |
+
ITALY_TIMEZONE = ZoneInfo("Europe/Rome")
|
| 45 |
+
|
| 46 |
# Funzione di conversione
|
| 47 |
def convert_json_to_excel_data(json_file_content: str):
|
| 48 |
try:
|
|
|
|
| 61 |
order_date_formatted = None
|
| 62 |
if order_date_str:
|
| 63 |
try:
|
| 64 |
+
# 1. Parsa la stringa ISO, che gestisce già 'Z' (UTC)
|
| 65 |
+
dt_object_utc = datetime.fromisoformat(order_date_str)
|
| 66 |
+
|
| 67 |
+
# 2. Assicurati che l'oggetto datetime sia consapevole del fuso orario UTC
|
| 68 |
+
if dt_object_utc.tzinfo is None:
|
| 69 |
+
# Se non ha informazioni sul fuso orario, assumi UTC (per casi senza 'Z')
|
| 70 |
+
dt_object_utc = dt_object_utc.replace(tzinfo=ZoneInfo("UTC"))
|
| 71 |
+
|
| 72 |
+
# 3. Converti al fuso orario italiano
|
| 73 |
+
dt_object_italy = dt_object_utc.astimezone(ITALY_TIMEZONE)
|
| 74 |
+
|
| 75 |
+
# 4. Formatta per includere data e ora locale
|
| 76 |
+
order_date_formatted = dt_object_italy.strftime('%d/%m/%Y %H:%M:%S')
|
| 77 |
except ValueError:
|
| 78 |
order_date_formatted = order_date_str
|
| 79 |
st.warning(f"Attenzione: Impossibile parsare la data '{order_date_str}' per un file. Verrà usata la stringa originale.")
|
|
|
|
| 82 |
|
| 83 |
processed_data_for_this_file = []
|
| 84 |
for item in details:
|
| 85 |
+
# LOGICA PER positions.status BASATA SU cancelPosOdA
|
| 86 |
cancel_pos_oda_val = item.get('cancelPosOdA')
|
| 87 |
if cancel_pos_oda_val is None or \
|
| 88 |
(isinstance(cancel_pos_oda_val, bool) and not cancel_pos_oda_val) or \
|
|
|
|
| 100 |
'supplier.partnerRef.code': partner_code,
|
| 101 |
'supplier.partnerRef.company.code': company_code,
|
| 102 |
'docDate': order_date_formatted,
|
| 103 |
+
'status': 'CREATED',
|
| 104 |
+
'positions.status': positions_status_value,
|
| 105 |
'positions.positionId': item.get('positionId'),
|
| 106 |
'positions.stock.item.itemNumber': item.get('itemCode'),
|
| 107 |
'positions.stock.quantity': item.get('quantity'),
|
|
|
|
| 110 |
'positions.stock.accountingInfo.availability': item.get('availability'),
|
| 111 |
'positions.stock.item.company.code': company_code,
|
| 112 |
'positions.spare.string1': item.get('refOrder'),
|
| 113 |
+
'positions.reason.code': item.get('reasonCode'),
|
| 114 |
'positions.reason.company.code': company_code,
|
|
|
|
| 115 |
}
|
| 116 |
processed_data_for_this_file.append(row)
|
| 117 |
|
|
|
|
| 180 |
|
| 181 |
# --- Post-processing per la formattazione Excel ---
|
| 182 |
|
|
|
|
|
|
|
|
|
|
| 183 |
# Definizione delle colonne di testata
|
| 184 |
header_columns = [
|
| 185 |
'site.code', 'docNumber', 'company.code', 'supplier.partnerRef.code',
|
|
|
|
| 215 |
'supplier.partnerRef.company.code',
|
| 216 |
'docDate',
|
| 217 |
'status',
|
| 218 |
+
'positions.status',
|
| 219 |
'positions.positionId',
|
| 220 |
'positions.stock.item.itemNumber',
|
| 221 |
'positions.stock.quantity',
|
|
|
|
| 224 |
'positions.stock.accountingInfo.availability',
|
| 225 |
'positions.stock.item.company.code',
|
| 226 |
'positions.spare.string1',
|
| 227 |
+
'positions.reason.code',
|
| 228 |
'positions.reason.company.code',
|
|
|
|
| 229 |
]
|
| 230 |
|
| 231 |
# Assicurati che il DataFrame abbia tutte le colonne nell'ordine desiderato
|
|
|
|
| 243 |
'supplier.partnerRef.company.code': 25,
|
| 244 |
'docDate': 20,
|
| 245 |
'status': 10,
|
| 246 |
+
'positions.status': 12,
|
| 247 |
'positions.positionId': 12,
|
| 248 |
'positions.stock.item.itemNumber': 25,
|
| 249 |
'positions.stock.quantity': 10,
|
|
|
|
| 254 |
'positions.spare.string1': 15,
|
| 255 |
'positions.reason.code': 15,
|
| 256 |
'positions.reason.company.code': 25,
|
|
|
|
| 257 |
}
|
| 258 |
|
| 259 |
# Scrivi i nomi delle colonne nella riga 2 (indice 1 in xlsxwriter)
|
| 260 |
for col_num, col_name in enumerate(final_df.columns.values):
|
| 261 |
+
worksheet.write(1, col_num, col_name)
|
| 262 |
|
| 263 |
# Imposta le larghezze delle colonne
|
| 264 |
if col_name in col_widths:
|
| 265 |
worksheet.set_column(col_num, col_num, col_widths[col_name])
|
| 266 |
else:
|
| 267 |
+
worksheet.set_column(col_num, col_num, 15)
|
| 268 |
|
| 269 |
# Scrivi i dati a partire dalla riga 3 (indice 2 in xlsxwriter)
|
| 270 |
final_df.to_excel(writer, sheet_name=sheet_name_excel, index=False, header=False, startrow=2)
|
|
|
|
| 286 |
else:
|
| 287 |
st.info("Nessun dato valido estratto dai file selezionati.")
|
| 288 |
else:
|
| 289 |
+
st.info("Carica i tuoi file JSON per iniziare.")
|
| 290 |
|
| 291 |
# --- Funzione per il reset ---
|
| 292 |
def clear_inputs():
|