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

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +135 -120
src/streamlit_app.py CHANGED
@@ -6,56 +6,53 @@ import io
6
  import os
7
 
8
  # --- Inizializzazione Session State ---
9
- # Per il text_input 'site_code_input'
10
- if 'site_code_input' not in st.session_state:
11
- st.session_state.site_code_input = ""
12
-
13
- # Per il file_uploader, useremo una chiave che cambia per forzare il reset
14
  if 'file_uploader_key' not in st.session_state:
15
- st.session_state.file_uploader_key = 0 # Inizializziamo con un numero intero
16
 
17
  # --- CSS personalizzato per sfondo giallo e testo blu ---
18
  st.markdown(
19
  """
20
  <style>
21
- /* Colore di sfondo dell'intera app (giallo) */
22
  .stApp {
23
- background-color: #FFFFCC; /* Giallo pastello, puoi cambiare il codice esadecimale */
24
  background-attachment: fixed;
25
  }
26
- /* Colore per i titoli (blu) */
27
  h1, h2 {
28
- color: #1E90FF; /* Blu acceso */
29
  }
30
- /* Colore per il testo normale e le etichette (blu scuro/navy) */
31
  p, label {
32
- color: #000080; /* Blu scuro */
33
  }
34
- /* Stili per i bottoni (per coerenza) */
35
  .stButton>button {
36
  color: white;
37
- background-color: #1E90FF; /* Blu acceso */
38
  border: none;
39
  border-radius: 5px;
40
  padding: 10px 20px;
41
  font-size: 16px;
42
  }
43
  .stButton>button:hover {
44
- background-color: #4169E1; /* Blu medio al passaggio del mouse */
45
  }
46
  </style>
47
  """,
48
  unsafe_allow_html=True # QUESTA RIGA DEVE ESSERCI
49
  )
50
 
51
-
52
  # Funzione di conversione
53
- def convert_json_to_excel_data(json_file_content: str):
54
  try:
55
  json_data = json.loads(json_file_content)
56
 
 
57
  company_code = json_data.get('companyCode')
 
 
58
  order_info = json_data.get('order', {})
 
 
 
59
  partner_code = order_info.get('partnerCode')
60
 
61
  order_date_str = order_info.get('orderDate')
@@ -82,8 +79,11 @@ def convert_json_to_excel_data(json_file_content: str):
82
  cancel_pos_oda_processed = bool(cancel_pos_oda_val)
83
 
84
  row = {
 
 
85
  'company.code': company_code,
86
  'supplier.partnerRef.code': partner_code,
 
87
  'docDate': order_date_formatted,
88
  'status': 'CREATED',
89
  'positions.status': 'CREATED',
@@ -93,8 +93,10 @@ def convert_json_to_excel_data(json_file_content: str):
93
  'positions.stock.accountingInfo.stockOwner': item.get('stockOwner'),
94
  'positions.stock.accountingInfo.costCenter': item.get('warehouse'),
95
  'positions.stock.accountingInfo.availability': item.get('availability'),
96
- 'positions.stock.refOrder': item.get('refOrder'),
 
97
  'positions.stock.reasonCode': item.get('reasonCode'),
 
98
  'positions.stock.cancelPosOda': cancel_pos_oda_processed
99
  }
100
  processed_data_for_this_file.append(row)
@@ -118,128 +120,141 @@ def convert_json_to_excel_data(json_file_content: str):
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
- # Sezione per l'input del solo siteCode
122
- st.header("1. Qual è il Site Code? Inseriscilo qui:")
123
- user_site_code = st.text_input("Site Code", key="site_code_input")
124
 
125
- st.header("2. Carica i tuoi file JSON")
126
- # Passiamo la chiave dinamica al file_uploader
127
  uploaded_files = st.file_uploader(
128
- "Scegli uno o più file JSON per lo stesso siteCode di tipo 'Ordine_Acquisto'",
129
  type=["json"],
130
  accept_multiple_files=True,
131
- key=st.session_state.file_uploader_key # Usa la chiave dinamica qui
132
  )
133
 
134
  all_processed_data = []
135
 
136
  if uploaded_files:
137
- if not user_site_code:
138
- st.warning("Per favor, compila il campo 'Site Code' prima di caricare i file.")
139
- else:
140
- st.info(f"Caricati {len(uploaded_files)} file. Elaborazione in corso...")
 
 
141
 
