AIEmailAutomationUtility 0.0.26__py3-none-any.whl → 0.0.28__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -95,6 +95,12 @@ class EmailReplyAssistant:
95
95
 
96
96
  def identify_customer_product_reply_assitant(self, openAI_key, assistant_ID, email_content, subject, prompt):
97
97
  try:
98
+ logger.log(f"the Assistant id is ::: {assistant_ID}")
99
+ logger.log(f"the Prompt is ::: {prompt}")
100
+ logger.log(f"the Api key is ::: {openAI_key}")
101
+ logger.log(f"the email content is ::: {email_content}")
102
+ logger.log(f"the subject is ::: {subject}")
103
+
98
104
  openAI_response = ""
99
105
  client = OpenAI(api_key=openAI_key)
100
106
  thread = client.beta.threads.create()
@@ -102,7 +108,8 @@ class EmailReplyAssistant:
102
108
  client.beta.threads.messages.create(
103
109
  thread_id=thread.id,
104
110
  role="user",
105
- content=f"subject:{subject}\nemail body:{email_content}",
111
+ # content=f"subject:{subject}\nemail body:{email_content}",
112
+ content=prompt,
106
113
  )
107
114
 
108
115
  event_handler = EmailReplyAssistant().EventHandler()
@@ -110,7 +117,7 @@ class EmailReplyAssistant:
110
117
  with client.beta.threads.runs.stream(
111
118
  thread_id=thread.id,
112
119
  assistant_id=assistant_ID,
113
- instructions=prompt,
120
+ # instructions=prompt,
114
121
  event_handler=event_handler,
115
122
  ) as stream:
116
123
  stream.until_done()
@@ -552,7 +552,8 @@ class Email_Read:
552
552
  logger.log(f"Exception in writeJsonFile: {msg} \n {trace} \n DataType ::: {type(msg)}")
553
553
  raise Exception(msg)
554
554
 
555
- def log_email_login(self, user_id, email, model_name, login_status, base_dir="EMail_log"):
555
+ def log_email_login(self, user_id, email, model_name, login_status):
556
+ base_dir="EMail_log"
556
557
  timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
557
558
  log_dir = os.path.join(base_dir, user_id)
558
559
  os.makedirs(log_dir, exist_ok=True)
@@ -42,16 +42,14 @@ class Process_Category:
42
42
  is_html = dataValues.get('is_html')
43
43
  import_file = dataValues.get('import_file')
44
44
 
45
-
46
- logger.log(f"the json datavalues of mailare ------------------------ {mail}")
47
- logger.log(f"the json datavalues of email_id are ------------------------ {email_id}")
48
- logger.log(f"the category is ------------------------ {category}")
45
+ customer_determination = None
46
+ product_determination = None
49
47
 
50
48
  if category == "Product Enquiry":
51
49
  if Model_Name == "OpenAI":
52
50
  action_taken = "Reply email drafted using Open_AI Model"
53
51
  responseMethod, parameters = self.get_JsonArray_values(category, file_JsonArray)
54
- logger.log(f"the repsonse method{responseMethod}")
52
+ logger.log(f"the repsonse method is ::: {responseMethod}")
55
53
  if responseMethod == "Reply_Email_Ai_Assistant":
56
54
  emailreplyassistant = EmailReplyAssistant()
57
55
  openai_Response = emailreplyassistant.Reply_Email_Ai_Assistant(openai_api_key, parameters["Assistant_Id"], openai_Process_Input, subject)
@@ -107,47 +105,51 @@ class Process_Category:
107
105
  logger.log(f"fileName 107::: {fileName}")
108
106
  logger.log(f"document_type 108::: {document_type}")
109
107
 
110
- if responseMethod == "Upload_Document":
111
- # Get today's date folder path
112
- today_date = datetime.today().strftime('%Y-%m-%d')
113
- order_folder = os.path.join(document_type, today_date)
114
-
115
- email_upload_document = Email_DocumentUploader()
116
- if len(fileName) != 0:
117
- file_path = os.path.join(order_folder, fileName) # Correct file path
118
-
119
- with open(file_path, "rb") as file:
120
- parameters["DOCUMENT_TYPE"] = document_type
121
-
122
- logger.log(f"Updated Parameters ::: {parameters}")
123
- response_status, restAPI_Result = email_upload_document.email_document_upload(file, parameters)
124
- logger.log(f"email_upload_document_response ::: {restAPI_Result}")
125
- else:
126
- document_type = "Order Email"
108
+ if document_type != '':
109
+ if responseMethod == "Upload_Document":
127
110
  # Get today's date folder path
