varshakolanu commited on
Commit
88e3d9a
·
verified ·
1 Parent(s): b1eb1b7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +94 -89
app.py CHANGED
@@ -8,18 +8,18 @@ from reportlab.pdfgen import canvas
8
  from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
9
  from reportlab.lib.styles import getSampleStyleSheet
10
  from reportlab.lib.units import inch
11
- import io # Import the io module
 
 
12
 
13
  # 1. Load the Model and Artifacts
14
  # Model and artifact paths - adjust as necessary
15
- model_path = 'your_model.pkl' # Make sure this path is correct
16
  scaler_path = 'scaler.pkl' # If you used a scaler
17
- # encoder_path = 'encoder.pkl' # If you used an encoder
18
 
19
  try:
20
  model = joblib.load(model_path)
21
  scaler = joblib.load(scaler_path) if scaler_path else None
22
- # encoder = joblib.load(encoder_path) if encoder_path else None
23
  except Exception as e:
24
  print(f"Error loading model or artifacts: {e}")
25
  model = None
@@ -27,12 +27,10 @@ except Exception as e:
27
  # 2. Preprocessing Function
28
  def preprocess_data(data: Dict[str, Any]) -> pd.DataFrame:
29
  """
30
- Preprocesses input data for the model. This version is adapted to use
31
- the Vendor_Log__c fields directly.
32
 
33
  Args:
34
- data (dict): A dictionary containing the input data from the Gradio interface,
35
- matching Vendor_Log__c fields.
36
 
37
  Returns:
38
  pandas.DataFrame: A DataFrame ready for model prediction.
@@ -40,36 +38,30 @@ def preprocess_data(data: Dict[str, Any]) -> pd.DataFrame:
40
  try:
41
  df = pd.DataFrame([data])
42
 
43
- # Expected fields based on Vendor_Log__c. Adjust *EXACTLY* to match your Salesforce field names.
44
  expected_fields = [
45
- 'Quality_Report__c', # Long Text Area
46
- 'Delay_Days__c', # Number
47
- 'Incident_Log__c', # Long Text Area
48
- 'Vendor__c', # Lookup (Important: Send the Salesforce ID, not the name)
49
- 'Work_Details__c', # Long Text Area
50
- 'Work_Completion_Date__c', # Date
51
- 'Actual_Completion_Date__c' # Date
52
  ]
53
 
54
- # 1. Check for missing fields
55
  missing_fields = [field for field in expected_fields if field not in df.columns]
56
  if missing_fields:
57
  raise ValueError(f"Missing required fields: {', '.join(missing_fields)}")
58
 
59
- # 2. Data Transformations (Adapt to your needs)
60
- # Example: Scaling
61
  if 'Delay_Days__c' in df.columns and scaler:
62
  df['Delay_Days__c'] = df['Delay_Days__c'].fillna(0)
63
  df[['Delay_Days__c']] = scaler.transform(df[['Delay_Days__c']])
64
 
65
- # 3. Handle Dates (Example - you might need more complex logic)
66
  if 'Work_Completion_Date__c' in df.columns:
67
  df['Work_Completion_Date__c'] = pd.to_datetime(df['Work_Completion_Date__c'])
68
- # Example: Extract year, month, day. Include if your model uses these.
69
  df['Work_Completion_Year'] = df['Work_Completion_Date__c'].dt.year
70
  df['Work_Completion_Month'] = df['Work_Completion_Date__c'].dt.month
71
  df['Work_Completion_Day'] = df['Work_Completion_Date__c'].dt.day
72
- df = df.drop(columns=['Work_Completion_Date__c']) # remove original date
73
 
74
  if 'Actual_Completion_Date__c' in df.columns:
75
  df['Actual_Completion_Date__c'] = pd.to_datetime(df['Actual_Completion_Date__c'])
@@ -78,30 +70,20 @@ def preprocess_data(data: Dict[str, Any]) -> pd.DataFrame:
78
  df['Actual_Completion_Day'] = df['Actual_Completion_Date__c'].dt.day
79
  df = df.drop(columns=['Actual_Completion_Date__c'])
80
 
81
- # 4. Text Handling (Example - for long text areas)
82
- # if 'Work_Details__c' in df.columns:
83
- # df['Work_Details__c'] = df['Work_Details__c'].fillna('')
84
- # df['Work_Details_Length'] = df['Work_Details__c'].apply(len) #example feature
85
-
86
  df = df[expected_fields]
87
  return df
88
  except ValueError as ve:
89
  print(f"Error in preprocess_data: {ve}")
90
- return pd.DataFrame() # Return empty DataFrame on error
91
  except Exception as e:
92
  print(f"Error in preprocess_data: {e}")
93
  return pd.DataFrame()
94
 
 
95
  # 3. Prediction Function
96
- def predict_vendor_score(*args: Any) -> Tuple[List[Tuple[str, float]], bytes]:
97
  """