142
- conversion_successful = True
 
 
 
143
 
144
- for uploaded_file in uploaded_files:
145
- file_name = uploaded_file.name
146
-
147
- if not file_name.lower().startswith("ordine_acquisto"):
148
- st.error(f"Errore: Il file '{file_name}' non inizia con 'Ordine_Acquisto'. Verrà ignorato.")
149
- conversion_successful = False
150
- continue
151
 
152
- try:
153
- json_content_bytes = uploaded_file.read()
154
- json_content_string = json_content_bytes.decode('utf-8')
155
-
156
- df_this_file = convert_json_to_excel_data(json_content_string)
157
-
158
- if df_this_file is not None:
159
- df_this_file['site.code'] = user_site_code
160
-
161
- final_columns_order = [
162
- 'site.code', 'docDate', 'company.code', 'supplier.partnerRef.code',
163
- 'status',
164
- 'positions.status', 'positions.positionId',
165
- 'positions.stock.item.itemNumber', 'positions.stock.quantity',
166
- 'positions.stock.accountingInfo.stockOwner',
167
- 'positions.stock.accountingInfo.costCenter', 'positions.stock.accountingInfo.availability',
168
- 'positions.stock.refOrder', 'positions.stock.reasonCode', 'positions.stock.cancelPosOda'
169
- ]
170
-
171
- cols_present_and_ordered = [col for col in final_columns_order if col in df_this_file.columns]
172
- df_this_file = df_this_file[cols_present_and_ordered]
173
-
174
- all_processed_data.append(df_this_file)
175
- else:
176
- conversion_successful = False
177
- st.error(f"Impossibile convertire il file '{file_name}'. Controlla i log per i dettagli.")
178
- except Exception as e:
179
- st.error(f"Si è verificato un errore imprevisto durante la lettura o l'elaborazione del file '{file_name}': {e}")
180
  conversion_successful = False
 
 
 
 
181
 
182
- if all_processed_data:
183
- final_df = pd.concat(all_processed_data, ignore_index=True)
184
- st.success(f"Elaborazione di {len(all_processed_data)} file JSON completata! Pronto per il download.")
185
-
186
- # --- Gestione di cancelPosOda per avere "True" o "False" come stringhe ---
187
- # Mappa i valori booleani Python in stringhe "True" o "False"
188
- final_df['positions.stock.cancelPosOda'] = final_df['positions.stock.cancelPosOda'].apply(lambda x: str(x).capitalize())
189
 
190
- output = io.BytesIO()
191
- writer = pd.ExcelWriter(output, engine='xlsxwriter')
192
-
193
- sheet_name_excel = 'PurchaseOrder'
194
- final_df.to_excel(writer, sheet_name=sheet_name_excel, index=False)
195
 
