gopichandra commited on
Commit
4a93b16
Β·
verified Β·
1 Parent(s): b0067d0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +283 -71
app.py CHANGED
@@ -9,6 +9,100 @@ import pandas as pd
9
  import matplotlib.pyplot as plt
10
  from io import BytesIO
11
  from fuzzywuzzy import process
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
  # Salesforce credentials
14
  SALESFORCE_USERNAME = "venkatramana@sandbox.com"
@@ -26,92 +120,210 @@ def extract_text(image):
26
  extracted_text.append(line[1][0])
27
  return "\n".join(extracted_text)
28
 
29
- # Function to fetch data from Salesforce and format it into a DataFrame
30
- def fetch_salesforce_data():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  try:
32
  sf = Salesforce(
33
  username=SALESFORCE_USERNAME,
34
  password=SALESFORCE_PASSWORD,
35
  security_token=SALESFORCE_SECURITY_TOKEN
36
  )
37
- query = "SELECT Product_Name__c, Modal_Name__c, Current_Stocks__c FROM MotorDataAPI__c"
38
- response = sf.query_all(query)
39
- records = response["records"]
40
- df = pd.DataFrame(records)
41
- if not df.empty:
42
- df = df.rename(columns={
43
- "Product_Name__c": "Product Name",
44
- "Modal_Name__c": "Model Name",
45
- "Current_Stocks__c": "Current Stocks"
46
- })
47
- return df[["Product Name", "Model Name", "Current Stocks"]]
48
- else:
49
- return None
50
- except Exception as e:
51
- print(f"Error fetching Salesforce data: {e}")
52
- return None
53
 
54
- # Function to generate a bar graph from Salesforce data
55
- def generate_salesforce_bar_chart(df):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  try:
57
- plt.figure(figsize=(12, 6))
58
- plt.bar(df["Product Name"], df["Current Stocks"], color='blue')
59
- plt.title("Stock Distribution by Product Name")
60
- plt.xlabel("Product Name")
61
- plt.ylabel("Current Stocks")
62
- plt.xticks(rotation=45, ha="right")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  plt.tight_layout()
64
  buffer = BytesIO()
65
  plt.savefig(buffer, format="png")
66
  buffer.seek(0)
67
- return Image.open(buffer)
 
 
68
  except Exception as e:
69
- print(f"Error generating bar chart: {e}")
70
- return None
71
-
72
- # Function to fetch and return Salesforce data
73
- def get_salesforce_visualization():
74
- df = fetch_salesforce_data()
75
- if df is not None:
76
- table_component = df.to_html(index=False)
77
- bar_chart_image = generate_salesforce_bar_chart(df)
78
- return table_component, bar_chart_image
79
- return "<p>No Data Available</p>", None
 
80
 
 
 
 
 
 
 
 
81
  def app():
82
- with gr.Blocks() as interface:
83
- gr.Markdown("<h1>🏒 VENKATARAMANA MOTORS</h1>")
84
-
85
- with gr.Tab("πŸ“₯ Stock Entry & Processing"):
86
- with gr.Row():
87
- with gr.Column():
88
- gr.Markdown("<h3>πŸ“Œ Upload & Process</h3>")
89
- image_input = gr.Image(type="numpy", label="πŸ“„ Upload Image")
90
- mode_dropdown = gr.Dropdown(label="πŸ“Œ Mode", choices=["Entry", "Exit"], value="Entry")
91
- entry_type_radio = gr.Radio(label="πŸ“¦ Entry Type", choices=["Sales", "Non-Sales"], value="Sales")
92
- quantity_input = gr.Number(label="πŸ”’ Quantity", value=1, interactive=True)
93
-
94
- with gr.Column():
95
- gr.Markdown("<h3>πŸ“Š Processed Data</h3>")
96
- image_view = gr.Text(label="πŸ“œ Image Data Viewer", interactive=False)
97
- result_output = gr.Text(label="πŸ“ Processed Result", interactive=False)
98
- submit_button = gr.Button("πŸ” Process Image")
99
-
100
- with gr.Tab("πŸ“Š Salesforce Data Overview"):
101
- gr.Markdown("<h3>πŸ“‘ Stock Table</h3>")
102
- with gr.Row():
103
- salesforce_table = gr.HTML(label="πŸ“¦ Salesforce Data Table")
104
-
105
- gr.Markdown("<h3>πŸ“ˆ Inventory Analytics</h3>")
106
- with gr.Row():
107
- salesforce_graph = gr.Image(type="pil", label="πŸ“‰ Stock Distribution Bar Graph")
108
-
109
- generate_button = gr.Button("⚑ Generate Data")
110
-
111
- generate_button.click(fn=get_salesforce_visualization, inputs=[], outputs=[salesforce_table, salesforce_graph])
112
- submit_button.click(fn=process_image, inputs=[image_input, mode_dropdown, entry_type_radio, quantity_input], outputs=[image_view, result_output])
113
-
114
- return interface
115
 