98
- Predicts the vendor performance score based on the input data from Vendor_Log__c.
99
- Returns a list of tuples, where each tuple contains the score name and its value,
100
- and the PDF data as bytes.
101
-
102
- Args:
103
- *args: Input values from the Gradio interface, in the order matching
104
- the Vendor_Log__c fields.
105
 
106
  Returns:
107
  Tuple[List[Tuple[str, float]], bytes]: A tuple containing the score data and the PDF data.
@@ -116,37 +98,65 @@ def predict_vendor_score(*args: Any) -> Tuple[List[Tuple[str, float]], bytes]:
116
  ("Final Score (%)", 0.0),
117
  ], generate_pdf(error_message)
118
 
119
- # 1. Prepare input data as a dictionary, mapping to Vendor_Log__c fields
120
- input_data = {
121
- 'Quality_Report__c': args[0],
122
- 'Delay_Days__c': args[1],
123
- 'Incident_Log__c': args[2],
124
- 'Vendor__c': args[3],
125
- 'Work_Details__c': args[4],
126
- 'Work_Completion_Date__c': args[5],
127
- 'Actual_Completion_Date__c': args[6]
128
- }
129
-
130
- # 2. Preprocess the data
131
- processed_df = preprocess_data(input_data)
132
- if processed_df.empty:
133
- error_message = "Error in input data. Check logs."
134
- return [
135
- ("Quality Score (%)", 0.0),
136
- ("Timeliness Score (%)", 0.0),
137
- ("Safety Score (%)", 0.0),
138
- ("Communication Score (%)", 0.0),
139
- ("Final Score (%)", 0.0),
140
- ], generate_pdf(error_message) # Return empty PDF
141
-
142
- # 3. Make Prediction
143
  try:
144
- predictions = model.predict(processed_df)[0] # Get the first element
145
-
146
- # 4. Output: Map model output to Subcontractor_Performance_Score__c fields
147
- # IMPORTANT: Adjust this mapping based on your model's output.
148
- # This is a *crucial* step where you tell Gradio how to interpret
149
- # the numbers coming from your model.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  output_data = [
151
  ("Quality Score (%)", predictions[0] * 100),
152
  ("Timeliness Score (%)", predictions[1] * 100),
@@ -158,8 +168,8 @@ def predict_vendor_score(*args: Any) -> Tuple[List[Tuple[str, float]], bytes]:
158
  return output_data, pdf_data
159
 
160
  except Exception as e:
161
- error_message = f"Error during prediction: {e}"
162
- print(f"Error during prediction: {e}")
163
  return [
164
  ("Quality Score (%)", 0.0),
165
  ("Timeliness Score (%)", 0.0),
@@ -168,6 +178,9 @@ def predict_vendor_score(*args: Any) -> Tuple[List[Tuple[str, float]], bytes]:
168
  ("Final Score (%)", 0.0),
169
  ], generate_pdf(error_message)