128
111
  today_date = datetime.today().strftime('%Y-%m-%d')
129
112
  order_folder = os.path.join(document_type, today_date)
130
113
 
131
- parameters["DOCUMENT_TYPE"] = document_type
132
- logger.log(f"Updated Parameters ::: {parameters}")
133
- new_fileName = self.create_file_from_emailBody(email_body, sender_email_addr, parameters)
134
- new_file_path = os.path.join(order_folder, new_fileName)
135
-
136
- with open(new_file_path, "rb") as file:
137
- response_status, restAPI_Result = email_upload_document.email_document_upload(file, parameters)
138
- logger.log(f"email_upload_document_response ::: {restAPI_Result}")
139
-
140
- if response_status == "200":
141
- logger.log(f"Attachment uploaded successfully against Document ID: '{restAPI_Result}'.")
142
- csv_data_status="Success",
143
- csv_data_response=f"Attachment uploaded successfully against Document ID: '{restAPI_Result}'"
114
+ email_upload_document = Email_DocumentUploader()
115
+ if len(fileName) != 0:
116
+ file_path = os.path.join(order_folder, fileName) # Correct file path
117
+
118
+ with open(file_path, "rb") as file:
119
+ parameters["DOCUMENT_TYPE"] = document_type
120
+
121
+ logger.log(f"Updated Parameters ::: {parameters}")
122
+ response_status, restAPI_Result = email_upload_document.email_document_upload(file, parameters)
123
+ logger.log(f"email_upload_document_response ::: {restAPI_Result}")
124
+ else:
125
+ document_type = "Order Email"
126
+ # Get today's date folder path
127
+ today_date = datetime.today().strftime('%Y-%m-%d')
128
+ order_folder = os.path.join(document_type, today_date)
129
+
130
+ parameters["DOCUMENT_TYPE"] = document_type
131
+ logger.log(f"Updated Parameters ::: {parameters}")
132
+ new_fileName = self.create_file_from_emailBody(email_body, sender_email_addr, parameters)
133
+ new_file_path = os.path.join(order_folder, new_fileName)
134
+
135
+ with open(new_file_path, "rb") as file:
136
+ response_status, restAPI_Result = email_upload_document.email_document_upload(file, parameters)
137
+ logger.log(f"email_upload_document_response ::: {restAPI_Result}")
138
+
139
+ if response_status == "200":
140
+ logger.log(f"Attachment uploaded successfully against Document ID: '{restAPI_Result}'.")
141
+ csv_data_status="Success",
142
+ csv_data_response=f"Attachment uploaded successfully against Document ID: '{restAPI_Result}'"
143
+ else:
144
+ logger.log(restAPI_Result)
145
+ csv_data_status="Fail",
146
+ csv_data_response=f"Attachment uploaded Failed against Document ID: '{restAPI_Result}'"
144
147
  else:
145
- logger.log(restAPI_Result)
146
- csv_data_status="Fail",
147
- csv_data_response=f"Attachment uploaded Failed against Document ID: '{restAPI_Result}'"
148
+ message = f"Invalid response method received '{responseMethod}' for category : '{category}'"
149
+ raise ValueError(message)
148
150
  else:
149
- message = f"Invalid response method received '{responseMethod}' for category : '{category}'"
150
- raise ValueError(message)
151
+ csv_data_status="Fail",
152
+ csv_data_response=f"Respective document type has not matched for uploading."
151
153
 
152
154
  elif category == "Quotation":
153
155
  action_taken = f"Mail drafted for products rate"
@@ -156,32 +158,39 @@ class Process_Category:
156
158
 
157
159
  # Step 4: Identify customer from email using AI
158
160
  customer_data = self.identify_customer(email_body, subject, Model_Name, openai_api_key, geminiAI_APIKey, localAIURL, parameters["Customer_Assistant_Id"])