116
  if __name__ == "__main__":
117
  app().launch(share=True)
 
 
9
  import matplotlib.pyplot as plt
10
  from io import BytesIO
11
  from fuzzywuzzy import process
12
+ import kaleido # Ensure kaleido is imported
13
+
14
+ # Attribute mappings: readable names to Salesforce API names
15
+ ATTRIBUTE_MAPPING = {
16
+ "Productname": "Productname__c",
17
+ "Colour": "Colour__c",
18
+ "Motortype": "Motortype__c",
19
+ "Frequency": "Frequency__c",
20
+ "Grossweight": "Grossweight__c",
21
+ "Ratio": "Ratio__c",
22
+ "MotorFrame": "Motorframe__c",
23
+ "Model": "Model__c",
24
+ "Speed": "Speed__c",
25
+ "Quantity": "Quantity__c",
26
+ "Voltage": "Voltage__c",
27
+ "Material": "Material__c",
28
+ "Type": "Type__c",
29
+ "Horsepower": "Horsepower__c",
30
+ "Consignee": "Consignee__c",
31
+ "LOT": "LOT__c",
32
+ "Stage": "Stage__c",
33
+ "Outlet": "Outlet__c",
34
+ "Serialnumber": "Serialnumber__c",
35
+ "HeadSize": "Headsize__c",
36
+ "Deliverysize": "Deliverysize__c",
37
+ "Phase": "Phase__c",
38
+ "Size": "Size__c",
39
+ "MRP": "MRP__c",
40
+ "Usebefore": "Usebefore__c",
41
+ "Height": "Height__c",
42
+ "MaximumDischarge Flow": "Maximumdischargeflow__c",
43
+ "DischargeRange": "Dischargeflow__c",
44
+ "Assembledby": "Manufacturer__c",
45
+ "Manufacturedate": "Manufacturedate__c",
46
+ "Companyname": "Companyname__c",
47
+ "Customercarenumber": "Customercarenumber__c",
48
+ "SellerAddress": "Selleraddress__c",
49
+ "Selleremail": "Selleremail__c",
50
+ "GSTIN": "GSTIN__c",
51
+ "Totalamount": "Totalamount__c",
52
+ "Paymentstatus": "Paymentstatus__c",
53
+ "Paymentmethod": "Paymentstatus__c",
54
+ "Invoicedate": "Manufacturedate__c",
55
+ "Warranty": "Warranty__c",
56
+ "Brand": "Brand__c",
57
+ "Motorhorsepower": "Motorhorsepower__c",
58
+ "Power": "Power__c",
59
+ "Motorphase": "Motorphase__c",
60
+ "Enginetype": "Enginetype__c",
61
+ "Tankcapacity": "Tankcapacity__c",
62
+ "Head": "Head__c",
63
+ "Usage/Application": "Usage_Application__c",
64
+ "Volts": "volts__c",
65
+ "Hertz": "Hertz__c",
66
+ "Frame": "frame__c",
67
+ "Mounting": "Mounting__c",
68
+ "Tollfreenumber": "Tollfreenumber__c",
69
+ "Pipesize": "Pipesize__c",
70
+ "Manufacturer": "Manufacturer__c",
71
+ "Office": "Office__c",
72
+ "SRnumber": "SRnumber__c",
73
+ "TypeOfEndUse": "TypeOfEndUse__c",
74
+ "Model Name": "Model_Name_Number__c",
75
+ "coolingmethod": "coolingmethod__c"
76
+ }
77
+
78
+ # List of product names to match
79
+ PRODUCT_NAMES = [
80
+ "Centrifugal mono block pump", "SINGLE PHASE MOTOR STARTER", "EasyPact EZC 100",
81
+ "Openwell Submersible Pumpset", "Electric Motor", "Self Priming Pump",
82
+ "Control panel for single phase submersible pumps", "MOTOR", "Submersible pump set",
83
+ "Fusion submersible pump set", "DCT", "Shock proof water proof", "CG COMMERCIAL MOTORS", "Fusion",
84
+ "control panel for single phase submerisible pumps",
85
+ "single phase digital starter dry run and timer panel", "5HP AV1 XL Kirloskar Pump",
86
+ "Phase stainless steel submersible pump", "Submersible pump", "WB15X",
87
+ "Vtype self priming pump", "SP SHINE DISC", "havells submersible pump",
88
+ "Havells open well Submersible pump", "Bertolini pump CK3 90pp",
89
+ "WPA 772 Water Pump Assy", "bertolini TTL triplex high pressure plunger pumps",
90
+ "Generic plunger high pressure pump", "Apple Normal, Banana",
91
+ "Cast Iron KSb centrifugal pump", "5.5kw Water Pump",
92
+ "KSB reliable i line centrifuged pumps", "Apple Normal, Orange, Banana",
93
+ "Positive API 6745 hydraulic diaphragm pump", "1/2 inch Fuel Hose Pipe", "Kirloskar Water Pump",
94
+ "Rotodel motor pump", "PVC Electrical Insulation Materials",
95
+ "Electric kirloskar domestic water pump", "Electrical Insulation Materials",
96
+ "sellowell motor pump", "bhupathi submersible pump set",
97
+ "Flowshine Submersible pump set", "Index submersible pump",
98
+ "Wintoss Plastic Electric Switch Board", "Electric 18 watt ujagar cooler pump",
99
+ "Generator Service", "LG WM FHT1207ZWL, LG REF GL-S292RSCY",
100
+ "Water tank, Filters, Water Pump", "MS Control Submersible Panel",
101
+ "Centrifugal Monoblock Pumps", "Electric Motor with Pump BodyBlue and White",
102
+ "Various Repair and Maintenance Parts", "Earthmax Pump",
103
+ "Water Tank, Filters, Water Pump", "Centrifugal Water Pump for Agriculture",
104
+ "mono block pumps"
105
+ ]
106
 