170
 
 
 
 
171
  def generate_pdf(scores: List[Tuple[str, float]]) -> bytes:
172
  """Generates a PDF report of the subcontractor performance scores.
173
 
@@ -176,48 +189,40 @@ def generate_pdf(scores: List[Tuple[str, float]]) -> bytes:
176
  Returns:
177
  bytes: The PDF data as bytes.
178
  """
179
- buffer = io.BytesIO() # Use BytesIO for in-memory PDF generation
180
  doc = SimpleDocTemplate(buffer, pagesize=letter)
181
  styles = getSampleStyleSheet()
182
  Story = []
183
-
184
- # Add a title
185
  Story.append(Paragraph("Subcontractor Performance Report", styles['Title']))
186
  Story.append(Spacer(1, 0.2 * inch))
187
-
188
- if isinstance(scores, str): # Check if it is an error message
189
  Story.append(Paragraph(scores, styles['Normal']))
190
  else:
191
- # Add the scores to the PDF
192
  for score_name, score_value in scores:
193
  Story.append(Paragraph(f"{score_name}: {score_value:.2f}", styles['Normal']))
194
  Story.append(Spacer(1, 0.1 * inch))
195
-
196
  doc.build(Story)
197
  pdf_data = buffer.getvalue()
198
  buffer.close()
199
  return pdf_data
200
 
201
- # 4. Gradio Interface
202
  iface = gr.Interface(
203
  fn=predict_vendor_score,
204
- inputs=[
205
- gr.Textbox(label="Quality Report (Long Text)", type="text"),
206
- gr.Number(label="Delay Days (Number)"),
207
- gr.Textbox(label="Incident Log (Long Text)", type="text"),
208
- gr.Textbox(label="Vendor ID (Text)"), # Send ID
209
- gr.Textbox(label="Work Details (Long Text)", type="text"),
210
- gr.DateTime(label="Work Completion Date", type="datetime"), # Corrected to "datetime"
211
- gr.DateTime(label="Actual Completion Date", type="datetime"), # Corrected to "datetime"
212
- ],
213
- outputs=[ # Changed to a list
214
  gr.HighlightedText(label="Performance Scores"),
215
  gr.File(label="Download PDF Report"),
216
  ],
217
  title="Subcontractor Performance Score Calculator",
218
- description="Enter Vendor Log details to calculate performance scores and generate a PDF report.",
 
219
  )
220
 
221
- # 5. Launch the Interface
222
  if __name__ == "__main__":
223
- iface.launch()
 
 
 
 
 
8
  from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
9
  from reportlab.lib.styles import getSampleStyleSheet
10
  from reportlab.lib.units import inch
11
+ import io
12
+ from simple_salesforce import Salesforce
13
+ import os
14
 
15
  # 1. Load the Model and Artifacts
16
  # Model and artifact paths - adjust as necessary
17
+ model_path = 'your_model.pkl' # Make sure this path is correct
18
  scaler_path = 'scaler.pkl' # If you used a scaler
 
19
 
20
  try:
21
  model = joblib.load(model_path)
22
  scaler = joblib.load(scaler_path) if scaler_path else None
 
23
  except Exception as e:
24
  print(f"Error loading model or artifacts: {e}")
25
  model = None
 
27
  # 2. Preprocessing Function
28
  def preprocess_data(data: Dict[str, Any]) -> pd.DataFrame:
