gopichandra commited on
Commit
77e4681
ยท
verified ยท
1 Parent(s): 958ec02

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +262 -23
app.py CHANGED
@@ -1,38 +1,250 @@
 
 
 
1
  import gradio as gr
 
 
 
2
  import pandas as pd
3
  import matplotlib.pyplot as plt
4
- from simple_salesforce import Salesforce
5
  from io import BytesIO
6
- from PIL import Image
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
 
8
  # Salesforce credentials
9
  SALESFORCE_USERNAME = "venkatramana@sandbox.com"
10
  SALESFORCE_PASSWORD = "Venkat12345@"
11
  SALESFORCE_SECURITY_TOKEN = "GhcJJmjBEefdnukJoz4CAQlR"
12
 
13
- # Function to pull data from Salesforce and format it into a DataFrame
14
- def format_salesforce_data():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  try:
16
- # Connecting to Salesforce
17
  sf = Salesforce(
18
  username=SALESFORCE_USERNAME,
19
  password=SALESFORCE_PASSWORD,
20
  security_token=SALESFORCE_SECURITY_TOKEN
21
  )
22
- # Query to get product data from Inventory_Management__c
23
- query = "SELECT Product_Name__c, Model_Name__c, Current_Stocks__c FROM Inventory_Management__c"
24
- data = sf.query(query)
25
-
26
- if 'records' in data:
27
- # Converting Salesforce data to a pandas DataFrame
28
- df = pd.DataFrame(data['records'])
29
- # Renaming the columns for better readability
 
 
 
30
  df = df.rename(columns={
31
  "Product_Name__c": "Product Name",
32
- "Model_Name__c": "Model Name",
33
  "Current_Stocks__c": "Current Stocks"
34
  })
35
- # Returning only relevant columns
36
  df = df[["Product Name", "Model Name", "Current Stocks"]]
37
  return df
38
  else:
@@ -43,7 +255,6 @@ def format_salesforce_data():
43
  # Function to generate a bar graph from Salesforce data
44
  def generate_bar_graph(df):
45
  try:
46
- # Generating a bar graph for current stock distribution
47
  fig, ax = plt.subplots(figsize=(12, 8))
48
  df.plot(kind='bar', x="Product Name", y="Current Stocks", ax=ax, legend=False)
49
  ax.set_title("Stock Distribution by Product Name")
@@ -51,8 +262,6 @@ def generate_bar_graph(df):
51
  ax.set_ylabel("Current Stocks")
52
  plt.xticks(rotation=45, ha="right", fontsize=10)
53
  plt.tight_layout()
54
-
55
- # Saving the plot into a buffer and converting it to an image
56
  buffer = BytesIO()
57
  plt.savefig(buffer, format="png")
58
  buffer.seek(0)
@@ -61,6 +270,23 @@ def generate_bar_graph(df):
61
  except Exception as e:
62
  return None
63
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  # Gradio Interface
65
  def app():
66
  df = format_salesforce_data()
@@ -68,19 +294,32 @@ def app():
68
  bar_graph_component = None
69
 
70
  if df is not None:
71
- # Converting the DataFrame to an HTML table
72
  table_component = df.to_html(index=False)
73
- # Generating a bar graph image
74
  bar_graph_image = generate_bar_graph(df)
75
  if bar_graph_image:
76
  bar_graph_component = bar_graph_image
77
 
78
  with gr.Blocks() as demo:
79
- with gr.Tab("๐Ÿ“Š Salesforce Data Export"):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  gr.Markdown("## ๐Ÿ“Š Salesforce Data Export")
81
- # Displaying the table
82
  table_output = gr.HTML(value=table_component if table_component else "No Data Available")
83
- # Displaying the bar graph
84
  graph_output = gr.Image(value=bar_graph_component if bar_graph_component else None, type="pil")
85
 
86
  return demo
 
1
+ import os
2
+ from paddleocr import PaddleOCR
3
+ from PIL import Image
4
  import gradio as gr