159
- logger.log(f"Identified customer: {customer_data}")
160
- logger.log(f'This is the customer data we are getting ::: {customer_data}')
161
+ logger.log(f"Identified customer is ::: {customer_data}")
162
+
163
+ customer_determination=customer_data
164
+
161
165
  # Extract customer code once
162
166
  customer_code = customer_data.get("customer_code", "")
163
167
 
164
168
  # Step 5: Identify product from email using AI
165
169
  products = self.identify_products(email_body, subject, Model_Name, openai_api_key, geminiAI_APIKey, localAIURL, parameters["Product_Assistant_Id"])
166
- logger.log(f'this is the products data we are getting ::: {products}')
170
+ logger.log(f'Identified Products are ::: {products}')
171
+
172
+ product_determination=products
167
173
 
168
174
  db_connection = sqlite3.connect('/home/base/git/ai-email-automation/AI_Email/database/fetchprice.db')
169
175
  for product in products:
170
- cursor = db_connection.cursor()
171
-
172
176
  item_no = product.get("item_no", "").strip()
173
177
  make = product.get("make", "").strip()
174
178
  rate = None
175
179
  found_rate = False
176
180
 
181
+ logger.log(f"item no is ::: {item_no}")
182
+ logger.log(f"make is ::: {make}")
183
+
177
184
  # Step 1: Get base price from PRICE_LIST
178
185
  query_price = '''
179
186
  SELECT PRICE
180
187
  FROM PRICE_LIST
181
188
  WHERE ITEM_NO = ?;
182
189
  '''
190
+ cursor = db_connection.cursor()
183
191
  cursor.execute(query_price, (item_no,))
184
192
  price_result = cursor.fetchone()
193
+ cursor.close()
185
194
 
186
195
  if price_result:
187
196
  price_raw = price_result[0]
@@ -194,17 +203,16 @@ class Process_Category:
194
203
 
195
204
  try:
196
205
  raw_price = float(price_cleaned)
197
- logger.log(f"[0] Base price for item '{item_no}' is {raw_price}")
206
+ logger.log(f"Process_Category - Quotation [0] Base price for item '{item_no}' is {raw_price}")
198
207
  except (TypeError, ValueError):
199
- logger.log(f"[0] Invalid raw price for item '{item_no}': {price_result[0]}")
208
+ logger.log(f"Process_Category - Quotation [0] Invalid raw price for item '{item_no}': {price_result[0]}")
200
209
  product["rate"] = None
201
210
  continue
202
211
  else:
203
- logger.log(f"[0] No base price found for item '{item_no}'. Skipping...")
204
- product["rate"] = None
212
+ logger.log(f"Process_Category - Quotation [0] No base price found for item '{item_no}' .")
213
+ product["rate"] = "NA"
205
214
  continue
206
215
 
207
-
208
216
  # Condition 1: Exact match in special_rate_customer_wise
209
217
  query1 = '''
210
218
  SELECT RATE
@@ -212,13 +220,16 @@ class Process_Category:
212
220
  WHERE ITEM_CODE = ?
213
221
  AND CUSTOMER_CODE = ?;
214
222
  '''
223
+ cursor = db_connection.cursor()
215
224
  cursor.execute(query1, (item_no, customer_code))
216
225
  result = cursor.fetchone()
226
+ cursor.close()
217
227
 
218
228
  if result:
219
229
  rate = result[0]
220
230
  found_rate = True
221
- logger.log(f"[1] Special Rate for item '{item_no}' and customer '{customer_code}' is {rate}")
231
+ logger.log(f"Process_Category - Quotation [1] Special Rate for item '{item_no}' and customer '{customer_code}' is {rate}")
232
+ price_pickup_source="SPECIAL_RATE_CUSTOMER_WISE"
222
233
 
223
234
  # Condition 2: Customer + Manufacturer discount
224
235
  if not found_rate:
@@ -227,15 +238,18 @@ class Process_Category:
227
238
  FROM CUSTOMER_WISE_DISCOUNT
228
239
  WHERE CUSTOMER_CODE = ? AND MAKE = ?;
