Ninad077 commited on
Commit
6f4113b
Β·
verified Β·
1 Parent(s): ea7b72f

Upload 6 files

Browse files
Files changed (4) hide show
  1. app.py +7 -2
  2. queries.py +344 -0
  3. recon.py +285 -0
  4. requirements.txt +2 -0
app.py CHANGED
@@ -57,10 +57,11 @@ st.markdown(html_title, unsafe_allow_html=True)
57
 
58
  menu_options = [
59
  {"label": "Internal users", "icon": "πŸ“„", "description": "Upload a document and schedule it for email"},
60
- {"label": "External users", "icon": "πŸ“Š", "description": "Schedule an email with BigQuery data"}
 
61
  ]
62
 
63
- # Create the custom option menu
64
  selected_option = option_menu(
65
  menu_title="Select Integration", # Title of the menu
66
  options=[option["label"] for option in menu_options], # Displayed options
@@ -379,3 +380,7 @@ if selected_option == "External users":
379
  elif selected_option == "Internal users":
380
  with open('ap.py') as file:
381
  exec(file.read())
 
 
 
 
 
57
 
58
  menu_options = [
59
  {"label": "Internal users", "icon": "πŸ“„", "description": "Upload a document and schedule it for email"},
60
+ {"label": "External users", "icon": "πŸ“Š", "description": "Schedule an email with BigQuery data"},
61
+ {"label": "Recon checking", "icon": "πŸ“Š", "description": "Schedule an email with BigQuery data"}
62
  ]
63
 
64
+ # Create the custom option menu
65
  selected_option = option_menu(
66
  menu_title="Select Integration", # Title of the menu
67
  options=[option["label"] for option in menu_options], # Displayed options
 
380
  elif selected_option == "Internal users":
381
  with open('ap.py') as file:
382
  exec(file.read())
383
+
384
+ elif selected_option == "Recon checking":
385
+ with open('recon.py') as file:
386
+ exec(file.read())
queries.py ADDED
@@ -0,0 +1,344 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ queries = {
3
+ # Query 1
4
+ '1. fynd-db.finance_recon_tool_asia.01_finance_avis_data_final': '''
5
+ select
6
+ bag_id,
7
+ concat(bag_id,Recon_Status,Settlement_type,Transaction_Type) as Merged,
8
+ count(concat(bag_id,Recon_Status,Settlement_type,Transaction_Type))
9
+ from `fynd-db.finance_recon_tool_asia.01_finance_avis_data_final`
10
+ group by
11
+ 1,2
12
+ having count(concat(bag_id,Recon_Status,Settlement_type,Transaction_Type)) not in (1)
13
+ ''',
14
+
15
+ # Query 2
16
+ '2. Seller fees date validation': '''
17
+ select
18
+ *
19
+ from `fynd-db.finance_recon_tool_asia.11_seller_fees_daily`
20
+ where
21
+ invoice_generation_date is null
22
+ ''',
23
+
24
+ # Query 3
25
+ '3. Transaction components validation': '''
26
+ select
27
+ bag_id,
28
+ transaction_type,
29
+ inserted_date,
30
+ round(transaction_fee+packaging_fee+logistics_charges+refund_support_fees+sla_charges-net_charges,0) as diff
31
+ from `fynd-db.finance_recon_tool_asia.11_seller_fees_daily`
32
+ where
33
+ round(transaction_fee+packaging_fee+logistics_charges+refund_support_fees+sla_charges-net_charges,0) not in (0,-1,-1)
34
+ and inserted_date > '2023-09-30'
35
+ group by 1,2,3, transaction_fee,packaging_fee,refund_support_fees,sla_charges,net_charges,logistics_charges
36
+ ''',
37
+
38
+ # Query 4
39
+ '4. Transactions in net collection validation': '''
40
+ select
41
+ concat(bag_id,Settlement_type) as Merged,
42
+ count(concat(bag_id,Settlement_type))
43
+ from `fynd-db.finance_recon_tool_asia.09_seller_net_collection_daily`
44
+ group by 1
45
+ having
46
+ count(concat(bag_id,Settlement_type)) not in (1)
47
+ ''',
48
+
49
+ # Query 5
50
+ '5. Transactions in seller fees validation': '''
51
+ select
52
+ bag_id,
53
+ concat(bag_id,transaction_type) as Merged,
54
+ count(concat(bag_id,transaction_type))
55
+ from `fynd-db.finance_recon_tool_asia.11_seller_fees_daily`
56
+ group by 1,2
57
+ having
58
+ count(concat(bag_id,transaction_type)) not in (1)
59
+ ''',
60
+
61
+
62
+ # Query 6
63
+ '6. Transactions in seller claims validation': '''
64
+ select
65
+ current_shipment_id,
66
+ concat(current_shipment_id,transaction_type) as Merged,
67
+ count(concat(current_shipment_id,transaction_type))
68
+ from `fynd-db.finance_recon_tool_asia.12_seller_claims_daily`
69
+ group by 1,2
70
+ having
71
+ count(concat(current_shipment_id,transaction_type)) not in (1)
72
+ ''',
73
+
74
+
75
+ # Query 7
76
+ '7. Aggregate liability validation': '''
77
+ select
78
+ *
79
+ from `fynd-db.finance_recon_tool_asia.12_seller_claims_daily`
80
+ where
81
+ aggregate_liability is null
82
+ ''',
83
+
84
+
85
+ # Query 8
86
+ '8. Lost claim validation': '''
87
+ select
88
+ *
89
+ from `fynd-db.finance_recon_tool_asia.01_finance_avis_data_final` as A
90
+ left join
91
+ `fynd-db.finance_recon_tool_asia.12_seller_claims_daily` as B
92
+ on
93
+ A.current_shipment_id = B.current_shipment_id
94
+ where
95
+ A.claim_settle_date is not null
96
+ and A.transaction_type = 'Claim'
97
+ and A.dp_partner = 'fynd'
98
+ and B.current_shipment_id is null
99
+ ''',
100
+
101
+
102
+
103
+ # Query 9
104
+ '9. Gstin validation': '''
105
+ select
106
+ company_id,
107
+ company_name,
108
+ ordering_channel
109
+ from `fynd-db.finance_recon_tool_asia.11_seller_fees_daily`
110
+ where
111
+ company_gstn is null
112
+ group by
113
+ 1,2,3
114
+ ''',
115
+
116
+
117
+
118
+ # Query 10
119
+ '10. Positive transaction components validation': '''
120
+ select
121
+ *
122
+ from `fynd-db.finance_recon_tool_asia.11_seller_fees_daily`
123
+ where
124
+ transaction_type in ('Sale','SLA','Claim')
125
+ and net_charges > 0
126
+ ''',
127
+
128
+
129
+ # Query 11
130
+ '11. Negative transaction components validation': '''
131
+ select
132
+ *
133
+ from `fynd-db.finance_recon_tool_asia.11_seller_fees_daily`
134
+ where
135
+ transaction_type = 'Return'
136
+ and net_charges < 0
137
+ ''',
138
+
139
+
140
+ # Query 12
141
+ '12. GST Tag validation': '''
142
+ select
143
+ company_id,
144
+ company_name,
145
+ ordering_channel,
146
+ company_gstn,
147
+ gst_tag,
148
+ case WHEN LENGTH(company_gstn) = 10 then "SGST"
149
+ when SUBSTRING(company_gstn,1,2) = '27' then "SGST" else "IGST" end as Tag,
150
+ case when gst_tag = (case WHEN LENGTH(company_gstn) = 10 then "SGST"
151
+ when SUBSTRING(company_gstn,1,2) = '27' then "SGST" else "IGST" end) then "Match" else "Not_Match" end as CC
152
+ from `fynd-db.finance_recon_tool_asia.11_seller_fees_daily`
153
+ where
154
+ (case when gst_tag = (case WHEN LENGTH(company_gstn) = 10 then "SGST"
155
+ when SUBSTRING(company_gstn,1,2) = '27' then "SGST" else "IGST" end) then "Match" else "Not_Match" end) = "Not_Match"
156
+ group by 1,2,3,4,5,6
157
+ ''',
158
+
159
+ # Query 13
160
+ '13. 09_Net collection all data validation': '''
161
+ select
162
+ A.company_id,
163
+ A.company_name,
164
+ A.ordering_channel,
165
+ A.bag_id,
166
+ A.Settlement_type,
167
+ A.recon_status,
168
+ A.recon_date,
169
+ A.inserted_date,
170
+ B.bag_id,
171
+ B.Settlement_type
172
+ from `fynd-db.finance_recon_tool_asia.01_finance_avis_data_final` as A
173
+ left join
174
+ `fynd-db.finance_recon_tool_asia.09_seller_net_collection_daily` as B
175
+ on
176
+ A.bag_id = B.bag_id
177
+ and A.Settlement_type = B.Settlement_type
178
+ where
179
+ A.Settlement_type not in ('NA','SLA')
180
+ and A.recon_status in ('delivery_done','return_bag_delivered','return_bag_picked')
181
+ and B.bag_id is null
182
+ and (case when A.Settlement_type = 'collection' and A.collection_partner = 'fynd' then 'yes'
183
+ when A.Settlement_type = 'refund' and A.refund_partner = 'fynd' then 'yes' else 'no' end) = 'yes'
184
+ group by
185
+ 1,2,3,4,5,6,7,8,9,10
186
+ ''',
187
+
188
+
189
+ # Query 14
190
+ '14. Net collection collection & refund validation': '''
191
+ select
192
+ bag_id,
193
+ settlement_type,
194
+ collection_partner,
195
+ refund_partner,
196
+ case when settlement_type in ('collection','Claim',"dispute","rectify","rectify_R") and collection_partner = 'fynd' then 'Yes' when settlement_type = 'refund' and refund_partner = 'fynd' then 'Yes' else 'No' end as Comment
197
+ from `fynd-db.finance_recon_tool_asia.09_seller_net_collection_daily`
198
+ where
199
+ (case when settlement_type in ('collection','Claim',"dispute","rectify","rectify_R") and collection_partner = 'fynd' then 'Yes' when settlement_type = 'refund' and refund_partner = 'fynd' then 'Yes' else 'No' end) = 'No'
200
+ ''',
201
+
202
+
203
+ # Query 15
204
+ '15. 09_Net collection collection & refund validation': '''
205
+ select
206
+ A.bag_id,
207
+ B.bag_id,
208
+ A.settlement_type,
209
+ B.settlement_type,
210
+ A.transaction_type,
211
+ A.collection_partner,
212
+ A.refund_partner,
213
+ case when A.settlement_type = 'collection' and A.collection_partner = 'fynd' then 'Yes' when A.settlement_type = 'refund' and A.refund_partner = 'fynd' then 'Yes' else 'No' end as Comment
214
+ from `fynd-db.finance_recon_tool_asia.01_finance_avis_data_final` as A
215
+ left join
216
+ `fynd-db.finance_recon_tool_asia.09_seller_net_collection_daily` as B
217
+ on
218
+ A.bag_id = B.bag_id
219
+ and A.settlement_type = B.settlement_type
220
+ where
221
+ A.settlement_type <> 'NA'
222
+ and A.recon_status not in ("bag_lost","return_bag_lost")
223
+ and (case when A.settlement_type = 'collection' and A.collection_partner = 'fynd' then 'yes' when A.settlement_type = 'refund' and A.refund_partner = 'fynd' then 'yes' else 'No' end) = 'yes'
224
+ and (case when A.transaction_type = 'Sale' and A.collection_partner = 'fynd' then 'Yes' when A.transaction_type = 'Return' and A.refund_partner = 'fynd' then 'Yes' when A.transaction_type = 'Claim' and A.collection_partner = 'fynd' then 'Yes' else 'No' end) = 'Yes'
225
+ and B.bag_id is null
226
+ ''',
227
+
228
+
229
+ # Query 16
230
+ '16. NA settlement validation': '''
231
+ select
232
+ *
233
+ from `fynd-db.finance_recon_tool_asia.09_seller_net_collection_daily`
234
+ where
235
+ -- settlement_type = 'NA'
236
+ (case when settlement_type in ('collection','Claim','rectify','rectify_R') and collection_partner = 'fynd' then 'Yes' when settlement_type = 'refund' and refund_partner = 'fynd' then 'Yes' else 'No'end ) = 'No'
237
+ ''',
238
+
239
+
240
+ # Query 17
241
+ '17. Fynd collection placed bags validation': '''
242
+ select
243
+ A.bag_id,
244
+ B.bag_id,
245
+ A.order_type,
246
+ A.transaction_type,
247
+ case when B.settlement_type = 'collection' then 'Sale' else 'Return' end as transaction_type,
248
+ from `fynd-db.finance_recon_tool_asia.11_seller_fees_daily` as A
249
+ left join
250
+ `fynd-db.finance_recon_tool_asia.09_seller_net_collection_daily` as B
251
+ on
252
+ A.bag_id = B.bag_id
253
+ and A.transaction_type = (case when B.settlement_type = 'collection' then 'Sale' when B.settlement_type = 'refund' then 'Return' else 'NA' end )
254
+ where
255
+ transaction_type <> 'SLA'
256
+ and (case when A.transaction_type = 'Sale' and A.collection_partner = 'fynd' then 'yes' when A.transaction_type = 'Return' and A.refund_partner = 'fynd' then 'yes' else 'no'end) = 'yes'
257
+ and B.bag_id is null
258
+ ''',
259
+
260
+
261
+ # # Query 18
262
+ # '18. Disbursement table validation': '''
263
+ # select
264
+ # A.sett_id,
265
+ # B.sett_id,
266
+ # NP,
267
+ # net_amount,
268
+ # case when A.sett_id = B.sett_id and round(NP - net_amount,0) in (0,1) then 'Match' else "Not_Match" end as Diff
269
+ # from
270
+ # (SELECT
271
+ # sett_id,
272
+ # SUM(seller_net_collection) AS NP
273
+ # FROM
274
+ # `fynd-db.finance_recon_tool_asia.09_seller_net_collection_daily`
275
+ # GROUP BY
276
+ # 1
277
+ # UNION ALL
278
+ # SELECT
279
+ # sett_id,
280
+ # SUM(total_charges) AS NP
281
+ # FROM
282
+ # `fynd-db.finance_recon_tool_asia.11_seller_fees_daily`
283
+ # GROUP BY
284
+ # 1
285
+ # UNION ALL
286
+ # SELECT
287
+ # sett_id,
288
+ # SUM(claimable_amt) AS NP
289
+ # FROM
290
+ # `fynd-db.finance_recon_tool_asia.12_seller_claims_daily`
291
+ # GROUP BY
292
+ # 1
293
+ # UNION ALL
294
+ # SELECT
295
+ # sett_id,
296
+ # SUM(dispute_amount) AS NP
297
+ # FROM
298
+ # `fynd-db.finance_recon_tool_asia.17_seller_manual_Dispute`
299
+ # GROUP BY
300
+ # 1) as A
301
+ # --left join
302
+ # right join
303
+ # (select
304
+ # sett_id,
305
+ # sum(net_amount) as net_amount
306
+ # from
307
+ # `fynd-db.finance_recon_tool_asia.disbursement_summary`
308
+ # group by
309
+ # 1) as B
310
+ # on
311
+ # A.sett_id = B.sett_id
312
+ # where
313
+ # (case when A.sett_id = B.sett_id and round(NP - net_amount,0) in (0,1) then 'Match' else "Not_Match" end) = 'Not_Match'
314
+ # ''',
315
+
316
+
317
+ # Query 19
318
+ '18. PPD validation': '''
319
+ select
320
+ *
321
+ from
322
+ (SELECT
323
+ *
324
+ FROM
325
+ `fynd-db.Outstanding.09_Payable_File`
326
+ where
327
+ expected_payout_date <= current_date()
328
+ and order_type = "PPD"
329
+ and lower(collection_partner) = "seller") as A
330
+ left join
331
+ (select
332
+ bag_id,
333
+ txn_id,
334
+ collected_amount
335
+ from
336
+ `fynd-db.finance_recon_tool_asia.05_partner_collection`) as B
337
+ on
338
+ A.bag_id = B.bag_id
339
+ where
340
+ B.bag_id is not null
341
+ ''',
342
+
343
+ # Add more queries as needed
344
+ }
recon.py ADDED
@@ -0,0 +1,285 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from google.cloud import bigquery
2
+ import functions_framework
3
+ from queries import queries
4
+ from google.oauth2 import service_account
5
+ import json
6
+ import requests
7
+ import streamlit as st
8
+ import pyperclip
9
+ from ap import send_message_via_webhook, Webhook_urls
10
+
11
+ # Dropdown for channels/members
12
+ webhook_url = list(Webhook_urls.keys())
13
+ html_subject = """
14
+ <html>
15
+ <head>
16
+ <style>
17
+ .button {
18
+ display: inline-block;
19
+ padding: 10px 20px;
20
+ border-radius: 12px;
21
+ background: linear-gradient(to bottom, #f8f9fa, #e0e0e0);
22
+ box-shadow:
23
+ 0 6px 12px rgba(0, 0, 0, 0.3),
24
+ 0 8px 16px rgba(0, 0, 0, 0.2),
25
+ inset 0 -2px 4px rgba(255, 255, 255, 0.6);
26
+ text-align: center;
27
+ position: relative;
28
+ transform: translateY(4px);
29
+ transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
30
+ cursor: pointer;
31
+ user-select: none;
32
+ }
33
+ .button:hover {
34
+ box-shadow:
35
+ 0 8px 16px rgba(0, 0, 0, 0.3),
36
+ 0 12px 24px rgba(0, 0, 0, 0.2);
37
+ transform: translateY(2px);
38
+ }
39
+ .button:active {
40
+ box-shadow:
41
+ 0 4px 8px rgba(0, 0, 0, 0.3),
42
+ 0 6px 12px rgba(0, 0, 0, 0.2);
43
+ transform: translateY(0);
44
+ }
45
+ </style>
46
+ </head>
47
+ <body>
48
+ <div class="button">
49
+ <h3 style="
50
+ font-size: 20px;
51
+ color: #ffffff;
52
+ background-image: linear-gradient(to right, #800000, #ff0000, #ffdab9);
53
+ background-clip: text;
54
+ -webkit-background-clip: text;
55
+ text-fill-color: transparent;
56
+ -webkit-text-fill-color: transparent;
57
+ margin: 0;
58
+ text-shadow: 0 2px 5px rgba(0, 0, 0, 0.4);
59
+ ">Select channels/members</h3>
60
+ </div>
61
+ </body>
62
+ </html>
63
+ """
64
+
65
+
66
+ st.markdown(html_subject, unsafe_allow_html=True)
67
+ selection = st.multiselect("", webhook_url)
68
+ # SLACK_WEBHOOK_URL = "https://hooks.slack.com/services/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"
69
+
70
+
71
+
72
+ def check_duplicates(credentials_file):
73
+ """Check for duplicates using BigQuery with the provided credentials file."""
74
+ results = {}
75
+ credentials = service_account.Credentials.from_service_account_info(json.loads(credentials_file))
76
+ client = bigquery.Client(credentials=credentials, project=credentials.project_id)
77
+
78
+ for i, (query_name, query) in enumerate(queries.items()):
79
+
80
+ query_job = client.query(query)
81
+ df = query_job.result().to_dataframe()
82
+ # For debugging, write the DataFrame to the Streamlit app
83
+ st.write(f"{query_name}:", df)
84
+
85
+ button_styles = """
86
+ <style>
87
+ div.stButton > button {
88
+ color: #ffffff; /* Text color */
89
+ font-size: 30px;
90
+ background-image: linear-gradient(to right, #800000, #ff0000); /* Maroon to light red gradient */
91
+ border: none;
92
+ padding: 10px 20px;
93
+ cursor: pointer;
94
+ border-radius: 15px;
95
+ display: inline-block;
96
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1), 0 8px 15px rgba(0, 0, 0, 0.1); /* Box shadow */
97
+ transition: all 0.3s ease; /* Smooth transition on hover */
98
+ }
99
+ div.stButton > button:hover {
100
+ background-color: #00ff00; /* Hover background color */
101
+ color: #ff0000; /* Hover text color */
102
+ box-shadow: 0 6px 10px rgba(0, 0, 0, 0.2), 0 12px 20px rgba(0, 0, 0, 0.2); /* Box shadow on hover */
103
+ }
104
+ </style>
105
+ """
106
+ st.markdown(button_styles, unsafe_allow_html=True)
107
+ if st.button(f"Copy Query", key=f"copy_query_{i}"):
108
+ pyperclip.copy(query)
109
+ st.success('Query copied to clipboard!')
110
+
111
+ if not df.empty:
112
+ duplicate_count = len(df)
113
+ results[query_name] = duplicate_count
114
+
115
+ return results
116
+
117
+ # Streamlit UI
118
+ html_subject = """
119
+ <html>
120
+ <head>
121
+ <style>
122
+ .button {
123
+ display: inline-block;
124
+ padding: 10px 20px;
125
+ border-radius: 12px;
126
+ background: linear-gradient(to bottom, #f8f9fa, #e0e0e0);
127
+ box-shadow:
128
+ 0 6px 12px rgba(0, 0, 0, 0.3),
129
+ 0 8px 16px rgba(0, 0, 0, 0.2),
130
+ inset 0 -2px 4px rgba(255, 255, 255, 0.6);
131
+ text-align: center;
132
+ position: relative;
133
+ transform: translateY(4px);
134
+ transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
135
+ cursor: pointer;
136
+ user-select: none;
137
+ }
138
+ .button:hover {
139
+ box-shadow:
140
+ 0 8px 16px rgba(0, 0, 0, 0.3),
141
+ 0 12px 24px rgba(0, 0, 0, 0.2);
142
+ transform: translateY(2px);
143
+ }
144
+ .button:active {
145
+ box-shadow:
146
+ 0 4px 8px rgba(0, 0, 0, 0.3),
147
+ 0 6px 12px rgba(0, 0, 0, 0.2);
148
+ transform: translateY(0);
149
+ }
150
+ </style>
151
+ </head>
152
+ <body>
153
+ <div class="button">
154
+ <h3 style="
155
+ font-size: 20px;
156
+ color: #ffffff;
157
+ background-image: linear-gradient(to right, #800000, #ff0000, #ffdab9);
158
+ background-clip: text;
159
+ -webkit-background-clip: text;
160
+ text-fill-color: transparent;
161
+ -webkit-text-fill-color: transparent;
162
+ margin: 0;
163
+ text-shadow: 0 2px 5px rgba(0, 0, 0, 0.4);
164
+ ">Upload service a/c credentials</h3>
165
+ </div>
166
+ </body>
167
+ </html>
168
+ """
169
+
170
+ st.markdown(html_subject, unsafe_allow_html=True)
171
+
172
+ # Upload credentials file
173
+ credentials_file = st.file_uploader("", type="json")
174
+
175
+ if credentials_file is not None:
176
+ # Read the credentials file
177
+ credentials_data = credentials_file.read().decode("utf-8")
178
+
179
+ # Check for duplicates
180
+ results = check_duplicates(credentials_data)
181
+ st.write("")
182
+ st.write("")
183
+
184
+ if results:
185
+ # Define the HTML message with gradient text and extra spacing
186
+ html_subject = """
187
+ <html>
188
+ <head>
189
+ <style>
190
+ .button {
191
+ display: inline-block;
192
+ padding: 10px 20px;
193
+ border-radius: 12px;
194
+ background: linear-gradient(to bottom, #f8f9fa, #e0e0e0);
195
+ box-shadow:
196
+ 0 6px 12px rgba(0, 0, 0, 0.3),
197
+ 0 8px 16px rgba(0, 0, 0, 0.2),
198
+ inset 0 -2px 4px rgba(255, 255, 255, 0.6);
199
+ text-align: center;
200
+ position: relative;
201
+ transform: translateY(4px);
202
+ transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
203
+ cursor: pointer;
204
+ user-select: none;
205
+ }
206
+ .button:hover {
207
+ box-shadow:
208
+ 0 8px 16px rgba(0, 0, 0, 0.3),
209
+ 0 12px 24px rgba(0, 0, 0, 0.2);
210
+ transform: translateY(2px);
211
+ }
212
+ .button:active {
213
+ box-shadow:
214
+ 0 4px 8px rgba(0, 0, 0, 0.3),
215
+ 0 6px 12px rgba(0, 0, 0, 0.2);
216
+ transform: translateY(0);
217
+ }
218
+ .spacing {
219
+ margin: 20px 0; /* Adjust the value as needed */
220
+ }
221
+ .result-box {
222
+ border: 1px solid #ddd;
223
+ border-radius: 8px;
224
+ background: #f9f9f9;
225
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
226
+ padding: 10px;
227
+ margin-bottom: 10px;
228
+ font-size: 16px;
229
+ }
230
+ .result-title {
231
+ font-weight: bold;
232
+ color: #333;
233
+ }
234
+ </style>
235
+ </head>
236
+ <body>
237
+ <div class="button">
238
+ <h3 style="
239
+ font-size: 20px;
240
+ color: #ffffff;
241
+ background-image: linear-gradient(to right, #800000, #ff0000, #ffdab9);
242
+ background-clip: text;
243
+ -webkit-background-clip: text;
244
+ text-fill-color: transparent;
245
+ -webkit-text-fill-color: transparent;
246
+ margin: 0;
247
+ text-shadow: 0 2px 5px rgba(0, 0, 0, 0.4);
248
+ ">Duplicate Counts for Queries:</h3>
249
+ </div>
250
+ <div class="spacing"></div> <!-- Adds spacing between the heading and the content -->
251
+ </body>
252
+ </html>
253
+ """
254
+
255
+ # Display HTML message with spacing
256
+ st.markdown(html_subject, unsafe_allow_html=True)
257
+
258
+ # Prepare the plain text message with styled boxes
259
+ message_html = ""
260
+ for query_name, count in results.items():
261
+ message_html += f"""
262
+ <div class="result-box">
263
+ <div class="result-title">{query_name}</div>
264
+ <div>{count} duplicate rows</div>
265
+ </div>
266
+ """
267
+
268
+ # Display the styled message in Streamlit
269
+ st.markdown(message_html, unsafe_allow_html=True)
270
+
271
+ # Prepare plain text for Slack messages
272
+ message_text = ""
273
+ for query_name, count in results.items():
274
+ message_text += f"*{query_name}*\n{count} duplicate rows\n\n"
275
+
276
+ if not results:
277
+ message_text = "No duplicates found in the queries."
278
+
279
+ # Send the message to selected channels
280
+ for channel in selection:
281
+ webhook_url = Webhook_urls.get(channel)
282
+ if webhook_url:
283
+ send_message_via_webhook(message_text, webhook_url)
284
+ else:
285
+ st.error(f"Webhook URL not found for channel: {channel}")
requirements.txt CHANGED
@@ -124,6 +124,7 @@ pyngrok==7.2.0
124
  pyOpenSSL==24.2.1
125
  pyparsing==3.1.2
126
  PyPDF2==3.0.1
 
127
  PySocks==1.7.1
128
  pytesseract==0.3.10
129
  python-dateutil==2.9.0.post0
@@ -184,6 +185,7 @@ websocket-client==1.8.0
184
  Werkzeug==3.0.3
185
  wrapt==1.16.0
186
  wsproto==1.2.0
 
187
  XlsxWriter==3.2.0
188
  xxhash==3.4.1
189
  yarl==1.9.4
 
124
  pyOpenSSL==24.2.1
125
  pyparsing==3.1.2
126
  PyPDF2==3.0.1
127
+ pyperclip==1.9.0
128
  PySocks==1.7.1
129
  pytesseract==0.3.10
130
  python-dateutil==2.9.0.post0
 
185
  Werkzeug==3.0.3
186
  wrapt==1.16.0
187
  wsproto==1.2.0
188
+ xlrd==2.0.1
189
  XlsxWriter==3.2.0
190
  xxhash==3.4.1
191
  yarl==1.9.4