5
+ import requests
6
+ import re
7
+ from simple_salesforce import Salesforce
8
  import pandas as pd
9
  import matplotlib.pyplot as plt
 
10
  from io import BytesIO
11
+ from fuzzywuzzy import process
12
+
13
+ # Attribute mappings: readable names to Salesforce API names
14
+ ATTRIBUTE_MAPPING = {
15
+ "Product name": "Productname__c",
16
+ "Colour": "Colour__c",
17
+ "Motortype": "Motortype__c",
18
+ "Frequency": "Frequency__c",
19
+ "Grossweight": "Grossweight__c",
20
+ "Ratio": "Ratio__c",
21
+ "MotorFrame": "Motorframe__c",
22
+ "Model": "Model__c",
23
+ "Speed": "Speed__c",
24
+ "Quantity": "Quantity__c",
25
+ "Voltage": "Voltage__c",
26
+ "Material": "Material__c",
27
+ "Type": "Type__c",
28
+ "Horsepower": "Horsepower__c",
29
+ "Consignee": "Consignee__c",
30
+ "LOT": "LOT__c",
31
+ "Stage": "Stage__c",
32
+ "Outlet": "Outlet__c",
33
+ "Serialnumber": "Serialnumber__c",
34
+ "HeadSize": "Headsize__c",
35
+ "Deliverysize": "Deliverysize__c",
36
+ "Phase": "Phase__c",
37
+ "Size": "Size__c",
38
+ "MRP": "MRP__c",
39
+ "Usebefore": "Usebefore__c",
40
+ "Height": "Height__c",
41
+ "MaximumDischarge Flow": "Maximumdischargeflow__c",
42
+ "DischargeRange": "Dischargeflow__c",
43
+ "Assembledby": "Manufacturer__c",
44
+ "Manufacturedate": "Manufacturedate__c",
45
+ "Companyname": "Companyname__c",
46
+ "Customercarenumber": "Customercarenumber__c",
47
+ "SellerAddress": "Selleraddress__c",
48
+ "Selleremail": "Selleremail__c",
49
+ "GSTIN": "GSTIN__c",
50
+ "Totalamount": "Totalamount__c",
51
+ "Paymentstatus": "Paymentstatus__c",
52
+ "Paymentmethod": "Paymentstatus__c",
53
+ "Invoicedate": "Manufacturedate__c",
54
+ "Warranty": "Warranty__c",
55
+ "Brand": "Brand__c",
56
+ "Motorhorsepower": "Motorhorsepower__c",
57
+ "Power": "Power__c",
58
+ "Motorphase": "Motorphase__c",
59
+ "Enginetype": "Enginetype__c",
60
+ "Tankcapacity": "Tankcapacity__c",
61
+ "Head": "Head__c",
62
+ "Usage/Application": "Usage_Application__c",
63
+ "Volts": "volts__c",
64
+ "Hertz": "Hertz__c",
65
+ "Frame": "frame__c",
66
+ "Mounting": "Mounting__c",
67
+ "Tollfreenumber": "Tollfreenumber__c",
68
+ "Pipesize": "Pipesize__c",
69
+ "Manufacturer": "Manufacturer__c",
70
+ "Office": "Office__c",
71
+ "SRnumber": "SRnumber__c",
72
+ "TypeOfEndUse": "TypeOfEndUse__c",
73
+ "Model Name": "Model_Name_Number__c",
74
+ "coolingmethod": "coolingmethod__c"
75
+ }
76
+
77
+ # List of product names to match
78
+ PRODUCT_NAMES = [
79
+ "Centrifugal mono block pump", "SINGLE PHASE MOTOR STARTER", "EasyPact EZC 100",
80
+ "Openwell Submersible Pumpset", "Electric Motor", "Self Priming Pump",
81
+ "Control panel for single phase submersible pumps", "MOTOR", "Submersible pump set",
82
+ "Fusion submersible pump set", "DCT", "Shock proof water proof", "CG COMMERCIAL MOTORS", "Fusion",
83
+ "control panel for single phase submerisible pumps",
84
+ "single phase digital starter dry run and timer panel", "5HP AV1 XL Kirloskar Pump",
85
+ "Phase stainless steel submersible pump", "Submersible pump", "WB15X",
86
+ "Vtype self priming pump", "SP SHINE DISC", "havells submersible pump",
87
+ "Havells open well Submersible pump", "Bertolini pump CK3 90pp",
88
+ "WPA 772 Water Pump Assy", "bertolini TTL triplex high pressure plunger pumps",
89
+ "Generic plunger high pressure pump", "Apple Normal, Banana",
90
+ "Cast Iron KSb centrifugal pump", "5.5kw Water Pump",
91
+ "KSB reliable i line centrifuged pumps", "Apple Normal, Orange, Banana",
92
+ "Positive API 6745 hydraulic diaphragm pump", "1/2 inch Fuel Hose Pipe", "Kirloskar Water Pump",
93
+ "Rotodel motor pump", "PVC Electrical Insulation Materials",
94
+ "Electric kirloskar domestic water pump", "Electrical Insulation Materials",
95
+ "sellowell motor pump", "bhupathi submersible pump set",
96
+ "Flowshine Submersible pump set", "Index submersible pump",
97
+ "Wintoss Plastic Electric Switch Board", "Electric 18 watt ujagar cooler pump",
98
+ "Generator Service", "LG WM FHT1207ZWL, LG REF GL-S292RSCY",
99
+ "Water tank, Filters, Water Pump", "MS Control Submersible Panel",
100
+ "Centrifugal Monoblock Pumps", "Electric Motor with Pump BodyBlue and White",
101
+ "Various Repair and Maintenance Parts", "Earthmax Pump",
102
+ "Water Tank, Filters, Water Pump", "Centrifugal Water Pump for Agriculture",
103
+ "mono block pumps"
104
+ ]
105
 