107
  # Salesforce credentials
108
  SALESFORCE_USERNAME = "venkatramana@sandbox.com"
 
120
  extracted_text.append(line[1][0])
121
  return "\n".join(extracted_text)
122
 
123
+ # Function to match product name using fuzzy matching
124
+ def match_product_name(extracted_text):
125
+ best_match = None
126
+ best_score = 0
127
+
128
+ for line in extracted_text.split("\n"):
129
+ match, score = process.extractOne(line, PRODUCT_NAMES)
130
+ if score > best_score:
131
+ best_match = match
132
+ best_score = score
133
+
134
+ return best_match if best_score >= 70 else None # Threshold of 70 for a match
135
+
136
+ # Function to extract attributes and their values
137
+ def extract_attributes(extracted_text):
138
+ attributes = {}
139
+
140
+ for readable_attr, sf_attr in ATTRIBUTE_MAPPING.items():
141
+ pattern = rf"{re.escape(readable_attr)}[:\-]?\s*(.+)"
142
+ match = re.search(pattern, extracted_text, re.IGNORECASE)
143
+ if match:
144
+ attributes[readable_attr] = match.group(1).strip()
145
+
146
+ return attributes
147
+
148
+ # Function to filter attributes for valid Salesforce fields
149
+ def filter_valid_attributes(attributes, valid_fields):
150
+ return {ATTRIBUTE_MAPPING[key]: value for key, value in attributes.items() if ATTRIBUTE_MAPPING[key] in valid_fields}
151
+
152
+ #πŸ“Š Function to interact with Salesforce based on mode and type
153
+ def interact_with_salesforce(mode, entry_type, quantity, extracted_text):
154
  try:
