Ankushbl6 commited on
Commit
5ae15b4
·
verified ·
1 Parent(s): e9a09af

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +83 -68
src/streamlit_app.py CHANGED
@@ -1176,21 +1176,59 @@ elif len(st.session_state.batch_results) > 0:
1176
  "Quantity": it.get("Quantity", it.get("Item Quantity", 0)),
1177
  "Unit Price": it.get("Unit Price", it.get("Item Unit Price", 0.0)),
1178
  "Amount": it.get("Amount", it.get("Item Amount", 0.0)),
 
1179
  "Tax": it.get("Tax", it.get("Item Tax", 0.0)),
1180
  "Line Total": it.get("Line Total", it.get("Item Line Total", 0.0)),
1181
  })
1182
 
1183
  items_df = pd.DataFrame(normalized) if normalized else pd.DataFrame(
1184
- columns=["Description", "Quantity", "Unit Price", "Amount", "Tax", "Line Total"]
1185
  )
1186
 
1187
- # Show editor without totals
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1188
  edited_df = st.data_editor(
1189
  items_df,
1190
  num_rows="dynamic",
1191
  key=f"items_editor_{selected_hash}",
1192
  use_container_width=True,
1193
  height=DATA_EDITOR_HEIGHT - 50, # Reduce height slightly for totals below
 
1194
  )
1195
 
1196
  # Display non-editable totals row immediately below (looks integrated)
@@ -1205,6 +1243,7 @@ elif len(st.session_state.batch_results) > 0:
1205
  "Quantity": "",
1206
  "Unit Price": "",
1207
  "Amount": f"${total_amount:,.2f}",
 
1208
  "Tax": f"${total_tax:,.2f}",
1209
  "Line Total": f"${total_line_total:,.2f}"
1210
  }])
@@ -1219,40 +1258,42 @@ elif len(st.session_state.batch_results) > 0:
1219
  saved = st.form_submit_button("💾 Save All Edits")
1220
  # ----------------- FORM END -----------------
1221
 
1222
- if saved:
1223
- currency = st.session_state.get(f"Currency_{selected_hash}", 'USD')
1224
- if currency == 'Other':
1225
- currency = st.session_state.get(f"Currency_Custom_{selected_hash}", '')
1226
 
1227
- # Convert date objects to normalized strings (dd-MMM-yyyy format)
1228
- invoice_date = st.session_state.get(f"Invoice Date_{selected_hash}", None)
1229
- due_date = st.session_state.get(f"Due Date_{selected_hash}", None)
1230
 
1231
- invoice_date_str = ""
1232
- if invoice_date is not None:
1233
- try:
1234
- invoice_date_str = invoice_date.strftime("%d-%b-%Y")
1235
- except (AttributeError, ValueError):
1236
- invoice_date_str = ""
1237
 
1238
- due_date_str = ""
1239
- if due_date is not None:
1240
- try:
1241
- due_date_str = due_date.strftime("%d-%b-%Y")
1242
- except (AttributeError, ValueError):
1243
- due_date_str = ""
1244
 
1245
- # Calculate totals from line items
1246
- line_items_list = edited_df.to_dict('records')
1247
- calculated_subtotal = sum(clean_float(item.get('Amount', 0)) for item in line_items_list)
1248
- calculated_total_tax = sum(clean_float(item.get('Tax', 0)) for item in line_items_list)
1249
- calculated_total = sum(clean_float(item.get('Line Total', 0)) for item in line_items_list)
1250
 
1251
- # Calculate tax percentage if possible
1252
- calculated_tax_pct = 0.0
1253
- if calculated_subtotal > 0 and calculated_total_tax > 0:
1254
- calculated_tax_pct = round((calculated_total_tax / calculated_subtotal) * 100, 4)
1255
 
 
 
1256
  updated = {
1257
  'Invoice Number': st.session_state.get(f"Invoice Number_{selected_hash}", ''),
1258
  'Invoice Date': invoice_date_str,
@@ -1282,48 +1323,22 @@ elif len(st.session_state.batch_results) > 0:
1282
  "Address": st.session_state.get(f"Recipient Address_{selected_hash}", '')},
1283
  }
1284
 
1285
- # Update session state fields to reflect the new calculated values
1286
- st.session_state[f"Subtotal_{selected_hash}"] = calculated_subtotal
1287
- st.session_state[f"Tax Percentage_{selected_hash}"] = calculated_tax_pct
1288
- st.session_state[f"Total Tax_{selected_hash}"] = calculated_total_tax
1289
- st.session_state[f"Total Amount_{selected_hash}"] = calculated_total
1290
-
1291
  st.session_state.batch_results[selected_hash]["edited_data"] = updated
 
 
1292
  st.success(f"✅ Saved: {current['file_name']} | Updated totals: Subtotal=${calculated_subtotal:,.2f}, Tax=${calculated_total_tax:,.2f}, Total=${calculated_total:,.2f}")