106
  # Salesforce credentials
107
  SALESFORCE_USERNAME = "venkatramana@sandbox.com"
108
  SALESFORCE_PASSWORD = "Venkat12345@"
109
  SALESFORCE_SECURITY_TOKEN = "GhcJJmjBEefdnukJoz4CAQlR"
110
 
111
+ # Initialize PaddleOCR
112
+ ocr = PaddleOCR(use_angle_cls=True, lang='en')
113
+
114
+ # Function to extract text using PaddleOCR
115
+ def extract_text(image):
116
+ result = ocr.ocr(image)
117
+ extracted_text = []
118
+ for line in result[0]:
119
+ extracted_text.append(line[1][0])
120
+ return "\n".join(extracted_text)
121
+
122
+ # Function to match product name using fuzzy matching
123
+ def match_product_name(extracted_text):
124
+ best_match = None
125
+ best_score = 0
126
+
127
+ for line in extracted_text.split("\n"):
128
+ match, score = process.extractOne(line, PRODUCT_NAMES)
129
+ if score > best_score:
130
+ best_match = match
131
+ best_score = score
132
+
133
+ return best_match if best_score >= 70 else None # Threshold of 70 for a match
134
+
135
+ # Function to extract attributes and their values
136
+ def extract_attributes(extracted_text):
137
+ attributes = {}
138
+
139
+ for readable_attr, sf_attr in ATTRIBUTE_MAPPING.items():
140
+ pattern = rf"{re.escape(readable_attr)}[:\-]?\s*(.+)"
141
+ match = re.search(pattern, extracted_text, re.IGNORECASE)
142
+ if match:
143
+ attributes[readable_attr] = match.group(1).strip()
144
+
145
+ return attributes
146
+
147
+ # Function to filter attributes for valid Salesforce fields
148
+ def filter_valid_attributes(attributes, valid_fields):
149
+ return {ATTRIBUTE_MAPPING[key]: value for key, value in attributes.items() if ATTRIBUTE_MAPPING[key] in valid_fields}
150
+
151
+ # Function to interact with Salesforce based on mode and type
152
+ def interact_with_salesforce(mode, entry_type, quantity, extracted_text):
153
+ try:
154
+ sf = Salesforce(
155
+ username=SALESFORCE_USERNAME,
156
+ password=SALESFORCE_PASSWORD,
157
+ security_token=SALESFORCE_SECURITY_TOKEN
158
+ )
159
+
160
+ # Mapping mode and entry_type to Salesforce object and field
161
+ object_name = None
162
+ field_name = None
163
+ product_field_name = "Product_Name__c" # Correct field for product name in the object
164
+ model_field_name = "Modal_Name__c" # Correct field for model name in the object
165
+
166
+ if mode == "Entry":
167
+ if entry_type == "Sales":
168
+ object_name = "VENKATA_RAMANA_MOTORS__c"
169
+ field_name = "Quantity__c"
170
+ elif entry_type == "Non-Sales":
171
+ object_name = "UNBILLING_DATA__c"
172
+ field_name = "TotalQuantity__c"
173
+ elif mode == "Exit":
174
+ if entry_type == "Sales":
175
+ object_name = "Inventory_Management__c"
176
+ product_field_name = "Product_Name__c"
177
+ model_field_name = "Modal_Name__c"
178
+ field_name = "Quantity_Sold__c"
179
+ elif entry_type == "Non-Sales":
180
+ object_name = "Un_Billable__c"
181
+ product_field_name = "Product_Name__c"
182
+ model_field_name = "Model_Name__c"
183
+ field_name = "Sold_Out__c"
184
+
185
+ if not object_name or not field_name:
186
+ return "Invalid mode or entry type."
187
+
188
+ # Get valid fields for the specified Salesforce object
189
+ sf_object = sf.__getattr__(object_name)
190
+ schema = sf_object.describe()
191
+ valid_fields = {field["name"] for field in schema["fields"]}
192
+
193
+ # Extract product name or model number
194
+ product_name = match_product_name(extracted_text)
195
+ attributes = extract_attributes(extracted_text)
196
+
197
+ if not product_name:
198
+ return "Product name could not be matched from the extracted text."
199
+
200
+ attributes["Product name"] = product_name
201
+
202
+ if mode == "Exit":
203
+ query = f"SELECT Id, {field_name} FROM {object_name} WHERE {product_field_name} = '{product_name}' OR {model_field_name} = '{attributes.get('Model Name', '')}' LIMIT 1"
204
+ response = sf.query(query)
205
+
206
+ if response["records"]:
207
+ record_id = response["records"][0]["Id"]
208
+ current_quantity = response["records"][0].get(field_name, 0) or 0
209
+ updated_quantity = max(0, current_quantity + quantity)
210
+ sf_object.update(record_id, {field_name: updated_quantity})
211
+ return f"Updated record for product '{product_name}' in {object_name}. New {field_name}: {updated_quantity}."
212
+ else:
213
+ return f"No matching record found for product '{product_name}' in {object_name}."
214
+ else:
215
+ filtered_attributes = filter_valid_attributes(attributes, valid_fields)
216
+ filtered_attributes[field_name] = quantity
217
+ sf_object.create(filtered_attributes)
218
+ return f"Data successfully exported to Salesforce object {object_name}."
219
+
220
+ except Exception as e:
221
+ return f"Error interacting with Salesforce: {str(e)}"
222
+
223
+ # Function to pull data from Salesforce MotorDataAPI
224
+ def pull_data_from_motor_api():
225
  try:
 
