pasquale991 commited on
Commit
db3eb47
·
verified ·
1 Parent(s): b96bef5

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +58 -25
src/streamlit_app.py CHANGED
@@ -6,7 +6,6 @@ import io
6
  import os
7
 
8
  # --- Inizializzazione Session State ---
9
- # Non serve più site_code_input nel session_state perché lo leggiamo dal JSON
10
  if 'file_uploader_key' not in st.session_state:
11
  st.session_state.file_uploader_key = 0
12
 
@@ -37,21 +36,19 @@ st.markdown(
37
  }
38
  </style>
39
  """,
40
- unsafe_allow_html=True # QUESTA RIGA DEVE ESSERCI
41
  )
42
 
43
  # Funzione di conversione
44
- def convert_json_to_excel_data(json_file_content: str): # Rimosso user_site_code come parametro
45
  try:
46
  json_data = json.loads(json_file_content)
47
 
48
- # Prendi companyCode e siteCode dal JSON
49
  company_code = json_data.get('companyCode')
50
- site_code_json = json_data.get('siteCode') # Leggi siteCode direttamente dal JSON
51
 
52
  order_info = json_data.get('order', {})
53
 
54
- # docNumber: da prendere da orderNumber del json
55
  doc_number = order_info.get('orderNumber')
56
  partner_code = order_info.get('partnerCode')
57
 
@@ -61,7 +58,8 @@ def convert_json_to_excel_data(json_file_content: str): # Rimosso user_site_code
61
  if order_date_str:
62
  try:
63
  dt_object = datetime.fromisoformat(order_date_str.replace('Z', '+00:00'))
64
- order_date_formatted = dt_object.strftime('%d/%m/%Y')
 
65
  except ValueError:
66
  order_date_formatted = order_date_str
67
  st.warning(f"Attenzione: Impossibile parsare la data '{order_date_str}' per un file. Verrà usata la stringa originale.")
@@ -79,7 +77,7 @@ def convert_json_to_excel_data(json_file_content: str): # Rimosso user_site_code
79
  cancel_pos_oda_processed = bool(cancel_pos_oda_val)
80
 
81
  row = {
82
- 'site.code': site_code_json, # Ora prende da JSON
83
  'docNumber': doc_number,
84
  'company.code': company_code,
85
  'supplier.partnerRef.code': partner_code,
@@ -94,8 +92,8 @@ def convert_json_to_excel_data(json_file_content: str): # Rimosso user_site_code
94
  'positions.stock.accountingInfo.costCenter': item.get('warehouse'),
95
  'positions.stock.accountingInfo.availability': item.get('availability'),
96
  'positions.stock.item.company.code': company_code,
97
- 'positions.spare.string1': item.get('refOrder'), # Naming modificato
98
- 'positions.stock.reasonCode': item.get('reasonCode'),
99
  'positions.reason.company.code': company_code,
100
  'positions.stock.cancelPosOda': cancel_pos_oda_processed
101
  }
@@ -120,7 +118,6 @@ def convert_json_to_excel_data(json_file_content: str): # Rimosso user_site_code
120
  st.title("Convertitore JSON Oda a Template Excel Oda")
121
  st.write("Carica i tuoi file JSON degli ordini ODA e scarica il foglio Excel formattato.")
122
 
123
- # Rimosso l'input del Site Code, ora viene letto dal JSON
124
  st.markdown("**(Il Site Code verrà letto direttamente dal JSON)**")
125
 
126
  st.header("1. Carica i tuoi file JSON")
@@ -150,7 +147,6 @@ if uploaded_files:
150
  json_content_bytes = uploaded_file.read()
151
  json_content_string = json_content_bytes.decode('utf-8')
152
 
153
- # Chiamata alla funzione senza user_site_code
154
  df_this_file = convert_json_to_excel_data(json_content_string)
155
 
156
  if df_this_file is not None:
@@ -166,17 +162,43 @@ if uploaded_files:
166
  final_df = pd.concat(all_processed_data, ignore_index=True)
167
  st.success(f"Elaborazione di {len(all_processed_data)} file JSON completata! Pronto per il download.")
168
 
 
 
 
169
  final_df['positions.stock.cancelPosOda'] = final_df['positions.stock.cancelPosOda'].apply(lambda x: str(x).capitalize())
170
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
  output = io.BytesIO()
172
  writer = pd.ExcelWriter(output, engine='xlsxwriter')
173
 
174
  sheet_name_excel = 'PurchaseOrder'
175
- final_df.to_excel(writer, sheet_name=sheet_name_excel, index=False)
176
 
177
  workbook = writer.book
178
- worksheet = writer.sheets[sheet_name_excel]
179
-
 
 
180
  # Lista delle colonne finali nell'ordine desiderato
181
  final_columns_order = [
182
  'site.code',
@@ -194,22 +216,27 @@ if uploaded_files:
194
  'positions.stock.accountingInfo.costCenter',
195
  'positions.stock.accountingInfo.availability',
196
  'positions.stock.item.company.code',
197
- 'positions.spare.string1', # Nome modificato
198
- 'positions.stock.reasonCode',
199
  'positions.reason.company.code',
200
  'positions.stock.cancelPosOda'
201
  ]
202
 
203
- cols_present_and_ordered = [col for col in final_columns_order if col in final_df.columns]
204
- final_df = final_df[cols_present_and_ordered]
 
 
 
 
205
 
 
206
  col_widths = {
207
  'site.code': 10,
208
  'docNumber': 15,
209
  'company.code': 15,
210
  'supplier.partnerRef.code': 18,
211
  'supplier.partnerRef.company.code': 25,
212
- 'docDate': 12,
213
  'status': 10,
214
  'positions.status': 12,
215
  'positions.positionId': 12,
@@ -220,17 +247,24 @@ if uploaded_files:
220
  'positions.stock.accountingInfo.availability': 15,
221
  'positions.stock.item.company.code': 25,
222
  'positions.spare.string1': 15,
223
- 'positions.stock.reasonCode': 15,
224
  'positions.reason.company.code': 25,
225
  'positions.stock.cancelPosOda': 18
226
  }
227
 
 
228
  for col_num, col_name in enumerate(final_df.columns.values):
229
- worksheet.write(0, col_num, col_name)
 
 
230
  if col_name in col_widths:
231
  worksheet.set_column(col_num, col_num, col_widths[col_name])
232
  else:
233
- worksheet.set_column(col_num, col_num, 15)
 
 
 
 
234
 
235
  writer.close()
236
  output.seek(0)
@@ -249,12 +283,11 @@ if uploaded_files:
249
  else:
250
  st.info("Nessun dato valido estratto dai file selezionati.")
251
  else:
252
- st.info("Carica i tuoi file JSON per iniziare. I file devono essere della stessa tipologia!")
253
 
254
  # --- Funzione per il reset ---
255
  def clear_inputs():
256
  st.session_state.file_uploader_key += 1 # Invalida la chiave del file_uploader
257
- # Rimosso st.session_state.site_code_input = "" perché l'input non c'è più
258
 
259
  st.markdown("---")
260
  st.button("Pulisci Input (RESET)", on_click=clear_inputs)
 
6
  import os
7
 
8
  # --- Inizializzazione Session State ---
 
9
  if 'file_uploader_key' not in st.session_state:
10
  st.session_state.file_uploader_key = 0
11
 
 
36
  }
37
  </style>
38
  """,