229
240
  '''
241
+ cursor = db_connection.cursor()
230
242
  cursor.execute(query2, (customer_code, make))
231
243
  discount_result = cursor.fetchone()
244
+ cursor.close()
232
245
 
233
246
  if discount_result:
234
247
  discount_percent = discount_result[0]
235
248
  rate = raw_price * (1 - int(discount_percent) / 100)
236
249
  rate = round(rate, 2)
237
250
  found_rate = True
238
- logger.log(f"[2] Discounted rate for '{make}' ({discount_percent}%) on price {raw_price}: {rate}")
251
+ logger.log(f"Process_Category - Quotation [2] Discounted rate for '{make}' ({discount_percent}%) on price {raw_price}: {rate}")
252
+ price_pickup_source="CUSTOMER_WISE_DISCOUNT"
239
253
 
240
254
  # Condition 3: Past Sales most used make
241
255
  if not found_rate:
@@ -248,8 +262,10 @@ class Process_Category:
248
262
  ORDER BY COUNT(*) DESC
249
263
  LIMIT 1;
250
264
  '''
265
+ cursor = db_connection.cursor()
251
266
  cursor.execute(query3, (customer_code, item_no))
252
267
  past_sales_result = cursor.fetchone()
268
+ cursor.close()
253
269
 
254
270
  if past_sales_result:
255
271
  most_common_make, past_discount = past_sales_result
@@ -257,12 +273,11 @@ class Process_Category:
257
273
  rate = raw_price * (1 - int(past_discount) / 100)
258
274
  rate = round(rate, 2)
259
275
  found_rate = True
260
- logger.log(f"[3] Fallback: Most used make '{most_common_make}' for customer '{customer_code}' got {past_discount}% discount. Rate: {rate}")
276
+ logger.log(f"Process_Category - Quotation [3] Fallback: Most used make '{most_common_make}' for customer '{customer_code}' got {past_discount}% discount. Rate: {rate}")
277
+ price_pickup_source="PAST_SALES"
261
278
  else:
262
- logger.log(f"[3] Fallback: Invalid price for item '{item_no}'")
263
- else:
264
- logger.log(f"[3] No past sales data for item '{item_no}' and customer '{customer_code}'")
265
-
279
+ logger.log(f"Process_Category - Quotation [3] Fallback: Invalid price for item '{item_no}'")
280
+
266
281
  # Condition 4: Manufacturer General Discount
267
282
  if not found_rate:
268
283
  query4 = '''
@@ -270,20 +285,27 @@ class Process_Category:
270
285
  FROM MANUFACTURE_WISE_GENERAL_DISCOUNT
271
286
  WHERE MAKE = ?;
272
287
  '''
288
+ cursor = db_connection.cursor()
273
289
  cursor.execute(query4, (make,))
274
290
  general_discount_result = cursor.fetchone()
291
+ cursor.close()
275
292
 
276
293
  if general_discount_result:
277
294
  general_discount_percent = general_discount_result[0]
278
295
  rate = raw_price * (1 - int(general_discount_percent) / 100)
279
296
  rate = round(rate, 2)
280
297
  found_rate = True
281
- logger.log(f"[4] General Discount for '{make}' ({general_discount_percent}%) on price {raw_price}: {rate}")
282
- else:
283
- logger.log(f"[4] No applicable discount found for item '{item_no}'")
298
+ logger.log(f"Process_Category - Quotation [4] General Discount for '{make}' ({general_discount_percent}%) on price {raw_price}: {rate}")
299
+ price_pickup_source="MANUFACTURE_WISE_GENERAL_DISCOUNT"
300
+
301
+ #Condition 5: Fallback to raw_price if no discount applied
302
+ if not found_rate:
303
+ rate = raw_price
304
+ logger.log(f"Process_Category - Quotation [5] No discounts applied. Using base price for item '{item_no}': {rate}")
305
+ price_pickup_source="PRICE_LIST"
284
306
 
285
307
  product["rate"] = rate
286
- cursor.close()
308
+ product["Price Pickup Source"]=price_pickup_source
287
309
 
288
310
  db_connection.close()
289
311
 
@@ -311,8 +333,6 @@ class Process_Category:
311
333
 
312
334
  csv_data_status = status
313
335
  csv_data_response = response
314
- # csv_data_status = "status"
315
- # csv_data_response = "response"
316
336
  logger.log(f"Quotation email sent to {sender_email_addr}")
317
337
 
318
338
  elif category == "Others" and import_file == True:
@@ -325,7 +345,7 @@ class Process_Category:
325
345
  csv_data_response = f""
326
346
 