1293
- # REMOVED st.rerun() - This was causing the download button to disappear
1294
-
1295
- # Per-file CSV download (MOVED OUTSIDE THE FORM - Always visible)
1296
- d_currency = st.session_state.get(f"Currency_{selected_hash}", 'USD')
1297
- if d_currency == 'Other':
1298
- d_currency = st.session_state.get(f"Currency_Custom_{selected_hash}", '')
1299
-
1300
- # Convert date objects to strings for download
1301
- d_invoice_date = st.session_state.get(f"Invoice Date_{selected_hash}", None)
1302
- d_due_date = st.session_state.get(f"Due Date_{selected_hash}", None)
1303
-
1304
- d_invoice_date_str = ""
1305
- if d_invoice_date is not None:
1306
- try:
1307
- d_invoice_date_str = d_invoice_date.strftime("%d-%b-%Y")
1308
- except (AttributeError, ValueError):
1309
- d_invoice_date_str = ""
1310
-
1311
- d_due_date_str = ""
1312
- if d_due_date is not None:
1313
- try:
1314
- d_due_date_str = d_due_date.strftime("%d-%b-%Y")
1315
- except (AttributeError, ValueError):
1316
- d_due_date_str = ""
1317
 
 
1318
  download_data = {
1319
  'Invoice Number': st.session_state.get(f"Invoice Number_{selected_hash}", ''),
1320
- 'Invoice Date': d_invoice_date_str,
1321
- 'Due Date': d_due_date_str,
1322
- 'Currency': d_currency,
1323
- 'Subtotal': st.session_state.get(f"Subtotal_{selected_hash}", 0.0),
1324
- 'Tax Percentage': st.session_state.get(f"Tax Percentage_{selected_hash}", 0.0),
1325
- 'Total Tax': st.session_state.get(f"Total Tax_{selected_hash}", 0.0),
1326
- 'Total Amount': st.session_state.get(f"Total Amount_{selected_hash}", 0.0),
1327
  'Sender Name': st.session_state.get(f"Sender Name_{selected_hash}", ''),
1328
  'Sender Address': st.session_state.get(f"Sender Address_{selected_hash}", ''),
1329
  'Recipient Name': st.session_state.get(f"Recipient Name_{selected_hash}", ''),
@@ -1337,7 +1352,7 @@ elif len(st.session_state.batch_results) > 0:
1337
  'bank_routing': st.session_state.get(f"Bank_bank_routing_{selected_hash}", ''),
1338
  'bank_branch': st.session_state.get(f"Bank_bank_branch_{selected_hash}", '')
1339
  },
1340
- 'Itemized Data': edited_df.to_dict('records')
1341
  }
1342
  rows = flatten_invoice_to_rows(download_data)
1343
  full_df = pd.DataFrame(rows)
 
1176
  "Quantity": it.get("Quantity", it.get("Item Quantity", 0)),
1177
  "Unit Price": it.get("Unit Price", it.get("Item Unit Price", 0.0)),
1178
  "Amount": it.get("Amount", it.get("Item Amount", 0.0)),
1179
+ "IO Number/Cost Centre": it.get("IO Number/Cost Centre", ""), # New column
1180
  "Tax": it.get("Tax", it.get("Item Tax", 0.0)),
1181
  "Line Total": it.get("Line Total", it.get("Item Line Total", 0.0)),
1182
  })
1183
 
1184
  items_df = pd.DataFrame(normalized) if normalized else pd.DataFrame(
1185
+ columns=["Description", "Quantity", "Unit Price", "Amount", "IO Number/Cost Centre", "Tax", "Line Total"]
1186
  )
1187
 
1188
+ # Configure column widths to make Description wider and avoid horizontal scrolling
1189
+ column_config = {
1190
+ "Description": st.column_config.TextColumn(
1191
+ "Description",
1192
+ width="large", # Make description column wider
1193
+ ),
1194
+ "Quantity": st.column_config.NumberColumn(
1195
+ "Quantity",
1196
+ width="small",
1197
+ ),
1198
+ "Unit Price": st.column_config.NumberColumn(
1199
+ "Unit Price",
1200
+ width="small",
1201
+ format="%.2f"
1202
+ ),
1203
+ "Amount": st.column_config.NumberColumn(
1204
+ "Amount",
1205
+ width="small",
1206
+ format="%.2f"
1207
+ ),
1208
+ "IO Number/Cost Centre": st.column_config.TextColumn(
1209
+ "IO Number/Cost Centre",
1210
+ width="medium",
1211
+ ),
1212
+ "Tax": st.column_config.NumberColumn(
1213
+ "Tax",
1214
+ width="small",
1215
+ format="%.2f"
1216
+ ),
1217
+ "Line Total": st.column_config.NumberColumn(
1218
+ "Line Total",
1219
+ width="small",
1220
+ format="%.2f"
1221
+ ),
1222
+ }
1223
+
1224
+ # Show editor without totals - no horizontal scrolling
1225
  edited_df = st.data_editor(
1226
  items_df,
1227
  num_rows="dynamic",
1228
  key=f"items_editor_{selected_hash}",
1229
  use_container_width=True,
1230
  height=DATA_EDITOR_HEIGHT - 50, # Reduce height slightly for totals below
1231
+ column_config=column_config,
1232
  )