39
+ unsafe_allow_html=True
40
  )
41
 
42
  # Funzione di conversione
43
+ def convert_json_to_excel_data(json_file_content: str):
44
  try:
45
  json_data = json.loads(json_file_content)
46
 
 
47
  company_code = json_data.get('companyCode')
48
+ site_code_json = json_data.get('siteCode')
49
 
50
  order_info = json_data.get('order', {})
51
 
 
52
  doc_number = order_info.get('orderNumber')
53
  partner_code = order_info.get('partnerCode')
54
 
 
58
  if order_date_str:
59
  try:
60
  dt_object = datetime.fromisoformat(order_date_str.replace('Z', '+00:00'))
61
+ # Formattazione per includere data e ora
62
+ order_date_formatted = dt_object.strftime('%d/%m/%Y %H:%M:%S')
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.")
 
77
  cancel_pos_oda_processed = bool(cancel_pos_oda_val)
78
 
79
  row = {
80
+ 'site.code': site_code_json,
81
  'docNumber': doc_number,
82
  'company.code': company_code,
83
  'supplier.partnerRef.code': partner_code,
 
92
  'positions.stock.accountingInfo.costCenter': item.get('warehouse'),
93
  'positions.stock.accountingInfo.availability': item.get('availability'),
94
  'positions.stock.item.company.code': company_code,
95
+ 'positions.spare.string1': item.get('refOrder'),
96
+ 'positions.reason.code': item.get('reasonCode'), # Naming corretto
97
  'positions.reason.company.code': company_code,
98
  'positions.stock.cancelPosOda': cancel_pos_oda_processed
99
  }
 
118
  st.title("Convertitore JSON Oda a Template Excel Oda")
119
  st.write("Carica i tuoi file JSON degli ordini ODA e scarica il foglio Excel formattato.")
120
 
 
121
  st.markdown("**(Il Site Code verrà letto direttamente dal JSON)**")
122
 
123
  st.header("1. Carica i tuoi file JSON")
 
147
  json_content_bytes = uploaded_file.read()
148
  json_content_string = json_content_bytes.decode('utf-8')
149
 
 
150
  df_this_file = convert_json_to_excel_data(json_content_string)
151
 
152
  if df_this_file is not None:
 
162
  final_df = pd.concat(all_processed_data, ignore_index=True)
163
  st.success(f"Elaborazione di {len(all_processed_data)} file JSON completata! Pronto per il download.")
164
 
165
+ # --- Post-processing per la formattazione Excel ---
166
+
167
+ # 1. Gestione di cancelPosOda per avere "True" o "False" come stringhe
168
  final_df['positions.stock.cancelPosOda'] = final_df['positions.stock.cancelPosOda'].apply(lambda x: str(x).capitalize())
