mousom commited on
Commit
9847bda
·
verified ·
1 Parent(s): 7390c56

Upload folder using huggingface_hub

Browse files
Files changed (3) hide show
  1. README.md +3 -9
  2. app.py +350 -0
  3. requirements.txt +3 -0
README.md CHANGED
@@ -1,12 +1,6 @@
1
  ---
2
- title: Huggingface Deployment
3
- emoji: 📈
4
- colorFrom: green
5
- colorTo: purple
6
- sdk: gradio
7
- sdk_version: 5.42.0
8
  app_file: app.py
9
- pinned: false
 
10
  ---
11
-
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: huggingface-deployment
 
 
 
 
 
3
  app_file: app.py
4
+ sdk: gradio
5
+ sdk_version: 5.6.0
6
  ---
 
 
app.py ADDED
@@ -0,0 +1,350 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import requests
3
+ import pandas as pd
4
+ from typing import Dict, List, Optional, Tuple
5
+ import json
6
+
7
+ # Base URL for the API
8
+ BASE_URL = "https://gljx3devrf.execute-api.us-west-1.amazonaws.com/prod/"
9
+
10
+ class ContractPaymentViewer:
11
+ def __init__(self):
12
+ self.current_contract_data = {}
13
+ self.current_monthly_data = {}
14
+
15
+ def fetch_payment_history(self, contract_number: str) -> Tuple[gr.Dropdown, str, pd.DataFrame]:
16
+ """
17
+ Fetch payment history for a given contract number
18
+ """
19
+ if not contract_number:
20
+ return gr.Dropdown(choices=[], value=None), "Please enter a contract number", pd.DataFrame()
21
+
22
+ try:
23
+ # Clean the contract number
24
+ contract_number = contract_number.strip()
25
+
26
+ # Call the API
27
+ url = f"{BASE_URL}/contracts/{contract_number}/payments"
28
+ response = requests.get(url, timeout=10)
29
+ response.raise_for_status()
30
+
31
+ data = response.json()
32
+ self.current_contract_data = data
33
+
34
+ # Extract monthly breakdown for dropdown
35
+ monthly_breakdown = data.get('monthly_breakdown', {})
36
+
37
+ if not monthly_breakdown:
38
+ return gr.Dropdown(choices=[], value=None), "No payment history found", pd.DataFrame()
39
+
40
+ # Create choices for dropdown (sorted by date, newest first)
41
+ choices = sorted(list(monthly_breakdown.keys()), reverse=True)
42
+
43
+ # Create summary info
44
+ contract_details = data.get('contract_details', {})
45
+ summary = data.get('summary', {})
46
+
47
+ # Clean job description by removing carriage returns
48
+ job_description = contract_details.get('job_description', 'N/A').replace('\r', ' ')
49
+
50
+ summary_info = f"""
51
+ ### Contract Summary
52
+ - **Contract Number:** {contract_details.get('contract_number', contract_number)}
53
+ - **Contractor:** {contract_details.get('contractor_name', 'N/A')}
54
+ - **Job Description:** {job_description}
55
+ - **Total Payments:** {summary.get('total_payments', 0)}
56
+ - **Total Disbursed:** ${summary.get('total_disbursed', 0):,.2f}
57
+ - **Total Held:** ${summary.get('total_held', 0):,.2f}
58
+ - **Estimated Completion:** {contract_details.get('estimated_completion', 'N/A')}
59
+ - **Last Updated:** {contract_details.get('last_updated', 'N/A')}
60
+ """
61
+
62
+ # Create payment history DataFrame
63
+ payment_history = data.get('payment_history', [])
64
+ if payment_history:
65
+ history_df = pd.DataFrame(payment_history)
66
+ history_df = history_df[['estimate_number', 'type', 'payment_type', 'release_date', 'disbursed_amount', 'held_amount']]
67
+ history_df.columns = ['Estimate #', 'Type', 'Payment Type', 'Release Date', 'Disbursed Amount', 'Held Amount']
68
+ history_df['Disbursed Amount'] = history_df['Disbursed Amount'].apply(lambda x: f"${x:,.2f}")
69
+ history_df['Held Amount'] = history_df['Held Amount'].apply(lambda x: f"${x:,.2f}")
70
+ else:
71
+ history_df = pd.DataFrame()
72
+
73
+ return (
74
+ gr.Dropdown(choices=choices, value=choices[0] if choices else None, visible=True, interactive=True),
75
+ summary_info,
76
+ history_df
77
+ )
78
+
79
+ except requests.exceptions.RequestException as e:
80
+ return gr.Dropdown(choices=[], value=None), f"Error fetching data: {str(e)}", pd.DataFrame()
81
+ except Exception as e:
82
+ return gr.Dropdown(choices=[], value=None), f"Unexpected error: {str(e)}", pd.DataFrame()
83
+
84
+ def fetch_monthly_details(self, contract_number: str, selected_month: str) -> Tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame, pd.DataFrame, str]:
85
+ """
86
+ Fetch detailed monthly payment information
87
+ """
88
+ if not contract_number or not selected_month:
89
+ return pd.DataFrame(), pd.DataFrame(), pd.DataFrame(), "Please select a month"
90
+
91
+ try:
92
+ # Clean inputs
93
+ contract_number = contract_number.strip()
94
+ selected_month = selected_month.strip()
95
+
96
+ # Call the API for monthly details
97
+ url = f"{BASE_URL}/contracts/{contract_number}/payments/monthly/{selected_month}"
98
+ response = requests.get(url, timeout=10)
99
+ response.raise_for_status()
100
+
101
+ monthly_data = response.json()
102
+ self.current_monthly_data = monthly_data
103
+
104
+ # Process the payment data
105
+ payment_info = monthly_data.get('payments', [{}])[0] if monthly_data.get('payments') else {}
106
+
107
+ # Create monthly summary DataFrame
108
+ summary_data = {
109
+ 'Metric': [
110
+ 'Month',
111
+ 'Payment Count',
112
+ 'Total Disbursed',
113
+ 'Total Held',
114
+ 'Estimate Number',
115
+ 'Payment Type',
116
+ 'Release Date'
117
+ ],
118
+ 'Value': [
119
+ monthly_data.get('month', selected_month),
120
+ monthly_data.get('payment_count', 0),
121
+ f"${monthly_data.get('total_disbursed', 0):,.2f}",
122
+ f"${monthly_data.get('total_held', 0):,.2f}",
123
+ payment_info.get('estimate_number', 'N/A'),
124
+ payment_info.get('payment_type', 'N/A'),
125
+ payment_info.get('release_date', 'N/A')
126
+ ]
127
+ }
128
+ summary_df = pd.DataFrame(summary_data)
129
+
130
+ # Create detailed items DataFrame
131
+ items_df = pd.DataFrame()
132
+ if payment_info and 'detailed_estimate' in payment_info:
133
+ detailed_estimate = payment_info['detailed_estimate']
134
+ prime_items = detailed_estimate.get('prime_contract', {}).get('items', [])
135
+
136
+ if prime_items:
137
+ # Process items for display
138
+ items_data = []
139
+ for item in prime_items:
140
+ if item.get('amounts', {}).get('this_period', 0) != 0: # Only show items with activity
141
+ items_data.append({
142
+ 'Item #': item.get('item_number', ''),
143
+ 'Description': item.get('description', '')[:50] + '...' if len(item.get('description', '')) > 50 else item.get('description', ''),
144
+ 'Unit': item.get('units', ''),
145
+ 'Unit Price': f"${item.get('unit_price', 0):,.2f}",
146
+ 'Qty This Period': f"{item.get('quantities', {}).get('this_period', 0):,.2f}",
147
+ 'Amount This Period': f"${item.get('amounts', {}).get('this_period', 0):,.2f}",
148
+ 'Job to Date': f"${item.get('amounts', {}).get('job_to_date', 0):,.2f}",
149
+ '% Complete': f"{item.get('quantities', {}).get('percent_jtd', 0):.1f}%"
150
+ })
151
+
152
+ if items_data:
153
+ items_df = pd.DataFrame(items_data)
154
+ # Sort by amount this period (descending)
155
+ items_df['sort_value'] = items_df['Amount This Period'].str.replace('$', '').str.replace(',', '').astype(float)
156
+ items_df = items_df.sort_values('sort_value', ascending=False).drop('sort_value', axis=1)
157
+ else:
158
+ # Create empty dataframe with message
159
+ items_df = pd.DataFrame({'Message': ['No line items with activity for this period']})
160
+ else:
161
+ items_df = pd.DataFrame({'Message': ['No line items available']})
162
+ else:
163
+ items_df = pd.DataFrame({'Message': ['No line items available']})
164
+
165
+ # Create deductions DataFrame
166
+ deductions_df = pd.DataFrame()
167
+ if payment_info and 'detailed_estimate' in payment_info:
168
+ deductions = payment_info['detailed_estimate'].get('deductions', [])
169
+ if deductions:
170
+ deductions_data = []
171
+ for deduction in deductions:
172
+ deductions_data.append({
173
+ 'Estimate #': deduction.get('estimate_no', ''),
174
+ 'Description': deduction.get('description', ''),
175
+ 'This Period': f"${deduction.get('this_period', 0):,.2f}",
176
+ 'Job to Date': f"${deduction.get('job_to_date', 0):,.2f}"
177
+ })
178
+ deductions_df = pd.DataFrame(deductions_data)
179
+ else:
180
+ deductions_df = pd.DataFrame({'Message': ['No deductions for this period']})
181
+ else:
182
+ deductions_df = pd.DataFrame({'Message': ['No deductions available']})
183
+
184
+ # Create change orders DataFrame
185
+ change_orders_df = pd.DataFrame()
186
+ if payment_info and 'detailed_estimate' in payment_info:
187
+ change_orders = payment_info['detailed_estimate'].get('change_orders', {}).get('items', [])
188
+ if change_orders:
189
+ change_orders_data = []
190
+ for co in change_orders:
191
+ change_orders_data.append({
192
+ 'Change Order #': co.get('change_order_no', ''),
193
+ 'Description': co.get('description', '')[:50] + '...' if len(co.get('description', '')) > 50 else co.get('description', ''),
194
+ 'This Period': f"${co.get('this_period_amt', 0):,.2f}",
195
+ 'Job to Date': f"${co.get('job_to_date_amt', 0):,.2f}",
196
+ 'Status': co.get('status', 'N/A')
197
+ })
198
+ if change_orders_data:
199
+ change_orders_df = pd.DataFrame(change_orders_data)
200
+ # Sort by amount this period (descending)
201
+ change_orders_df['sort_value'] = change_orders_df['This Period'].str.replace('$', '').str.replace(',', '').astype(float)
202
+ change_orders_df = change_orders_df.sort_values('sort_value', ascending=False).drop('sort_value', axis=1)
203
+ else:
204
+ change_orders_df = pd.DataFrame({'Message': ['No change orders for this period']})
205
+ else:
206
+ change_orders_df = pd.DataFrame({'Message': ['No change orders available']})
207
+ else:
208
+ change_orders_df = pd.DataFrame({'Message': ['No change orders available']})
209
+
210
+ # Create totals summary
211
+ if payment_info and 'detailed_estimate' in payment_info:
212
+ totals = payment_info['detailed_estimate'].get('overall_totals', {})
213
+ totals_info = f"""
214
+ ### Payment Totals for {selected_month}
215
+ - **Original Contract Amount:** ${totals.get('original', 0):,.2f}
216
+ - **This Period:** ${totals.get('this_period', 0):,.2f}
217
+ - **Job to Date:** ${totals.get('job_to_date', 0):,.2f}
218
+ - **Extra Work This Estimate:** ${totals.get('extra_work_this_estimate', 0):,.2f}
219
+ - **Extra Work to Date:** ${totals.get('extra_work_to_date', 0):,.2f}
220
+ """
221
+ else:
222
+ totals_info = "No detailed totals available"
223
+
224
+ return summary_df, items_df, deductions_df, change_orders_df, totals_info
225
+
226
+ except requests.exceptions.RequestException as e:
227
+ return pd.DataFrame(), pd.DataFrame(), pd.DataFrame(), pd.DataFrame(), f"Error fetching monthly details: {str(e)}"
228
+ except Exception as e:
229
+ return pd.DataFrame(), pd.DataFrame(), pd.DataFrame(), pd.DataFrame(), f"Unexpected error: {str(e)}"
230
+
231
+ # Create instance of the viewer
232
+ viewer = ContractPaymentViewer()
233
+
234
+ # Create Gradio interface
235
+ with gr.Blocks(title="Contract Payment Viewer", theme=gr.themes.Soft()) as app:
236
+ gr.Markdown("# Contract Payment Viewer")
237
+ gr.Markdown("Enter a contract number to view payment history and detailed monthly breakdowns")
238
+
239
+ with gr.Row():
240
+ with gr.Column(scale=1):
241
+ contract_input = gr.Textbox(
242
+ label="Contract Number",
243
+ placeholder="e.g., 03-3F0704",
244
+ value="03-3F0704"
245
+ )
246
+ fetch_button = gr.Button("Fetch Payment History", variant="primary")
247
+
248
+ with gr.Row():
249
+ with gr.Column():
250
+ summary_output = gr.Markdown(label="Contract Summary")
251
+
252
+ with gr.Row():
253
+ with gr.Column(scale=1):
254
+ month_dropdown = gr.Dropdown(
255
+ label="Select Month",
256
+ choices=[],
257
+ visible=False
258
+ )
259
+ fetch_monthly_button = gr.Button("Get Monthly Details", variant="secondary", visible=False)
260
+
261
+ with gr.Row():
262
+ with gr.Column():
263
+ with gr.Accordion("Payment History", open=False):
264
+ history_table = gr.Dataframe(
265
+ label="Payment History",
266
+ wrap=True
267
+ )
268
+
269
+ # Monthly details section
270
+ with gr.Row(visible=False) as monthly_section:
271
+ with gr.Column():
272
+ gr.Markdown("## Monthly Payment Details")
273
+
274
+ with gr.Tabs():
275
+ with gr.TabItem("Summary"):
276
+ monthly_summary_table = gr.Dataframe(
277
+ label="Monthly Summary",
278
+ wrap=True
279
+ )
280
+ totals_output = gr.Markdown(label="Payment Totals")
281
+
282
+ with gr.TabItem("Line Items"):
283
+ items_table = gr.Dataframe(
284
+ label="Contract Items (This Period Activity)",
285
+ wrap=True
286
+ )
287
+
288
+ with gr.TabItem("Deductions"):
289
+ deductions_table = gr.Dataframe(
290
+ label="Deductions",
291
+ wrap=True
292
+ )
293
+
294
+ with gr.TabItem("Change Orders"):
295
+ change_orders_table = gr.Dataframe(
296
+ label="Change Orders",
297
+ wrap=True
298
+ )
299
+
300
+ # Event handlers
301
+ def handle_fetch_history(contract_number):
302
+ dropdown, summary, history = viewer.fetch_payment_history(contract_number)
303
+ return {
304
+ month_dropdown: dropdown,
305
+ summary_output: summary,
306
+ history_table: history,
307
+ fetch_monthly_button: gr.Button(visible=True if dropdown.choices else False),
308
+ monthly_section: gr.Row(visible=False)
309
+ }
310
+
311
+ def handle_fetch_monthly(contract_number, selected_month):
312
+ summary_df, items_df, deductions_df, change_orders_df, totals = viewer.fetch_monthly_details(contract_number, selected_month)
313
+ return {
314
+ monthly_summary_table: summary_df,
315
+ items_table: items_df,
316
+ deductions_table: deductions_df,
317
+ change_orders_table: change_orders_df,
318
+ totals_output: totals,
319
+ monthly_section: gr.Row(visible=True)
320
+ }
321
+
322
+ fetch_button.click(
323
+ fn=handle_fetch_history,
324
+ inputs=[contract_input],
325
+ outputs=[month_dropdown, summary_output, history_table, fetch_monthly_button, monthly_section]
326
+ )
327
+
328
+ fetch_monthly_button.click(
329
+ fn=handle_fetch_monthly,
330
+ inputs=[contract_input, month_dropdown],
331
+ outputs=[monthly_summary_table, items_table, deductions_table, change_orders_table, totals_output, monthly_section]
332
+ )
333
+
334
+ # Auto-fetch monthly details when dropdown changes
335
+ month_dropdown.change(
336
+ fn=handle_fetch_monthly,
337
+ inputs=[contract_input, month_dropdown],
338
+ outputs=[monthly_summary_table, items_table, deductions_table, change_orders_table, totals_output, monthly_section]
339
+ )
340
+
341
+ # Launch the app
342
+ if __name__ == "__main__":
343
+ app.launch(
344
+ share=True,
345
+ server_name="0.0.0.0",
346
+ server_port=7860,
347
+ show_error=True,
348
+ debug=False,
349
+ max_threads=10
350
+ )
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ gradio==5.6.0
2
+ requests==2.32.4
3
+ pandas==2.3.1