29
  """
30
+ Preprocesses input data for the model.
 
31
 
32
  Args:
33
+ data (dict): A dictionary containing the input data.
 
34
 
35
  Returns:
36
  pandas.DataFrame: A DataFrame ready for model prediction.
 
38
  try:
39
  df = pd.DataFrame([data])
40
 
 
41
  expected_fields = [
42
+ 'Quality_Report__c',
43
+ 'Delay_Days__c',
44
+ 'Incident_Log__c',
45
+ 'Vendor__c',
46
+ 'Work_Details__c',
47
+ 'Work_Completion_Date__c',
48
+ 'Actual_Completion_Date__c'
49
  ]
50
 
 
51
  missing_fields = [field for field in expected_fields if field not in df.columns]
52
  if missing_fields:
53
  raise ValueError(f"Missing required fields: {', '.join(missing_fields)}")
54
 
 
 
55
  if 'Delay_Days__c' in df.columns and scaler:
56
  df['Delay_Days__c'] = df['Delay_Days__c'].fillna(0)
57
  df[['Delay_Days__c']] = scaler.transform(df[['Delay_Days__c']])
58
 
 
59
  if 'Work_Completion_Date__c' in df.columns:
60
  df['Work_Completion_Date__c'] = pd.to_datetime(df['Work_Completion_Date__c'])
 
61
  df['Work_Completion_Year'] = df['Work_Completion_Date__c'].dt.year
62
  df['Work_Completion_Month'] = df['Work_Completion_Date__c'].dt.month
63
  df['Work_Completion_Day'] = df['Work_Completion_Date__c'].dt.day
64
+ df = df.drop(columns=['Work_Completion_Date__c'])
65
 
66
  if 'Actual_Completion_Date__c' in df.columns:
67
  df['Actual_Completion_Date__c'] = pd.to_datetime(df['Actual_Completion_Date__c'])
 
70
  df['Actual_Completion_Day'] = df['Actual_Completion_Date__c'].dt.day
71
  df = df.drop(columns=['Actual_Completion_Date__c'])
72
 
 
 
 
 
 
73
  df = df[expected_fields]
74
  return df
75
  except ValueError as ve:
76
  print(f"Error in preprocess_data: {ve}")
77
+ return pd.DataFrame()
78
  except Exception as e:
79
  print(f"Error in preprocess_data: {e}")
80
  return pd.DataFrame()
81
 
82
+
83
  # 3. Prediction Function
84
+ def predict_vendor_score() -> Tuple[List[Tuple[str, float]], bytes]:
85
  """
86
+ Retrieves data from Salesforce, predicts vendor performance scores, and generates a PDF report.
 
 
 
 
 
 
87
 
88
  Returns:
89
  Tuple[List[Tuple[str, float]], bytes]: A tuple containing the score data and the PDF data.
 
98
  ("Final Score (%)", 0.0),
99
  ], generate_pdf(error_message)