155
  sf = Salesforce(
156
  username=SALESFORCE_USERNAME,
157
  password=SALESFORCE_PASSWORD,
158
  security_token=SALESFORCE_SECURITY_TOKEN
159
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
 
161
+ # Mapping mode and entry_type to Salesforce object and field
162
+ object_name = None
163
+ field_name = None
164
+
165
+ if mode == "Entry":
166
+ if entry_type == "Sales":
167
+ object_name = "VENKATA_RAMANA_MOTORS__c"
168
+ field_name = "Quantity__c"
169
+ elif entry_type == "Non-Sales":
170
+ object_name = "UNBILLING_DATA__c"
171
+ field_name = "TotalQuantity__c"
172
+
173
+ # Get valid fields from Salesforce object schema
174
+ sf_object = sf.__getattr__(object_name)
175
+ schema = sf_object.describe()
176
+ valid_fields = {field["name"] for field in schema["fields"]}
177
+
178
+ # Extract attributes from the extracted text
179
+ attributes = extract_attributes(extracted_text)
180
+
181
+ # Explicitly extract Product Name from the attributes
182
+ product_name = attributes.get("Productname", "").strip() # Extract 'Productname' from the text
183
+ if product_name:
184
+ # Ensure that the Product Name is mapped to the right Salesforce field
185
+ if entry_type == "Sales":
186
+ attributes["Product_Name__c"] = product_name # For VENKATA_RAMANA_MOTORS__c
187
+ elif entry_type == "Non-Sales":
188
+ attributes["Productname__c"] = product_name # For UNBILLING_DATA__c
189
+
190
+ # Convert extracted keys to match Salesforce API field names
191
+ mapped_attributes = {}
192
+ for key, value in attributes.items():
193
+ field_name_sf = key.replace(" ", "_") + "__c" # Convert to Salesforce format
194
+ if field_name_sf in valid_fields:
195
+ mapped_attributes[field_name_sf] = value # Only keep valid fields
196
+
197
+ mapped_attributes[field_name] = quantity # Ensure Quantity is added
198
+
199
+ if not mapped_attributes:
200
+ return "No valid attributes found to export."
201
+
202
+ # Creating a new record with all valid attributes
203
+ sf_object.create(mapped_attributes)
204
+ return f"βœ… Record created in {object_name} with extracted valid attributes and Quantity: {quantity}."
205
+
206
+ elif mode == "Exit":
207
+ if entry_type == "Sales":
208
+ object_name = "Inventory_Management__c"
209
+ field_name = "Quantity_Sold__c"
210
+ elif entry_type == "Non-Sales":
211
+ object_name = "Un_Billable__c"
212
+ field_name = "Sold_Out__c"
213
+
214
+ # Extract product name
215
+ product_name = match_product_name(extracted_text)
216
+ if not product_name:
217
+ return "Product name could not be matched from the extracted text."
218
+
219
+ query = f"SELECT Id, {field_name} FROM {object_name} WHERE Product_Name__c = '{product_name}' LIMIT 1"
220
+ response = sf.query(query)
221
+
222
+ if response["records"]:
223
+ record_id = response["records"][0]["Id"]
224
+ updated_quantity = quantity
225
+ sf.__getattr__(object_name).update(record_id, {field_name: updated_quantity})
226
+ return f"βœ… Updated record for product '{product_name}' in {object_name}. New {field_name}: {updated_quantity}."
227
+ else:
228
+ return f"❌ No matching record found for product '{product_name}' in {object_name}."
229
+
230
+ except Exception as e:
231
+ return f"❌ Error interacting with Salesforce: {str(e)}"
232
+ # Function to pull structured data from Salesforce and display as a table
233
+ def pull_data_from_salesforce():
234
  try:
235
+ sf = Salesforce(
236
+ username=SALESFORCE_USERNAME,
237
+ password=SALESFORCE_PASSWORD,
238
+ security_token=SALESFORCE_SECURITY_TOKEN
239
+ )
240
+
241
+ query = "SELECT Product_Name__c, Modal_Name__c, Current_Stocks__c FROM Inventory_Management__c LIMIT 100"
242
+ response = sf.query_all(query)
243
+
244
+ records = response.get("records", [])
245
+ if not records:
246
+ return "No data found in Salesforce.", None, None, None
247
+
248
+ df = pd.DataFrame(records)
249
+ df = df.drop(columns=['attributes'], errors='ignore')
250
+
251
+ # Rename columns for better readability
252
+ df.rename(columns={
253
+ "Product_Name__c": "Product Name",
254
+ "Modal_Name__c": "Model Name",
255
+ "Current_Stocks__c": "Current Stocks"
256
+ }, inplace=True)
257
+
258
+ excel_path = "salesforce_data.xlsx"
259
+ df.to_excel(excel_path, index=False)
260
+
261
+ # Generate interactive vertical bar graph using Matplotlib
262
+ fig, ax = plt.subplots(figsize=(12, 8))
263
+ df.plot(kind='bar', x="Product Name", y="Current Stocks", ax=ax, legend=False)
264
+ ax.set_title("Stock Distribution by Product Name")
265
+ ax.set_xlabel("Product Name")
266
+ ax.set_ylabel("Current Stocks")
267
+ plt.xticks(rotation=45, ha="right", fontsize=10)
268
  plt.tight_layout()
269
  buffer = BytesIO()
270
  plt.savefig(buffer, format="png")
271
  buffer.seek(0)
272
+ img = Image.open(buffer)
273
+
274
+ return "Data successfully retrieved.", df, excel_path, img
275
  except Exception as e:
276
+ return f"Error fetching data: {str(e)}", None, None, None
277
+
278
+ # Unified function to handle image processing and Salesforce interaction
279
+ def process_image(image, mode, entry_type, quantity):
280
+ extracted_text = extract_text(image)
281
+ if not extracted_text:
282
+ return "No text detected in the image.", None
283
+
284
+ product_name = match_product_name(extracted_text)
285
+ attributes = extract_attributes(extracted_text)
286
+ if product_name:
287
+ attributes["Product name"] = product_name
288
 
289
+ # Interact with Salesforce
290
+ message = interact_with_salesforce(mode, entry_type, quantity, extracted_text)
291
+
292
+ numbered_output = "\n".join([f"{key}: {value}" for key, value in attributes.items()])
293
+ return f"Extracted Text:\n{extracted_text}\n\nAttributes and Values:\n{numbered_output}", message
294
+
295
+ # Gradio Interface
296
  def app():
297
+ return gr.TabbedInterface([
298
+ gr.Interface(
299
+ fn=process_image,
300
+ inputs=[
301
+ gr.Image(type="numpy", label="πŸ“„ Upload Image"),
302
+ gr.Dropdown(label="πŸ“Œ Mode", choices=["Entry", "Exit"], value="Entry"),
303
+ gr.Radio(label="πŸ“¦ Entry Type", choices=["Sales", "Non-Sales"], value="Sales"),
304
+ gr.Number(label="πŸ”’ Quantity", value=1, interactive=True),
305
+ ],
306
+ outputs=[
307
+ gr.Text(label="πŸ“ Extracted Image Data"),
308
+ gr.Text(label="πŸš€ Result")
309
+ ],
310
+ title="🏒 Inventory Management",
311
+ description="πŸ“¦ Inventory Management System"
312
+ ),
313
+ gr.Interface(
314
+ fn=pull_data_from_salesforce,
315
+ inputs=[],
316
+ outputs=[
317
+ gr.Text(label="Status"),
318
+ gr.Dataframe(label="πŸ“¦ Salesforce Data Table"),
319
+ gr.File(label="Download Salesforce Data"),
320
+ gr.Image(label="πŸ“‰ Stock Distribution Bar Graph")
321
+ ],
322
+ title="πŸ“Š Salesforce Data Export",
323
+ description="View, visualize (zoom-in/out), and download Salesforce data (Product Name, Model Name, Current Stocks)."
324
+ )
325
+ ], ["πŸ“₯ OCR Processing", "πŸ“Š Salesforce Data Export"])
 
 
 
 
326
 
327
  if __name__ == "__main__":
328
  app().launch(share=True)
329
+