Spaces:
Sleeping
Sleeping
| import os | |
| from paddleocr import PaddleOCR | |
| from PIL import Image | |
| import gradio as gr | |
| import requests | |
| import re | |
| from simple_salesforce import Salesforce | |
| import pandas as pd | |
| import matplotlib.pyplot as plt | |
| from io import BytesIO | |
| from fuzzywuzzy import process | |
| gr.Image( | |
| type="numpy", | |
| source="camera", # Enables camera access | |
| label="Upload or Take a Photo", | |
| tool="editor", # Optional: Add editing tools for cropping or annotations | |
| mirror_webcam=False # Ensures the image is not mirrored | |
| ) | |
| from PIL import ImageOps | |
| def correct_orientation(image): | |
| return ImageOps.mirror(image) | |
| # Attribute mappings: readable names to Salesforce API names | |
| ATTRIBUTE_MAPPING = { | |
| "Product name": "Productname__c", | |
| "Colour": "Colour__c", | |
| "Motortype": "Motortype__c", | |
| "Frequency": "Frequency__c", | |
| "Grossweight": "Grossweight__c", | |
| "Ratio": "Ratio__c", | |
| "MotorFrame": "Motorframe__c", | |
| "Model": "Model__c", | |
| "Speed": "Speed__c", | |
| "Quantity": "Quantity__c", | |
| "Voltage": "Voltage__c", | |
| "Material": "Material__c", | |
| "Type": "Type__c", | |
| "Horsepower": "Horsepower__c", | |
| "Consignee": "Consignee__c", | |
| "LOT": "LOT__c", | |
| "Stage": "Stage__c", | |
| "Outlet": "Outlet__c", | |
| "Serialnumber": "Serialnumber__c", | |
| "HeadSize": "Headsize__c", | |
| "Deliverysize": "Deliverysize__c", | |
| "Phase": "Phase__c", | |
| "Size": "Size__c", | |
| "MRP": "MRP__c", | |
| "Usebefore": "Usebefore__c", | |
| "Height": "Height__c", | |
| "MaximumDischarge Flow": "Maximumdischargeflow__c", | |
| "DischargeRange": "Dischargeflow__c", | |
| "Assembledby": "Manufacturer__c", | |
| "Manufacturedate": "Manufacturedate__c", | |
| "Companyname": "Companyname__c", | |
| "Customercarenumber": "Customercarenumber__c", | |
| "SellerAddress": "Selleraddress__c", | |
| "Selleremail": "Selleremail__c", | |
| "GSTIN": "GSTIN__c", | |
| "Totalamount": "Totalamount__c", | |
| "Paymentstatus": "Paymentstatus__c", | |
| "Paymentmethod": "Paymentstatus__c", | |
| "Invoicedate": "Manufacturedate__c", | |
| "Warranty": "Warranty__c", | |
| "Brand": "Brand__c", | |
| "Motorhorsepower": "Motorhorsepower__c", | |
| "Power": "Power__c", | |
| "Motorphase": "Motorphase__c", | |
| "Enginetype": "Enginetype__c", | |
| "Tankcapacity": "Tankcapacity__c", | |
| "Head": "Head__c", | |
| "Usage/Application": "Usage_Application__c", | |
| "Volts": "volts__c", | |
| "Hertz": "Hertz__c", | |
| "Frame": "frame__c", | |
| "Mounting": "Mounting__c", | |
| "Tollfreenumber": "Tollfreenumber__c", | |
| "Pipesize": "Pipesize__c", | |
| "Manufacturer": "Manufacturer__c", | |
| "Office": "Office__c", | |
| "SRnumber": "SRnumber__c", | |
| "TypeOfEndUse": "TypeOfEndUse__c", | |
| "Model Name": "Model_Name_Number__c", | |
| "coolingmethod": "coolingmethod__c" | |
| } | |
| # List of product names to match | |
| PRODUCT_NAMES = [ | |
| "Centrifugal mono block pump", "SINGLE PHASE MOTOR STARTER", "EasyPact EZC 100", | |
| "Openwell Submersible Pumpset", "Electric Motor", "Self Priming Pump", | |
| "Control panel for single phase submersible pumps", "MOTOR", "Submersible pump set", | |
| "Fusion submersible pump set", "DCT", "Shock proof water proof", "CG COMMERCIAL MOTORS", "Fusion", | |
| "control panel for single phase submerisible pumps", | |
| "single phase digital starter dry run and timer panel", "5HP AV1 XL Kirloskar Pump", | |
| "Phase stainless steel submersible pump", "Submersible pump", "WB15X", | |
| "Vtype self priming pump", "SP SHINE DISC", "havells submersible pump", | |
| "Havells open well Submersible pump", "Bertolini pump CK3 90pp", | |
| "WPA 772 Water Pump Assy", "bertolini TTL triplex high pressure plunger pumps", | |
| "Generic plunger high pressure pump", "Apple Normal, Banana", | |
| "Cast Iron KSb centrifugal pump", "5.5kw Water Pump", | |
| "KSB reliable i line centrifuged pumps", "Apple Normal, Orange, Banana", | |
| "Positive API 6745 hydraulic diaphragm pump", "1/2 inch Fuel Hose Pipe", "Kirloskar Water Pump", | |
| "Rotodel motor pump", "PVC Electrical Insulation Materials", | |
| "Electric kirloskar domestic water pump", "Electrical Insulation Materials", | |
| "sellowell motor pump", "bhupathi submersible pump set", | |
| "Flowshine Submersible pump set", "Index submersible pump", | |
| "Wintoss Plastic Electric Switch Board", "Electric 18 watt ujagar cooler pump", | |
| "Generator Service", "LG WM FHT1207ZWL, LG REF GL-S292RSCY", | |
| "Water tank, Filters, Water Pump", "MS Control Submersible Panel", | |
| "Centrifugal Monoblock Pumps", "Electric Motor with Pump BodyBlue and White", | |
| "Various Repair and Maintenance Parts", "Earthmax Pump", | |
| "Water Tank, Filters, Water Pump", "Centrifugal Water Pump for Agriculture", | |
| "mono block pumps" | |
| ] | |
| # Salesforce credentials | |
| SALESFORCE_USERNAME = "venkatramana@sandbox.com" | |
| SALESFORCE_PASSWORD = "Venkat12345@" | |
| SALESFORCE_SECURITY_TOKEN = "GhcJJmjBEefdnukJoz4CAQlR" | |
| # Initialize PaddleOCR | |
| ocr = PaddleOCR(use_angle_cls=True, lang='en') | |
| # Function to extract text using PaddleOCR | |
| def extract_text(image): | |
| result = ocr.ocr(image) | |
| extracted_text = [] | |
| for line in result[0]: | |
| extracted_text.append(line[1][0]) | |
| return "\n".join(extracted_text) | |
| # Function to interact with Salesforce based on mode and type | |
| def interact_with_salesforce(mode, entry_type, quantity, extracted_text): | |
| try: | |
| sf = Salesforce( | |
| username=SALESFORCE_USERNAME, | |
| password=SALESFORCE_PASSWORD, | |
| security_token=SALESFORCE_SECURITY_TOKEN | |
| ) | |
| # Mapping mode and entry_type to Salesforce object and field | |
| object_name = None | |
| field_name = None | |
| product_field_name = "Product_Name__c" # Correct field for product name in the object | |
| model_field_name = "Modal_Name__c" # Correct field for model name in the object | |
| if mode == "Entry": | |
| if entry_type == "Sales": | |
| object_name = "VENKATA_RAMANA_MOTORS__c" | |
| field_name = "Quantity__c" | |
| elif entry_type == "Non-Sales": | |
| object_name = "UNBILLING_DATA__c" | |
| field_name = "TotalQuantity__c" | |
| elif mode == "Exit": | |
| if entry_type == "Sales": | |
| object_name = "Inventory_Management__c" | |
| product_field_name = "Product_Name__c" | |
| model_field_name = "Modal_Name__c" | |
| field_name = "Quantity_Sold__c" | |
| elif entry_type == "Non-Sales": | |
| object_name = "Un_Billable__c" | |
| product_field_name = "Product_Name__c" | |
| model_field_name = "Model_Name__c" | |
| field_name = "Sold_Out__c" | |
| if not object_name or not field_name: | |
| return "Invalid mode or entry type." | |
| # Get valid fields for the specified Salesforce object | |
| sf_object = sf.__getattr__(object_name) | |
| schema = sf_object.describe() | |
| valid_fields = {field["name"] for field in schema["fields"]} | |
| # Extract product name or model number | |
| product_name_match = re.search(r"Product name[:\-]?\s*(.+)", extracted_text, re.IGNORECASE) | |
| model_name_match = re.search(r"Model[:\-]?\s*(.+)", extracted_text, re.IGNORECASE) | |
| if not product_name_match and not model_name_match: | |
| return "Product name or model name not found in the extracted text." | |
| product_name_value = product_name_match.group(1).strip() if product_name_match else None | |
| model_name_value = model_name_match.group(1).strip() if model_name_match else None | |
| # Query for existing record by product name or model name | |
| if mode == "Exit": | |
| query = f"SELECT Id, {field_name} FROM {object_name} WHERE {product_field_name} = '{product_name_value}' OR {model_field_name} = '{model_name_value}' LIMIT 1" | |
| response = sf.query(query) | |
| if response["records"]: | |
| record_id = response["records"][0]["Id"] | |
| current_quantity = response["records"][0].get(field_name, 0) or 0 # Ensure current_quantity is not None | |
| updated_quantity = max(0, current_quantity + quantity) # Add the quantity directly for sales | |
| sf_object.update(record_id, {field_name: updated_quantity}) | |
| return f"Updated record for product '{product_name_value}' in {object_name}. New {field_name}: {updated_quantity}." | |
| else: | |
| return f"No matching record found for product '{product_name_value}' in {object_name}." | |
| else: | |
| # For Entry mode, include all mapped attributes | |
| structured_data = {field_name: quantity} | |
| for readable_attr, sf_attr in ATTRIBUTE_MAPPING.items(): | |
| pattern = rf"{re.escape(readable_attr)}[:\-]?\s*(.+)" | |
| match = re.search(pattern, extracted_text, re.IGNORECASE) | |
| if match and sf_attr in valid_fields: | |
| structured_data[sf_attr] = match.group(1).strip() | |
| # Insert data into Salesforce | |
| sf_object.create(structured_data) | |
| return f"Data successfully exported to Salesforce object {object_name}." | |
| except Exception as e: | |
| return f"Error interacting with Salesforce: {str(e)}" | |
| # Function to pull data from Salesforce MotorDataAPI | |
| def pull_data_from_motor_api(): | |
| try: | |
| sf = Salesforce( | |
| username=SALESFORCE_USERNAME, | |
| password=SALESFORCE_PASSWORD, | |
| security_token=SALESFORCE_SECURITY_TOKEN, | |
| ) | |
| motor_data = sf.apexecute("MotorDataAPI/", method="GET") | |
| return motor_data # API returns the list of records | |
| except Exception as e: | |
| return f"Error pulling data from MotorDataAPI: {str(e)}" | |
| # Function to format Salesforce data into a DataFrame with readable headers | |
| def format_salesforce_data(): | |
| try: | |
| data = pull_data_from_motor_api() | |
| if isinstance(data, list): | |
| df = pd.DataFrame(data) | |
| df = df.rename(columns={ | |
| "Product_Name__c": "Product Name", | |
| "Modal_Name__c": "Model Name", | |
| "Current_Stocks__c": "Current Stocks" | |
| }) | |
| # Remove unnecessary columns | |
| df = df[["Product Name", "Model Name", "Current Stocks"]] | |
| return df | |
| else: | |
| return None | |
| except Exception as e: | |
| return None | |
| # Function to generate a bar graph from Salesforce data | |
| def generate_bar_graph(df): | |
| try: | |
| fig, ax = plt.subplots(figsize=(12, 8)) | |
| df.plot(kind='bar', x="Product Name", y="Current Stocks", ax=ax, legend=False) | |
| ax.set_title("Stock Distribution by Product Name") | |
| ax.set_xlabel("Product Name") | |
| ax.set_ylabel("Current Stocks") | |
| plt.xticks(rotation=45, ha="right", fontsize=10) | |
| plt.tight_layout() | |
| buffer = BytesIO() | |
| plt.savefig(buffer, format="png") | |
| buffer.seek(0) | |
| img = Image.open(buffer) | |
| return img | |
| except Exception as e: | |
| return None | |
| # Unified function to handle image processing and Salesforce interaction | |
| def process_image(image, mode, entry_type, quantity): | |
| extracted_text = extract_text(image) | |
| if not extracted_text: | |
| return "No text detected in the image.", None | |
| # Interact with Salesforce | |
| message = interact_with_salesforce(mode, entry_type, quantity, extracted_text) | |
| return extracted_text, message | |
| # Gradio Interface | |
| def app(): | |
| df = format_salesforce_data() | |
| table_component = None | |
| bar_graph_component = None | |
| if df is not None: | |
| table_component = df.to_html(index=False) | |
| bar_graph_image = generate_bar_graph(df) | |
| if bar_graph_image: | |
| bar_graph_component = bar_graph_image | |
| return gr.TabbedInterface([ | |
| gr.Interface( | |
| fn=process_image, | |
| inputs=[ | |
| gr.Image(type="numpy", label="Upload Image"), | |
| gr.Dropdown(label="Mode", choices=["Entry", "Exit"], value="Entry"), | |
| gr.Radio(label="Entry Type", choices=["Sales", "Non-Sales"], value="Sales"), | |
| gr.Number(label="Quantity", value=1, interactive=True), | |
| ], | |
| outputs=[ | |
| gr.Text(label="Image Data Viewer"), | |
| gr.Text(label="Result") | |
| ], | |
| title="Salesforce Export", | |
| description="Upload an image, select Entry/Exit mode and Sales/Non-Sales type, and specify quantity." | |
| ), | |
| gr.Interface( | |
| fn=lambda: (table_component, bar_graph_component), | |
| inputs=[], | |
| outputs=[ | |
| gr.HTML(label="Salesforce Data Table"), | |
| gr.Image(type="pil", label="Stock Distribution Bar Graph") | |
| ], | |
| title="Salesforce Data", | |
| description="View structured Salesforce data as a table and bar graph." | |
| ) | |
| ], ["Processing", "Salesforce Data"]) | |
| if __name__ == "__main__": | |
| app().launch(share=True) | |