196
- workbook = writer.book
197
- worksheet = writer.sheets[sheet_name_excel]
198
-
199
- col_widths = {
200
- 'site.code': 10, 'docDate': 12, 'company.code': 15, 'supplier.partnerRef.code': 18,
201
- 'status': 10,
202
- 'positions.status': 12, 'positions.positionId': 12,
203
- 'positions.stock.item.itemNumber': 25, 'positions.stock.quantity': 10,
204
- 'positions.stock.accountingInfo.stockOwner': 18,
205
- 'positions.stock.accountingInfo.costCenter': 18,
206
- 'positions.stock.accountingInfo.availability': 15,
207
- 'positions.stock.refOrder': 15, 'positions.stock.reasonCode': 15,
208
- 'positions.stock.cancelPosOda': 18
209
- }
210
-
211
- for col_num, col_name in enumerate(final_df.columns.values):
212
- worksheet.write(0, col_num, col_name)
213
- if col_name in col_widths:
214
- worksheet.set_column(col_num, col_num, col_widths[col_name])
215
- else:
216
- worksheet.set_column(col_num, col_num, 15)
217
-
218
- writer.close()
219
- output.seek(0)
220
-
221
- timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
222
- output_file_name = f"PurchaseOrder_{timestamp}.xlsx"
223
-
224
- st.download_button(
225
- label="Scarica file Excel Unificato",
226
- data=output.getvalue(),
227
- file_name=output_file_name,
228
- mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
229
- )
230
- elif not conversion_successful:
231
- st.error("Nessun file valido è stato elaborato con successo. Controlla i messaggi di errore sopra.")
232
- else:
233
- st.info("Nessun dato valido estratto dai file selezionati.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
234
  else:
235
  st.info("Carica i tuoi file JSON per iniziare. I file devono essere della stessa tipologia!")
236
 
237
-
238
- # --- Funzione per il reset: incrementa la chiave del file_uploader ---
239
  def clear_inputs():
240
- st.session_state.file_uploader_key += 1 # Invalida la chiave del file_uploader, forzandone il reset
241
- st.session_state.site_code_input = "" # Resetta il campo Site Code
242
- st.rerun() # Forza un rerun per applicare i cambiamenti immediatamente
243
 
244
  st.markdown("---")
245
  st.button("Pulisci Input (RESET)", on_click=clear_inputs)
 
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
 
13
  # --- CSS personalizzato per sfondo giallo e testo blu ---
14
  st.markdown(
15
  """
16
  <style>
 
17
  .stApp {
18
+ background-color: #FFFFCC;
19
  background-attachment: fixed;
20
  }
 
21
  h1, h2 {
22
+ color: #1E90FF;
23
  }
 
24
  p, label {
25
+ color: #000080;
26
  }
 
27
  .stButton>button {
28
  color: white;
29
+ background-color: #1E90FF;
30
  border: none;
31
  border-radius: 5px;
32
  padding: 10px 20px;
33
  font-size: 16px;
34
  }
35
  .stButton>button:hover {
36
+ background-color: #4169E1;
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
 
58
  order_date_str = order_info.get('orderDate')
 
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,
86
+ 'supplier.partnerRef.company.code': company_code,
87
  'docDate': order_date_formatted,
88
  'status': 'CREATED',
89
  'positions.status': 'CREATED',
 
93
  'positions.stock.accountingInfo.stockOwner': item.get('stockOwner'),
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
  }
102
  processed_data_for_this_file.append(row)
 
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")
 
127
  uploaded_files = st.file_uploader(
128
+ "Scegli uno o più file JSON di tipo 'Ordine_Acquisto'",
129
  type=["json"],
130
  accept_multiple_files=True,
131
+ key=st.session_state.file_uploader_key
132
  )
133
 
134
  all_processed_data = []
135
 
136
  if uploaded_files:
137
+ st.info(f"Caricati {len(uploaded_files)} file. Elaborazione in corso...")
138
+
139
+ conversion_successful = True
140
+
141
+ for uploaded_file in uploaded_files:
142
+ file_name = uploaded_file.name
143
 
144
+ if not file_name.lower().startswith("ordine_acquisto"):
145
+ st.error(f"Errore: Il file '{file_name}' non inizia con 'Ordine_Acquisto'. Verrà ignorato.")
146
+ conversion_successful = False
147
+ continue
148
 
149
+ try:
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:
157
+ all_processed_data.append(df_this_file)
158
+ else:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
  conversion_successful = False
160
+ st.error(f"Impossibile convertire il file '{file_name}'. Controlla i log per i dettagli.")
161
+ except Exception as e:
162
+ st.error(f"Si è verificato un errore imprevisto durante la lettura o l'elaborazione del file '{file_name}': {e}")
163
+ conversion_successful = False
164
 
165
+ if all_processed_data:
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',
183
+ 'docNumber',
184
+ 'company.code',
185
+ 'supplier.partnerRef.code',
186
+ 'supplier.partnerRef.company.code',
187
+ 'docDate',
188
+ 'status',
189
+ 'positions.status',
190
+ 'positions.positionId',
191
+ 'positions.stock.item.itemNumber',
192
+ 'positions.stock.quantity',
193
+ 'positions.stock.accountingInfo.stockOwner',
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,
216
+ 'positions.stock.item.itemNumber': 25,
217
+ 'positions.stock.quantity': 10,
218
+ 'positions.stock.accountingInfo.stockOwner': 18,
219
+ 'positions.stock.accountingInfo.costCenter': 18,
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)
237
+
238
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
239
+ output_file_name = f"PurchaseOrder_{timestamp}.xlsx"
240
+
241
+ st.download_button(
242
+ label="Scarica file Excel Unificato",
243
+ data=output.getvalue(),
244
+ file_name=output_file_name,
245
+ mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
246
+ )
247
+ elif not conversion_successful:
248
+ st.error("Nessun file valido è stato elaborato con successo. Controlla i messaggi di errore sopra.")
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)