169
 
170
+ # 2. Definizione delle colonne di testata
171
+ header_columns = [
172
+ 'site.code', 'docNumber', 'company.code', 'supplier.partnerRef.code',
173
+ 'supplier.partnerRef.company.code', 'docDate', 'status'
174
+ ]
175
+
176
+ # 3. Ordina il DataFrame per docNumber e positionId per raggruppare gli ordini
177
+ final_df = final_df.sort_values(by=['docNumber', 'positions.positionId']).reset_index(drop=True)
178
+
179
+ # 4. Crea una maschera booleana per identificare le righe duplicate per docNumber
180
+ # (cioè tutte le righe tranne la prima per ogni orderNumber)
181
+ # Keep='first' significa che la prima occorrenza di ogni docNumber sarà False (non duplicata)
182
+ # e tutte le successive saranno True (duplicate).
183
+ # Vogliamo azzerare i campi di testata solo per le righe True.
184
+ rows_to_clear_headers = final_df.duplicated(subset=['docNumber'], keep='first')
185
+
186
+ # 5. Azzerare le colonne di testata per le righe identificate
187
+ # Usiamo .loc per modificare il DataFrame in modo sicuro
188
+ final_df.loc[rows_to_clear_headers, header_columns] = ""
189
+
190
+ # --- Creazione file Excel ---
191
  output = io.BytesIO()
192
  writer = pd.ExcelWriter(output, engine='xlsxwriter')
193
 
194
  sheet_name_excel = 'PurchaseOrder'
195
+ # Non scriviamo ancora su excel, lo faremo manualmente per la riga 1 e 2
196
 
197
  workbook = writer.book
198
+ worksheet = writer.sheets.get(sheet_name_excel) # Ottieni il worksheet se esiste, altrimenti crealo
199
+ if worksheet is None:
200
+ worksheet = workbook.add_worksheet(sheet_name_excel)
201
+
202
  # Lista delle colonne finali nell'ordine desiderato
203
  final_columns_order = [
204
  'site.code',
 
216
  'positions.stock.accountingInfo.costCenter',
217
  'positions.stock.accountingInfo.availability',
218
  'positions.stock.item.company.code',
219
+ 'positions.spare.string1',
220
+ 'positions.reason.code', # Naming corretto
221
  'positions.reason.company.code',
222
  'positions.stock.cancelPosOda'
223
  ]
224
 
225
+ # Assicurati che il DataFrame abbia tutte le colonne nell'ordine desiderato
226
+ # e aggiungi quelle mancanti come stringhe vuote se necessario, anche se non dovrebbero mancare
227
+ for col in final_columns_order:
228
+ if col not in final_df.columns:
229
+ final_df[col] = "" # Aggiungi colonne mancanti come vuote
230
+ final_df = final_df[final_columns_order]
231
 
232
+ # Larghezze delle colonne aggiornate
233
  col_widths = {
234
  'site.code': 10,
235
  'docNumber': 15,
236
  'company.code': 15,
237
  'supplier.partnerRef.code': 18,
238
  'supplier.partnerRef.company.code': 25,
239
+ 'docDate': 20, # Aumentata per data e ora
240
  'status': 10,
241
  'positions.status': 12,
242
  'positions.positionId': 12,
 
247
  'positions.stock.accountingInfo.availability': 15,
248
  'positions.stock.item.company.code': 25,
249
  'positions.spare.string1': 15,
250
+ 'positions.reason.code': 15, # Naming corretto
251
  'positions.reason.company.code': 25,
252
  'positions.stock.cancelPosOda': 18
253
  }
254
 
255
+ # Scrivi i nomi delle colonne nella riga 2 (indice 1 in xlsxwriter)
256
  for col_num, col_name in enumerate(final_df.columns.values):
257
+ worksheet.write(1, col_num, col_name) # Scrivi header in riga 2
258
+
259
+ # Imposta le larghezze delle colonne
260
  if col_name in col_widths:
261
  worksheet.set_column(col_num, col_num, col_widths[col_name])
262
  else:
263
+ worksheet.set_column(col_num, col_num, 15) # Larghezza di default
264
+
265
+ # Scrivi i dati a partire dalla riga 3 (indice 2 in xlsxwriter)
266
+ # header=False per evitare che to_excel scriva gli header (li abbiamo già scritti noi)
267
+ final_df.to_excel(writer, sheet_name=sheet_name_excel, index=False, header=False, startrow=2)
268
 
269
  writer.close()
270
  output.seek(0)
 
283
  else:
284
  st.info("Nessun dato valido estratto dai file selezionati.")
285
  else:
286
+ st.info("Carica i tuoi file JSON per iniziare.")
287
 
288
  # --- Funzione per il reset ---
289
  def clear_inputs():
290
  st.session_state.file_uploader_key += 1 # Invalida la chiave del file_uploader
 
291
 
292
  st.markdown("---")
293
  st.button("Pulisci Input (RESET)", on_click=clear_inputs)