1233
 
1234
  # Display non-editable totals row immediately below (looks integrated)
 
1243
  "Quantity": "",
1244
  "Unit Price": "",
1245
  "Amount": f"${total_amount:,.2f}",
1246
+ "IO Number/Cost Centre": "", # Empty for totals row
1247
  "Tax": f"${total_tax:,.2f}",
1248
  "Line Total": f"${total_line_total:,.2f}"
1249
  }])
 
1258
  saved = st.form_submit_button("💾 Save All Edits")
1259
  # ----------------- FORM END -----------------
1260
 
1261
+ # Calculate current values for display and download (always, not just on save)
1262
+ currency = st.session_state.get(f"Currency_{selected_hash}", 'USD')
1263
+ if currency == 'Other':
1264
+ currency = st.session_state.get(f"Currency_Custom_{selected_hash}", '')
1265
 
1266
+ # Convert date objects to normalized strings (dd-MMM-yyyy format)
1267
+ invoice_date = st.session_state.get(f"Invoice Date_{selected_hash}", None)
1268
+ due_date = st.session_state.get(f"Due Date_{selected_hash}", None)
1269
 
1270
+ invoice_date_str = ""
1271
+ if invoice_date is not None:
1272
+ try:
1273
+ invoice_date_str = invoice_date.strftime("%d-%b-%Y")
1274
+ except (AttributeError, ValueError):
1275
+ invoice_date_str = ""
1276
 
1277
+ due_date_str = ""
1278
+ if due_date is not None:
1279
+ try:
1280
+ due_date_str = due_date.strftime("%d-%b-%Y")
1281
+ except (AttributeError, ValueError):
1282
+ due_date_str = ""
1283
 
1284
+ # Calculate totals from line items (always, for both save and download)
1285
+ line_items_list = edited_df.to_dict('records')
1286
+ calculated_subtotal = sum(clean_float(item.get('Amount', 0)) for item in line_items_list)
1287
+ calculated_total_tax = sum(clean_float(item.get('Tax', 0)) for item in line_items_list)
1288
+ calculated_total = sum(clean_float(item.get('Line Total', 0)) for item in line_items_list)
1289
 
1290
+ # Calculate tax percentage if possible
1291
+ calculated_tax_pct = 0.0
1292
+ if calculated_subtotal > 0 and calculated_total_tax > 0:
1293
+ calculated_tax_pct = round((calculated_total_tax / calculated_subtotal) * 100, 4)
1294
 
1295
+ if saved:
1296
+ # Build updated data structure
1297
  updated = {
1298
  'Invoice Number': st.session_state.get(f"Invoice Number_{selected_hash}", ''),
1299
  'Invoice Date': invoice_date_str,
 
1323
  "Address": st.session_state.get(f"Recipient Address_{selected_hash}", '')},
1324
  }
1325
 
1326
+ # Save to batch_results (this persists the data)
 
 
 
 
 
1327
  st.session_state.batch_results[selected_hash]["edited_data"] = updated
1328
+
1329
+ # Show success message
1330
  st.success(f"✅ Saved: {current['file_name']} | Updated totals: Subtotal=${calculated_subtotal:,.2f}, Tax=${calculated_total_tax:,.2f}, Total=${calculated_total:,.2f}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1331
 
1332
+ # Per-file CSV download (ALWAYS visible, uses current edited values)
1333
  download_data = {
1334
  'Invoice Number': st.session_state.get(f"Invoice Number_{selected_hash}", ''),
1335
+ 'Invoice Date': invoice_date_str,
1336
+ 'Due Date': due_date_str,
1337
+ 'Currency': currency,
1338
+ 'Subtotal': calculated_subtotal, # Use calculated value
1339
+ 'Tax Percentage': calculated_tax_pct, # Use calculated value
1340
+ 'Total Tax': calculated_total_tax, # Use calculated value
1341
+ 'Total Amount': calculated_total, # Use calculated value
1342
  'Sender Name': st.session_state.get(f"Sender Name_{selected_hash}", ''),
1343
  'Sender Address': st.session_state.get(f"Sender Address_{selected_hash}", ''),
1344
  'Recipient Name': st.session_state.get(f"Recipient Name_{selected_hash}", ''),
 
1352
  'bank_routing': st.session_state.get(f"Bank_bank_routing_{selected_hash}", ''),
1353
  'bank_branch': st.session_state.get(f"Bank_bank_branch_{selected_hash}", '')
1354
  },
1355
+ 'Itemized Data': line_items_list
1356
  }
1357
  rows = flatten_invoice_to_rows(download_data)
1358
  full_df = pd.DataFrame(rows)