226
  sf = Salesforce(
227
  username=SALESFORCE_USERNAME,
228
  password=SALESFORCE_PASSWORD,
229
  security_token=SALESFORCE_SECURITY_TOKEN
230
  )
231
+ motor_data = sf.apexecute("MotorDataAPI/", method="GET")
232
+ return motor_data # API returns the list of records
233
+ except Exception as e:
234
+ return f"Error pulling data from MotorDataAPI: {str(e)}"
235
+
236
+ # Function to format Salesforce data into a DataFrame with readable headers
237
+ def format_salesforce_data():
238
+ try:
239
+ data = pull_data_from_motor_api()
240
+ if isinstance(data, list):
241
+ df = pd.DataFrame(data)
242
  df = df.rename(columns={
243
  "Product_Name__c": "Product Name",
244
+ "Modal_Name__c": "Model Name",
245
  "Current_Stocks__c": "Current Stocks"
246
  })
247
+ # Remove unnecessary columns
248
  df = df[["Product Name", "Model Name", "Current Stocks"]]
249
  return df
250
  else:
 
255
  # Function to generate a bar graph from Salesforce data
256
  def generate_bar_graph(df):
257
  try:
 
258
  fig, ax = plt.subplots(figsize=(12, 8))
259
  df.plot(kind='bar', x="Product Name", y="Current Stocks", ax=ax, legend=False)