327
347
  logger.log(f"Marking email as UNREAD. ")
328
- logger.log(f"email_id: {email_id}, type: {type(email_id)}")
348
+ # print(f"email_id: {email_id}, type: {type(email_id)}")
329
349
  mail.store(email_id, '-FLAGS', '\\Seen')
330
350
  mail.create(LABEL)
331
351
  mail.copy(email_id, LABEL)
@@ -335,7 +355,7 @@ class Process_Category:
335
355
 
336
356
  current_timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
337
357
  filename = f'{uid}{current_timestamp}'
338
- logger.log(f"the file name is ---------------- {filename}")
358
+ logger.log(f"The file name for csv and eml is ::: {filename}")
339
359
  self.store_email_details_to_csv(
340
360
  email_id=f'{uid}{current_timestamp}',
341
361
  to_email=parseaddr(to_email_addr)[1],
@@ -349,7 +369,9 @@ class Process_Category:
349
369
  user_id=user_id,
350
370
  status=csv_data_status,
351
371
  response=csv_data_response,
352
- current_timestamp=current_timestamp
372
+ current_timestamp=current_timestamp,
373
+ customer_determination=customer_determination,
374
+ product_determination=product_determination,
353
375
  )
354
376
  self.store_email_as_eml(
355
377
  uid=f'{uid}{current_timestamp}',
@@ -380,7 +402,7 @@ class Process_Category:
380
402
 
381
403
  filename = ""
382
404
  mime_type = ""
383
- document_type = "Orders"
405
+ document_type = ""
384
406
 
385
407
  for part in msg.walk():
386
408
  if part.get_content_maintype() == 'multipart':
@@ -460,10 +482,10 @@ class Process_Category:
460
482
  logger.log("Inside identify_customer")
461
483
 
462
484
  if model_type == "OpenAI":
463
- prompt = f"""Identify the customer code, customer name in json format from the following email {email_body} and received from {subject}. Do not include any instruction as the output will be directly in a program."""
485
+ prompt = f"""/* Identify the most likely customer code, customer name from the following email using the file attached in assistant. Use various key information's such as sender name, organisation, address, email id to determine the customer. If customer not available in the data return the name and NA as code. Return the data in json format. Always return 1 row. Do not include any instruction as the output will be directly in a program. */ /n {email_body}"""
464
486
  emailreplyassistant = EmailReplyAssistant()
465
487
  ai_result = emailreplyassistant.identify_customer_product_reply_assitant(openai_api_key, assistant_id, email_body, subject, prompt)
466
-
488
+
467
489
  elif model_type == "GeminiAI":
468
490
  prompt = f"""Identify the customer code, customer name in json format from the following email {email_body} and received from {subject}. Do not include any instruction as the output will be directly in a program."""
469
491
  ai_result = self.identify_customer_product_GeminiAI(gemini_api_key, email_body, prompt)
@@ -490,11 +512,7 @@ class Process_Category:
490
512
  logger.log("Inside identify_products")
491
513
 
492
514
  if model_type == "OpenAI":
493
- prompt = f"""
494
- Can you give me price information of all products in following format requested_description, item_no, make, description, price, price unit, inventory unit for following items in strictly in JSON String format {email_body}.
495
- If there is one product or multiple should return in list.
496
- Do not include any instruction as the output will be directly in a program.
497
- """
515
+ prompt = f"""/* Extract complete item pricing information from the following mixed-format email content. The email may contain a combination of:- descriptive product listings- tabular structured price info- semi-structured lines with HSN, quantity, material, etc. Give me price in INR and information of all items in following format requested_description, item_no, make, description, price, price unit, inventory unit strictly in JSON format. If the item is not available in the assistant files return requested description from email data and rest of the columns as NA. Do not include any instruction as the output will be directly in a program. */ /n {email_body}. """
498
516
  emailreplyassistant = EmailReplyAssistant()
499
517
  ai_result = emailreplyassistant.identify_customer_product_reply_assitant(openai_api_key, assistant_id, email_body, subject, prompt)
500
518
 
@@ -539,7 +557,7 @@ class Process_Category:
539
557
  Customer Code: {customer.get('customer_code', '')}
540
558
 
541
559
  {product_table}
542
- product_table must contain only price column even if it is none(set it as -).
560
+ product_table must contain price column, if it is none(set it as -).
543
561
  Original Email Subject: {subject}
544
562
 
545
563
  Return only the following JSON String format:
@@ -750,7 +768,7 @@ class Process_Category:
750
768
  logger.log(f"Error with Gemini AI detection/generation: {str(e)}")
751
769
  return {"success": "Failed", "message": f"Error with Gemini AI detection/generation: {str(e)}"}
752
770
 
753
- def store_email_details_to_csv(self, email_id, to_email, from_email, cc_email, subject, body, email_type, action_performed, filename, user_id,status,response,current_timestamp):
771
+ def store_email_details_to_csv(self, email_id, to_email, from_email, cc_email, subject, body, email_type, action_performed, filename, user_id,status,response,current_timestamp,customer_determination,product_determination):
754
772
  """
755
773
  Stores the extracted email details to a CSV file inside 'Mail_log/mail_log_user_id' folder
756
774
  with the name user_id.csv.
@@ -765,28 +783,55 @@ class Process_Category:
765
783
  os.makedirs(user_folder, exist_ok=True)
766
784
 
767
785
  filename = filename.lstrip()
768
- logger.log(f"filename ::: [{filename}]")
769
786
  full_csv_path = os.path.join(user_folder, f"{filename}.csv")
770
- logger.log(f"full_csv_path ::: {full_csv_path}")
771
787
 
772
- # Prepare the data to write
773
- csv_data = [{
788
+ if email_type=="Quotation":
789
+ csv_data = [{
774
790
  'to': to_email,
775
791
  'from': from_email,
776
792
  'cc': cc_email,
777
793
  'subject': subject,
778
794
  'body': body.replace('\n', ' ').replace('\r', ''),
779
795
  'Category': email_type,
780
- 'Action performed': action_performed,
796
+ 'Action Performed': action_performed,
781
797
  'unique_id': email_id,
782
798
  'timestamp': current_timestamp,
783
799
  'status of mail draft': status,
784
- 'Response generated':response
800
+ 'Response Generated':response,
801
+ 'Customer Determination':customer_determination,
802
+ 'Product Determination':product_determination,
785
803
  }]
804
+ else:
805
+ csv_data = [{
806
+ 'to': to_email,
807
+ 'from': from_email,
808
+ 'cc': cc_email,
809
+ 'subject': subject,
810
+ 'body': body.replace('\n', ' ').replace('\r', ''),
811
+ 'Category': email_type,
812
+ 'Action Performed': action_performed,
813
+ 'unique_id': email_id,
814
+ 'timestamp': current_timestamp,
815
+ 'status of mail draft': status,
816
+ 'Response Generated':response
817
+ }]
786
818
 
787
819
  # Write to CSV file (user_id.csv)
788
820
  with open(full_csv_path, 'a', newline='', encoding='utf-8') as csvfile:
789
- fieldnames = ['to', 'from', 'cc', 'timestamp', 'subject', 'body', 'Category', 'Action performed', 'unique_id','status of mail draft','Response generated']
821
+ if email_type == "Quotation":
822
+ fieldnames = [
823
+ 'to', 'from', 'cc', 'timestamp', 'subject', 'body',
824
+ 'Category', 'Action Performed', 'unique_id',
825
+ 'status of mail draft', 'Response Generated',
826
+ 'Customer Determination', 'Product Determination'
827
+ ]
828
+ else:
829
+ fieldnames = [
830
+ 'to', 'from', 'cc', 'timestamp', 'subject', 'body',
831
+ 'Category', 'Action Performed', 'unique_id',
832
+ 'status of mail draft', 'Response Generated'
833
+ ]
834
+
790
835
  writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
791
836
 
792
837
  # If the file is empty, write the header
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: AIEmailAutomationUtility
3
- Version: 0.0.26
4
- Summary: Resolve the issue of email and excel file uploading on orders
3
+ Version: 0.0.28
4
+ Summary: Set Bydefault document type as blank to avoid garbage data while uploading
5
5
  Author: Proteus Technology PVT. LTD.
6
6
  Author-email: <apps@baseinformation.com>
7
7
  Keywords: python,first package
@@ -13,4 +13,4 @@ Classifier: Operating System :: MacOS :: MacOS X
13
13
  Classifier: Operating System :: Microsoft :: Windows
14
14
  License-File: LICENCE.txt
15
15
 
16
- Resolve the issue of email and excel file uploading on orders
16
+ Set Bydefault document type as blank to avoid garbage data while uploading
@@ -1,15 +1,15 @@
1
- AIEmailAutomationUtility/EmailReplyAssistant.py,sha256=oRobM6C1AwiRA3lQ2Sh51m-FaH2PpbUEidbkOG7O9Ww,6339
1
+ AIEmailAutomationUtility/EmailReplyAssistant.py,sha256=R_wJna3-ITsVxQEccryhM93T_Nf_Oxo8DXnS-sDN8VE,6679
2
2
  AIEmailAutomationUtility/Email_Classification.py,sha256=Ar0g4Ff8HOT7xICktd3nP_C_vCyeY-xCpUjVCVRWAyc,9417
3
3
  AIEmailAutomationUtility/Email_DocumentUploader.py,sha256=YJu4tuTHr0K-5vuds9gZfj-Hwsgm4MuAOP39Lmu_t98,3219
4
4
  AIEmailAutomationUtility/Email_Draft.py,sha256=DcyBeDaE8CReKHnHxLiz-o2tDxuUgwy91c4k0qhQbVw,7749
5
- AIEmailAutomationUtility/Email_Read.py,sha256=UJDHdsr5RN_GG5OsOvUKbKziaw0a-kR3TT0iUv0oRmI,27795
5
+ AIEmailAutomationUtility/Email_Read.py,sha256=pRqc9295r_qqdfWIFJFG2XH9J-VlvO1E0yP3iv_cRV4,27802
6
6
  AIEmailAutomationUtility/Email_Upload_Document.py,sha256=3bdkxfDlwoeRp-46KPw2Gs1dqBhEIoA1yE5GCudpdV8,1320
7
- AIEmailAutomationUtility/Process_Category.py,sha256=EojfyGAN7U6NIBqinikJIauEgzz-ZQhHpzcjNr1No9M,41234
7
+ AIEmailAutomationUtility/Process_Category.py,sha256=f17YF8rfSTFScxBfAhuJJ8ev6TbxYDcPQljIpZWa5PY,44100
8
8
  AIEmailAutomationUtility/Save_Draft.py,sha256=yzLgFN14I_lXE6qL0I3tKNduvcnWdbsY9i2mKdTtio4,5348
9
9
  AIEmailAutomationUtility/Save_Transaction.py,sha256=Gg1w6hhzHmEFjsuzYvkq-3-EsWReetjLHsYSv5YIGgM,3816
10
10
  AIEmailAutomationUtility/__init__.py,sha256=Jad3IdPRsVMeLqEEh-FbCrc1lE2tzJO2DTG5Hgmxh5g,391
11
- AIEmailAutomationUtility-0.0.26.dist-info/LICENCE.txt,sha256=2qX9IkEUBx0VJp1Vh9O2dsRwE-IpYId0lXDyn7OVsJ8,1073
12
- AIEmailAutomationUtility-0.0.26.dist-info/METADATA,sha256=8n0W1uGzS7F2kkzHYPYi32axicmcCOapZ-LK8ql7fKs,623
13
- AIEmailAutomationUtility-0.0.26.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
14
- AIEmailAutomationUtility-0.0.26.dist-info/top_level.txt,sha256=3jTWrTUblVkaP7mpwY2UBSnrlfot5Ykpfsehyke-Uzw,25
15
- AIEmailAutomationUtility-0.0.26.dist-info/RECORD,,
11
+ AIEmailAutomationUtility-0.0.28.dist-info/LICENCE.txt,sha256=2qX9IkEUBx0VJp1Vh9O2dsRwE-IpYId0lXDyn7OVsJ8,1073
12
+ AIEmailAutomationUtility-0.0.28.dist-info/METADATA,sha256=u5RJjpiERsP60tsBgtLops76gMlO2yuRq9naJ-_5Qmo,649
13
+ AIEmailAutomationUtility-0.0.28.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
14
+ AIEmailAutomationUtility-0.0.28.dist-info/top_level.txt,sha256=3jTWrTUblVkaP7mpwY2UBSnrlfot5Ykpfsehyke-Uzw,25
15
+ AIEmailAutomationUtility-0.0.28.dist-info/RECORD,,