100
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  try:
102
+ # 1. Connect to Salesforce
103
+ sf = Salesforce(
104
+ username=os.environ.get('SALESFORCE_USERNAME'), # Use environment variables
105
+ password=os.environ.get('SALESFORCE_PASSWORD'),
106
+ security_token=os.environ.get('SALESFORCE_SECURITY_TOKEN'),
107
+ domain='login' # or 'test' for a sandbox
108
+ )
109
+
110
+ # 2. SOQL Query (Adapt to your needs)
111
+ query = """
112
+ SELECT
113
+ Quality_Report__c,
114
+ Delay_Days__c,
115
+ Incident_Log__c,
116
+ Vendor__c,
117
+ Work_Details__c,
118
+ Work_Completion_Date__c,
119
+ Actual_Completion_Date__c
120
+ FROM
121
+ Vendor_Log__c
122
+ WHERE
123
+ # Add any filtering criteria here (e.g., date range)
124
+ CreatedDate >= LAST_MONTH
125
+ """
126
+ results = sf.query(query)
127
+
128
+ # 3. Data Transformation
129
+ records = results['records']
130
+ df = pd.DataFrame(records)
131
+ df = df.rename(columns={
132
+ 'Quality_Report__c': 'Quality_Report__c',
133
+ 'Delay_Days__c': 'Delay_Days__c',
134
+ 'Incident_Log__c': 'Incident_Log__c',
135
+ 'Vendor__c': 'Vendor__c',
136
+ 'Work_Details__c': 'Work_Details__c',
137
+ 'Work_Completion_Date__c': 'Work_Completion_Date__c',
138
+ 'Actual_Completion_Date__c': 'Actual_Completion_Date__c'
139
+ })
140
+ df = df.drop(columns=['attributes'], errors='ignore')
141
+
142
+ # 4. Preprocess Data
143
+ processed_df = preprocess_data(df.iloc[0].to_dict()) # pass the first row as dict
144
+
145
+
146
+ if processed_df.empty:
147
+ error_message = "Error in input data. Check logs."
148
+ return [
149
+ ("Quality Score (%)", 0.0),
150
+ ("Timeliness Score (%)", 0.0),
151
+ ("Safety Score (%)", 0.0),
152
+ ("Communication Score (%)", 0.0),
153
+ ("Final Score (%)", 0.0),
154
+ ], generate_pdf(error_message)
155
+
156
+ # 5. Make Prediction
157
+ predictions = model.predict(processed_df)[0]
158
+
159
+ # 6. Output
160
  output_data = [
161
  ("Quality Score (%)", predictions[0] * 100),
162
  ("Timeliness Score (%)", predictions[1] * 100),
 
168
  return output_data, pdf_data
169
 
170
  except Exception as e:
171
+ error_message = f"Error: {e}"
172
+ print(error_message)
173
  return [
174
  ("Quality Score (%)", 0.0),
175
  ("Timeliness Score (%)", 0.0),
 
178
  ("Final Score (%)", 0.0),
179
  ], generate_pdf(error_message)
180
 
181
+
182
+
183
+ # 4. PDF Generation
184
  def generate_pdf(scores: List[Tuple[str, float]]) -> bytes:
185
  """Generates a PDF report of the subcontractor performance scores.
186
 
 
189
  Returns:
190
  bytes: The PDF data as bytes.
191
  """
192
+ buffer = io.BytesIO()
193
  doc = SimpleDocTemplate(buffer, pagesize=letter)
194
  styles = getSampleStyleSheet()
195
  Story = []
 
 
196
  Story.append(Paragraph("Subcontractor Performance Report", styles['Title']))
197
  Story.append(Spacer(1, 0.2 * inch))
198
+ if isinstance(scores, str):
 
199
  Story.append(Paragraph(scores, styles['Normal']))
200
  else:
 
201
  for score_name, score_value in scores:
202
  Story.append(Paragraph(f"{score_name}: {score_value:.2f}", styles['Normal']))
203
  Story.append(Spacer(1, 0.1 * inch))
 
204
  doc.build(Story)
205
  pdf_data = buffer.getvalue()
206
  buffer.close()
207
  return pdf_data
208
 
209
+ # 5. Gradio Interface
210
  iface = gr.Interface(
211
  fn=predict_vendor_score,
212
+ inputs=[],
213
+ outputs=[
 
 
 
 
 
 
 
 
214
  gr.HighlightedText(label="Performance Scores"),
215
  gr.File(label="Download PDF Report"),
216
  ],
217
  title="Subcontractor Performance Score Calculator",
218
+ description="Click the button to retrieve Vendor Log details from Salesforce, calculate performance scores, and generate a PDF report.",
219
+ buttons=[gr.Button("Get Scores from Salesforce")]
220
  )
221
 
222
+ # 6. Launch the Interface
223
  if __name__ == "__main__":
224
+ # Set up environment variables for Salesforce credentials
225
+ os.environ['SALESFORCE_USERNAME'] = 'scores@app.com' # Replace with your username
226
+ os.environ['SALESFORCE_PASSWORD'] = 'Internal@1' # Replace with your password
227
+ os.environ['SALESFORCE_SECURITY_TOKEN'] = 'NbUKcTx45azba5HEdntE9YAh' # Replace with your security token
228
+ iface.launch()