260
  ax.set_title("Stock Distribution by Product Name")
 
262
  ax.set_ylabel("Current Stocks")
263
  plt.xticks(rotation=45, ha="right", fontsize=10)
264
  plt.tight_layout()
 
 
265
  buffer = BytesIO()
266
  plt.savefig(buffer, format="png")
267
  buffer.seek(0)
 
270
  except Exception as e:
271
  return None
272
 
273
+ # Unified function to handle image processing and Salesforce interaction
274
+ def process_image(image, mode, entry_type, quantity):
275
+ extracted_text = extract_text(image)
276
+ if not extracted_text:
277
+ return "No text detected in the image.", None
278
+
279
+ product_name = match_product_name(extracted_text)
280
+ attributes = extract_attributes(extracted_text)
281
+ if product_name:
282
+ attributes["Product name"] = product_name
283
+
284
+ # Interact with Salesforce
285
+ message = interact_with_salesforce(mode, entry_type, quantity, extracted_text)
286
+
287
+ numbered_output = "\n".join([f"{key}: {value}" for key, value in attributes.items()])
288
+ return f"Extracted Text:\n{extracted_text}\n\nAttributes and Values:\n{numbered_output}", message
289
+
290
  # Gradio Interface
291
  def app():
292
  df = format_salesforce_data()
 
294
  bar_graph_component = None
295
 
296
  if df is not None:
 
297
  table_component = df.to_html(index=False)
 
298
  bar_graph_image = generate_bar_graph(df)
299
  if bar_graph_image:
300
  bar_graph_component = bar_graph_image
301
 
302
  with gr.Blocks() as demo:
303
+ with gr.Tab("๐Ÿ“ฆ ๐‘ท๐‘น๐‘ถ๐‘ช๐‘ฌ๐‘บ๐‘บ ๐‘ฐ๐‘ด๐‘จ๐‘ฎ๐‘ฌ"):
304
+ gr.Interface(
305
+ fn=process_image,
306
+ inputs=[
307
+ gr.Image(type="numpy", label="๐Ÿ“„ Upload Image"),
308
+ gr.Dropdown(label="๐Ÿ“Œ Mode", choices=["Entry", "Exit"], value="Entry"),
309
+ gr.Radio(label="Entry Type", choices=["Sales", "Non-Sales"], value="Sales"),
310
+ gr.Number(label="๐Ÿ”ข Quantity", value=1, interactive=True),
311
+ ],
312
+ outputs=[
313
+ gr.Text(label="๐Ÿ“ Extracted Image Data"),
314
+ gr.Text(label="๐Ÿš€ Result")
315
+ ],
316
+ title="๐Ÿข VENKATARAMANA MOTORS",
317
+ description="๐Ÿ“ฆ Inventory Management System"
318
+ )
319
+
320
+ with gr.Tab("๐Ÿ“Š SALESFORCE DATA EXPORT"):
321
  gr.Markdown("## ๐Ÿ“Š Salesforce Data Export")
 
322
  table_output = gr.HTML(value=table_component if table_component else "No Data Available")
 
323
  graph_output = gr.Image(value=bar_graph_component if bar_graph_component else None, type="pil")
324
 
325
  return demo