modelswrkpi 8.1.3__py3-none-any.whl → 9.0.1__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.

Potentially problematic release.


This version of modelswrkpi might be problematic. Click here for more details.

@@ -4,3 +4,4 @@ from models.bro_clicks.load_balancer.v3 import LoadBalancerV3
4
4
  from models.bro_clicks.load_balancer.v4 import LoadBalancerV4
5
5
  from models.bro_clicks.load_balancer.v5 import LoadBalancerV5
6
6
  from models.bro_clicks.load_balancer.v6 import LoadBalancerV6
7
+ from models.bro_clicks.load_balancer.v7 import LoadBalancerV7
@@ -8,6 +8,7 @@ ext_modules = [
8
8
  Extension("v4", ["v4.py"], extra_compile_args=["-g0"]),
9
9
  Extension("v5", ["v5.py"], extra_compile_args=["-g0"]),
10
10
  Extension("v6", ["v6.py"], extra_compile_args=["-g0"]),
11
+ Extension("v7", ["v7.py"], extra_compile_args=["-g0"]),
11
12
  ]
12
13
  setup(
13
14
  name='load_balancer',
@@ -12,6 +12,7 @@ class LoadBalancer(Db):
12
12
  self.set_constraint('load_balancer_2_pk', ['date', 'crm_id', 'gateway_id', 'router_id'])
13
13
  self.db_p = db_p
14
14
  self._account_id = account_id
15
+ self.is_cc_type_cap_split = False
15
16
 
16
17
  @staticmethod
17
18
  def set_max_decline_attempts(attempts):
@@ -44,7 +45,9 @@ class LoadBalancer(Db):
44
45
 
45
46
  def get_processing_for_month(self, crm_id):
46
47
  qry = f"""
47
- select b.gateway_id, count(a.order_id)::int initial_count_mtd from augmented_data.order_cycles a
48
+ select b.gateway_id,
49
+ count(a.order_id)::int initial_count_mtd
50
+ from augmented_data.order_cycles a
48
51
  inner join crm_global.orders b on a.order_id = b.order_id and a.crm_id = b.crm_id and a.crm_id = '{crm_id}'
49
52
  where a.time_stamp > '{self.get_first_om()}' and a.time_stamp < '{self.today()}'::timestamp
50
53
  and a.bc_inferred = 0
@@ -56,16 +59,52 @@ class LoadBalancer(Db):
56
59
  # print(qry)
57
60
  return pd.read_sql(qry, self.db_p.engine).fillna(0)
58
61
 
62
+ def get_processing_for_month_cc_type(self, crm_id):
63
+ qry = f"""
64
+ select
65
+ gateway_id,
66
+ (initial_count_mtd - visa_count_mtd)::int as initial_count_mtd,
67
+ visa_count_mtd
68
+ from
69
+ (select b.gateway_id,
70
+ count(a.order_id)::int initial_count_mtd,
71
+ (count(a.order_id) filter(where lower(cc_type) = 'visa'))::int visa_count_mtd
72
+ from augmented_data.order_cycles a
73
+ inner join crm_global.orders b on a.order_id = b.order_id and a.crm_id = b.crm_id and a.crm_id = '{crm_id}'
74
+ where a.time_stamp > '{self.get_first_om()}' and a.time_stamp < '{self.today()}'::timestamp
75
+ and a.bc_inferred = 0
76
+ and a.decline_reason is null
77
+ and b.is_test_cc::int <> '1'
78
+ group by b.gateway_id) a
79
+ """
80
+
81
+ # print(qry)
82
+ return pd.read_sql(qry, self.db_p.engine).fillna(0)
83
+
59
84
  def init_date(self, date, crm_id, reset_cap_count=True):
60
85
  sk = f'ui_{self._account_id}_clients'
61
86
  real_cap_space = self.get_processing_for_month(crm_id) if reset_cap_count else None
62
87
 
63
88
  qry = f"""
64
89
  SELECT '{date}'::date as date, b.crm_id, a.mid_id, b.gateway_id, b.step, a.processor,
65
- coalesce(e.approved, 0) approved, coalesce(e.approved,0) initial_count, c.dly_initial_cap, b.minimum_price, coalesce(e.declined, 0) declined,
66
- d.approval_rate, c.dly_min_approval_rate, array_to_string(c.pr_exclude_cc_types, ',') exclude_cc_types ,
67
- c.date_added, c.enable_tds, array_to_string(c.tds_exclude_cc_types, ',') tds_exclude_cc_types, c.enabled, c.enable_initials, c.monthly_initial_cap, c.priority, c.router_id, d.router_id as cur_router_id,
68
- d.soft_cap_alerted, d.initial_count_mtd as prev_mtd
90
+ coalesce(e.approved, 0) approved,
91
+ coalesce(e.approved,0) initial_count,
92
+ c.dly_initial_cap, b.minimum_price,
93
+ coalesce(e.declined, 0) declined,
94
+ d.approval_rate,
95
+ c.dly_min_approval_rate,
96
+ array_to_string(c.pr_exclude_cc_types, ',') exclude_cc_types ,
97
+ c.date_added,
98
+ c.enable_tds,
99
+ array_to_string(c.tds_exclude_cc_types, ',') tds_exclude_cc_types,
100
+ c.enabled,
101
+ c.enable_initials,
102
+ c.monthly_initial_cap,
103
+ c.priority,
104
+ c.router_id,
105
+ d.router_id as cur_router_id,
106
+ d.soft_cap_alerted,
107
+ d.initial_count_mtd as prev_mtd
69
108
 
70
109
  FROM {sk}.mids a
71
110
  LEFT JOIN {sk}.steps b on b.mid_id = a.mid_id
@@ -135,18 +174,25 @@ class LoadBalancer(Db):
135
174
  # self.engine.execute(f'truncate {self.schema}.{self.table}')
136
175
  self.upsert(up.dropna())
137
176
 
138
- def _increment_conversion(self, date, gateway_id, crm_id, approved, recurs_attempt=0, **kwargs):
139
- inc_p = '(initial_count +1)'
140
- m_inc_p = '(initial_count_mtd +1)'
141
- dnc_p = '(declined + 1)'
142
- inc = 'initial_count'
143
- m_inc = 'initial_count_mtd'
177
+ def _increment_conversion(self, date, gateway_id, crm_id, approved, recurs_attempt=0, cc_type=None, **kwargs):
178
+ if cc_type.lower() == 'visa':
179
+ inc_p = '(visa_count +1)'
180
+ m_inc_p = '(visa_count_mtd +1)'
181
+ inc = 'visa_count'
182
+ m_inc = 'visa_count_mtd'
183
+
184
+ else:
185
+ inc_p = '(initial_count +1)'
186
+ m_inc_p = '(initial_count_mtd +1)'
187
+ inc = 'initial_count'
188
+ m_inc = 'initial_count_mtd'
144
189
  dnc = 'declined'
190
+ dnc_p = '(declined + 1)'
145
191
  try:
146
192
  qry = f"""
147
193
  UPDATE {self.schema}.{self.table}
148
- set {f"{inc} ={inc_p}, approval_rate = ({inc_p}::numeric / ({dnc}+{inc_p}::numeric))*100, {m_inc} = {m_inc_p}" if approved
149
- else f"{dnc} ={dnc_p}, approval_rate = case when {inc}>0 then ({inc} / ({dnc_p}+{inc}))*100 else 0 end "
194
+ set {f"{inc} ={inc_p}, approval_rate = ((initial_count+visa_count+1)::numeric / ({dnc}+(initial_count+visa_count+1)::numeric))*100, {m_inc} = {m_inc_p}" if approved
195
+ else f"{dnc} ={dnc_p}, approval_rate = case when visa_count+initial_count>0 then ((visa_count+initial_count)::numeric / ({dnc_p}+visa_count+initial_count)::numeric * 100) else 0 end "
150
196
  }
151
197
  where crm_id = '{crm_id}' and date = '{date}'::date and gateway_id='{gateway_id}'
152
198
  returning gateway_id
@@ -165,9 +211,11 @@ class LoadBalancer(Db):
165
211
  def increment_conversion(self, date, gateway_id, crm_id, approved, **kwargs):
166
212
  return self._increment_conversion(date, gateway_id, crm_id, approved, recurs_attempt=0, **kwargs)
167
213
 
168
- def set_soft_cap_alerted(self, crm_id):
214
+ def set_soft_cap_alerted(self, crm_id, cc_type=None, **kw):
169
215
  self.engine.execute(
170
- f"""Update {self.schema}.{self.table} set soft_cap_alerted=true where crm_id= '{crm_id}'""")
216
+ f"""Update {self.schema}.{self.table}
217
+ {"set visa_soft_cap_alerted=true" if cc_type.lower()=='visa' else "set soft_cap_alerted=true"}
218
+ where crm_id= '{crm_id}'""")
171
219
 
172
220
  def disable(self, crm_id, gateway_id):
173
221
  self.engine.execute(
@@ -15,12 +15,28 @@ class LoadBalancerV5(LoadBalancerV4):
15
15
  real_cap_space = self.get_processing_for_month(crm_id) if reset_cap_count else None
16
16
 
17
17
  qry = f"""
18
- SELECT '{date}'::date as date, b.crm_id, a.mid_id, b.gateway_id, b.step, a.processor,
19
- coalesce(e.approved, 0) approved, coalesce(e.approved,0) initial_count, c.dly_initial_cap, b.minimum_price, coalesce(e.declined, 0) declined,
20
- d.approval_rate, c.dly_min_approval_rate, array_to_string(c.pr_exclude_cc_types, ',') exclude_cc_types ,
21
- c.date_added, c.enable_tds, array_to_string(c.tds_exclude_cc_types, ',') tds_exclude_cc_types, c.enabled, c.enable_initials, c.monthly_initial_cap, c.priority, c.router_id, d.router_id as cur_router_id,
22
- c.allow_prepaid, c.allow_non_prepaid,
23
- d.soft_cap_alerted, d.initial_count_mtd as prev_mtd
18
+ SELECT '{date}'::date as date, b.crm_id, a.mid_id, b.gateway_id, b.step, a.processor,
19
+ coalesce(e.approved, 0) approved,
20
+ coalesce(e.approved,0) initial_count,
21
+ c.dly_initial_cap,
22
+ b.minimum_price,
23
+ coalesce(e.declined, 0) declined,
24
+ d.approval_rate,
25
+ c.dly_min_approval_rate,
26
+ array_to_string(c.pr_exclude_cc_types, ',') exclude_cc_types ,
27
+ c.date_added,
28
+ c.enable_tds,
29
+ array_to_string(c.tds_exclude_cc_types, ',') tds_exclude_cc_types,
30
+ c.enabled,
31
+ c.enable_initials,
32
+ c.monthly_initial_cap,
33
+ c.priority,
34
+ c.router_id,
35
+ d.router_id as cur_router_id,
36
+ c.allow_prepaid,
37
+ c.allow_non_prepaid,
38
+ d.soft_cap_alerted,
39
+ d.initial_count_mtd as prev_mtd
24
40
 
25
41
  FROM {sk}.mids a
26
42
  LEFT JOIN {sk}.steps b on b.mid_id = a.mid_id
@@ -40,9 +40,6 @@ class LoadBalancerV6(LoadBalancerV5):
40
40
  with ThreadPoolExecutor(max_workers=1) as executor:
41
41
  self._t_get_bin = executor.submit(_exec) # Task that takes 5 seconds
42
42
 
43
-
44
-
45
-
46
43
  def next_gateway(self, crm_id, date, step, click_id='', processor=False, cc_type=None, cc_first_8=False, recurse=0,
47
44
  decs=False, ignore_user_exclusions=None,
48
45
  proc_excl=[], is_tds=None, is_prepaid=True, **kwargs):
@@ -1,8 +1,310 @@
1
- import random
2
- from models.db import Db, pd
3
- from models.bro_clicks.initial_routes import InitialRoutes, ForeignInitialRoutes
4
- from calendar import monthrange
5
- import datetime as dt
6
- from models import config
7
- from threading import Thread, Lock
8
- from copy import deepcopy
1
+ from models.bro_clicks.load_balancer.v6 import LoadBalancerV6
2
+ import pandas as pd
3
+ from numpy import nan as np_nan
4
+
5
+
6
+ class LoadBalancerV7(LoadBalancerV6):
7
+
8
+ def __init__(self, *args, **kw):
9
+ LoadBalancerV6.__init__(self, *args, **kw)
10
+ self.version = 7
11
+ self.is_cc_type_cap_split = True
12
+
13
+ def init_date(self, date, crm_id, reset_cap_count=True):
14
+ sk = f'ui_{self._account_id}_clients'
15
+ real_cap_space = self.get_processing_for_month_cc_type(crm_id) if reset_cap_count else None
16
+
17
+ qry = f"""
18
+ SELECT '{date}'::date as date, b.crm_id, a.mid_id, b.gateway_id, b.step, a.processor,
19
+ coalesce(e.approved, 0) approved,
20
+ coalesce(e.o_approved,0) initial_count,
21
+ coalesce(e.v_approved,0) visa_count,
22
+ c.dly_initial_cap,
23
+ c.visa_dly_cap,
24
+ b.minimum_price,
25
+ coalesce(e.declined, 0) declined,
26
+ d.approval_rate,
27
+ c.dly_min_approval_rate,
28
+ array_to_string(c.pr_exclude_cc_types, ',') exclude_cc_types ,
29
+ c.date_added,
30
+ c.enable_tds,
31
+ array_to_string(c.tds_exclude_cc_types, ',') tds_exclude_cc_types,
32
+ c.enabled,
33
+ c.enable_initials,
34
+ c.monthly_initial_cap,
35
+ c.visa_monthly_cap,
36
+ c.priority,
37
+ c.router_id,
38
+ d.router_id as cur_router_id,
39
+ d.soft_cap_alerted,
40
+ d.visa_soft_cap_alerted,
41
+ d.initial_count_mtd as prev_mtd,
42
+ d.visa_count_mtd as prev_visa_mtd
43
+
44
+ FROM {sk}.mids a
45
+ LEFT JOIN {sk}.steps b on b.mid_id = a.mid_id
46
+ LEFT JOIN {sk}.gateway_settings c on c.gateway_id = b.gateway_id and c.crm_id = b.crm_id
47
+ LEFT JOIN {self.schema}.{self.table} d on c.gateway_id =d.gateway_id and c.crm_id = d.crm_id and b.step = d.step and '{date}'::date =d.date
48
+ LEFT JOIN (select crm_id, gateway_id,
49
+ coalesce(sum(declined), 0) declined,
50
+ coalesce(sum(approved), 0) approved,
51
+ coalesce(sum(approved) filter (where lower(cc_type)='visa'), 0) v_approved,
52
+ coalesce(sum(approved) filter (where lower(cc_type)<>'visa'), 0) o_approved
53
+ from {self.schema}.conversions where coalesce(test, 0) <> 1 and time_stamp::date = '{date}'::date group by crm_id, gateway_id
54
+ ) e on e.gateway_id =c.gateway_id and e.crm_id=c.crm_id
55
+ where (b.close_date is null or b.close_date >'{self.today()}')
56
+ and b.crm_id = '{crm_id}'
57
+ and b.gateway_id is not null
58
+ and a.processor not ilike '%%virtual%%'
59
+ and b.gateway_id::int <> 1
60
+ and a.processor != 'FlexCharge'
61
+
62
+ """
63
+
64
+ try:
65
+ up = pd.read_sql(qry, self.engine)
66
+ up = up.sort_values('step').drop_duplicates(['gateway_id', 'cur_router_id'], keep='first')
67
+ up = up.loc[~up.router_id.isna()]
68
+ up = up.explode('router_id')
69
+
70
+ # delete changes to routers
71
+ del_gt_msk = (up.router_id != up.cur_router_id) & (
72
+ up.gateway_id.isin(up.loc[~up.cur_router_id.isna()].gateway_id.unique()))
73
+ del_gtys = up.loc[del_gt_msk].gateway_id.tolist()
74
+ up = up.loc[(~up.gateway_id.isin(del_gtys)) | (~up.cur_router_id.isna())]
75
+
76
+ # delete changes to routers
77
+ del_gt_msk = (up.router_id != up.cur_router_id)
78
+ del_gtys = up.loc[del_gt_msk].gateway_id.tolist()
79
+ self.engine.execute(
80
+ f"delete from {self.schema}.{self.table} where gateway_id::int = ANY(ARRAY{del_gtys}::int[]) and crm_id='{crm_id}'")
81
+ up = up.drop(columns='cur_router_id')
82
+ except Exception as e:
83
+ raise e
84
+ if reset_cap_count:
85
+ try:
86
+ up = up.merge(real_cap_space[['gateway_id', 'initial_count_mtd']], on=['gateway_id'], how='left')
87
+ up.initial_count_mtd = up.initial_count_mtd.fillna(0)
88
+ up.initial_count_mtd += up.initial_count
89
+
90
+ except:
91
+ up['initial_count_mtd'] = up.prev_mtd.fillna(0)
92
+ up.initial_count_mtd = up.initial_count_mtd.fillna(0)
93
+
94
+ try:
95
+ up = up.merge(real_cap_space[['gateway_id', 'visa_count_mtd']], on=['gateway_id'], how='left')
96
+ up.visa_count_mtd = up.visa_count_mtd.fillna(0)
97
+ up.visa_count_mtd += up.visa_count
98
+
99
+ except:
100
+ up['visa_count_mtd'] = up.prev_visa_mtd.fillna(0)
101
+ up.initial_count_mtd = up.initial_count_mtd.fillna(0)
102
+
103
+ drim = float(self.get_drim())
104
+ up.dly_initial_cap = pd.np.floor((up.monthly_initial_cap - up.initial_count_mtd) / drim)
105
+ up.visa_dly_cap = pd.np.floor((up.visa_monthly_cap - up.visa_count_mtd) / drim)
106
+ up.loc[up.dly_initial_cap < 0, 'dly_initial_cap'] = 0
107
+ up.loc[up.visa_dly_cap < 0, 'visa_dly_cap'] = 0
108
+
109
+ up.dly_initial_cap = up.dly_initial_cap.fillna(11)
110
+ up.visa_dly_cap = up.visa_dly_cap.fillna(11)
111
+ up.dly_min_approval_rate = up.dly_min_approval_rate.fillna(30)
112
+ up.declined = up.declined.fillna(0)
113
+ up.approval_rate = up.approval_rate.fillna(0)
114
+ up.soft_cap_alerted = up.soft_cap_alerted.fillna(False)
115
+ up.visa_soft_cap_alerted = up.visa_soft_cap_alerted.fillna(False)
116
+ up.drop('prev_mtd', axis=1, errors='ignore', inplace=True)
117
+ up = up.drop_duplicates(['gateway_id', 'router_id'])
118
+ # self.engine.execute(f'truncate {self.schema}.{self.table}')
119
+ self.upsert(up.dropna())
120
+
121
+ def gty_qry(self, crm_id, date, step, processor, cc_type=False, decs='', proc_excl=[], is_tds=None,
122
+ is_prepaid=False, is_decline_salvage=False, **kw):
123
+ p_ex = ''
124
+ if proc_excl and len(proc_excl) and not processor:
125
+ p_ex = f"and a.processor not ilike all(ARRAY{[f'%%{p}%%' for p in proc_excl]}::text[])"
126
+
127
+ if str(cc_type).lower() == 'visa':
128
+ dyna_cap_cols = "a.visa_fill_pct fill_pct, a.visa_dly_cap dly_initial_cap, a.visa_monthly_cap monthly_initial_cap, a.visa_soft_cap_alerted soft_cap_alerted, a.visa_count_mtd initial_count_mtd, a.visa_count initial_count, a.soft_cap_alerted sca2"
129
+ else:
130
+ dyna_cap_cols = "a.fill_pct, a.dly_initial_cap, a.monthly_initial_cap, a.soft_cap_alerted, initial_count_mtd, initial_count, a.visa_soft_cap_alerted sca2"
131
+
132
+
133
+ return f""" --LEFT HERE NEED TO GET MCC!
134
+ select a.gateway_id::int, priority, a.approval_rate, a.date_added, a.processor, a.mid_id, b.mcc,
135
+ {dyna_cap_cols}
136
+ from {self.schema}.{self.table} a
137
+ inner join (select crm_id, gateway_id, mcc from ui_54407332_clients.steps ) b on b.crm_id = a.crm_id and b.gateway_id=a.gateway_id
138
+ {"inner join (select crm_id, gateway_id where enable_decline_salvage) ds on ds.crm_id = a.crm_id and ds.gateway_id::int = a.gateway_id::int" if is_decline_salvage else ""}
139
+ inner join processing.cap c on a.mid_id = c.mid_id and a.step=c.step and a.processor=c.processor and c.monthly_available > 200
140
+ {f"left join processing.cap_cc_type d on a.mid_id = d.mid_id and a.step= d.step and a.processor = d.processor and d.cc_type = '{cc_type}' " if cc_type else ''}
141
+
142
+ where date = '{date}'::date and a.crm_id = '{crm_id}' and router_id = '{step if step in [1, 11] else 2}' and enabled and enable_initials
143
+ {f"and a.processor = '{processor}'" if processor else ""}
144
+ {f"and (exclude_cc_types is null or exclude_cc_types::text not ilike '%%{cc_type.lower()}%%')" if cc_type else ''}
145
+ and (approval_rate > dly_min_approval_rate or(declined+initial_count<110))
146
+ {'and (d.available_tc is null or d.available_tc >50)' if cc_type else ''}
147
+ {decs}
148
+ {p_ex}
149
+ {f"and enable_tds = {bool(is_tds)}" if is_tds else ""}
150
+ {f"and (tds_exclude_cc_types is null or tds_exclude_cc_types not ilike '%%{cc_type}%%')" if cc_type and is_tds else ""}
151
+ {f"and allow_prepaid" if is_prepaid else ""}
152
+ {f"and allow_non_prepaid" if not is_prepaid else ""}
153
+ --and fill_pct < 1
154
+
155
+ --order by date_added desc, approval_rate desc, fill_pct asc limit 1
156
+ order by priority desc, date_added desc, fill_pct, approval_rate desc, initial_count
157
+
158
+ """
159
+
160
+ def next_gateway(self, crm_id, date, step, click_id='', processor=False, cc_type=None, cc_first_8=False, recurse=0,
161
+ decs=False, ignore_user_exclusions=None,
162
+ proc_excl=[], is_tds=None, is_prepaid=True, **kwargs):
163
+ # opt vals 1 = random gateway constrained only by cap, 2 = optimised gateway constrained only by cap, 3 = Hybrid approach not ignoring settings, 4 = over cap (over-rides to that if needed)
164
+ if is_prepaid is None:
165
+ raise TypeError('is_prepaid value must be pass as a boolean got NoneType')
166
+
167
+ if is_prepaid:
168
+ pp_campaign_class = 'prepaid'
169
+ else:
170
+ pp_campaign_class = 'post_paid'
171
+ if ignore_user_exclusions is None:
172
+ ignore_user_exclusions = self._opt_val < 2
173
+ if cc_first_8:
174
+ self.set_bin_info(cc_first_8)
175
+ try:
176
+ decs = self.exclude_list(crm_id, step, click_id, 'a.') if not decs else decs
177
+ except Exception as e:
178
+ return str(e)
179
+
180
+ try:
181
+ qry = self.gty_qry(crm_id, date, step, processor, cc_type, decs, proc_excl=proc_excl, is_tds=is_tds,
182
+ is_prepaid=is_prepaid, **kwargs)
183
+ res = pd.read_sql(qry, self.engine)
184
+ cc_type = cc_type.lower()
185
+ if 'master' in cc_type:
186
+ cc_type = 'master'
187
+ try:
188
+ result = self._t_get_bin.result(timeout=4) # Wait for 2 seconds
189
+ except TimeoutError:
190
+ print("IIN INFO timed out!")
191
+ except Exception as e:
192
+ print(f"An error occurred: {e}")
193
+ if self._opt_val > 1 and self._opt_val < 4 and self.routes is not None:
194
+
195
+ self._lock_model_replace.acquire()
196
+ mod = self.routes if self.is_iin_data else self.routes.loc[
197
+ self.routes.mod_type.isin(['cc_type_conversion', 'cc_type_mcc_conversion'])]
198
+ self._lock_model_replace.release()
199
+ if len(mod): # and 'conversion_rate' in mod.columns:
200
+ if 'cc_level' not in mod.columns:
201
+ mod['cc_level'] = np_nan
202
+ if 'mcc' not in mod.columns:
203
+ mod['mcc'] = np_nan
204
+ mod = mod.loc[(mod.approved + mod.declined >= self._min_sample_count)
205
+ # & (mod.conversion_rate != 1) # take out dummy gateways
206
+ & ((mod.cc_first_8 == cc_first_8) | (mod.cc_first_8.isna()))
207
+ & (mod.campaign_class == pp_campaign_class)
208
+ & (((mod.cc_type == cc_type) | mod.cc_type.isna()) if 'cc_type' in mod.columns else (
209
+ True))
210
+ & (((mod.cc_level == str(self.iin_info['level'])) | (
211
+ mod.cc_level.isna())) if self.is_iin_data and 'level' in self.iin_info else (True))
212
+ & (((mod.bank == str(self.iin_info['bank'])) | (
213
+ mod.bank.isna())) if self.is_iin_data and 'bank' in self.iin_info else (True))
214
+ ]
215
+
216
+ df_opt = mod.copy().sort_values('conversion_rate', ascending=False).reset_index(drop=True)
217
+ df_opt['r_rank'] = df_opt.index + 1
218
+
219
+ # Optimization Filters
220
+
221
+ res = res.merge(df_opt.loc[df_opt.mod_type.isin(
222
+ ['cc_type_mcc_conversion', 'bank_conversion'])],
223
+ on=['processor', 'mcc'],
224
+ how='left').append(res.merge(
225
+ df_opt.loc[df_opt.mod_type.isin(
226
+ ['cc_type_cc_level_conversion', 'cc_type_conversion', 'iin_conversion'])].drop('mcc',
227
+ axis=1),
228
+ on=['processor'],
229
+ how='left')).sort_values('r_rank')
230
+ else:
231
+ res['mod_type'] = 'undefined'
232
+ res['conversion_rate'] = 0
233
+ # r_rank is Highest to lowest in terms of strength same as priority
234
+ res.mod_type = res.mod_type.fillna('undefined').replace({'nan': 'undefined', '': 'undefined'})
235
+ res.conversion_rate = res.conversion_rate.fillna(0)
236
+ else:
237
+ res['conversion_rate'] = 0
238
+ res['mod_type'] = 'undefined'
239
+ res = res.sort_values(**self.sort_map[self._opt_val]).drop_duplicates('gateway_id', keep='first')
240
+ res['cc_type'] = cc_type
241
+ res['cc_first_8'] = cc_first_8
242
+ self.set_iin(cc_first_8=cc_first_8, cc_type=cc_type)
243
+ except Exception as e:
244
+ print('LBV4 error', str(e))
245
+ raise e
246
+
247
+ if res is None or not len(res):
248
+ if not decs:
249
+ if not recurse and is_tds is not None:
250
+ return self.next_gateway(crm_id, date, step, click_id, processor, cc_type, recurse=recurse + 1,
251
+ is_tds=not is_tds, is_prepaid=is_prepaid)
252
+ elif recurse == 1:
253
+ self.init_date(date, crm_id)
254
+ return self.next_gateway(crm_id, date, step, click_id, processor, cc_type, recurse=recurse + 1,
255
+ is_tds=is_tds, is_prepaid=is_prepaid)
256
+ elif recurse == 2 and is_tds is not None:
257
+ return self.next_gateway(crm_id, date, step, click_id, processor, cc_type, recurse=recurse + 1,
258
+ is_tds=not is_tds, is_prepaid=is_prepaid)
259
+ return 'out of processing'
260
+ else:
261
+ # if len(decs) < 4:
262
+ # return 'out of processing'
263
+ return 'declined due to too many attempts'
264
+ r = res.loc[res.fill_pct < 1]
265
+ if 'conversion_rate' not in res:
266
+ res['conversion_rate'] = 0
267
+ # HARD CAP
268
+ if not len(r):
269
+
270
+ res = res.sort_values(['dly_initial_cap', 'conversion_rate'], ascending=[True, False]).sort_values(
271
+ ['fill_pct'])
272
+
273
+ def _get_aft_sc():
274
+ nonlocal res
275
+ if not len(res):
276
+ return 'out of processing'
277
+ r2 = res.to_dict(orient='records')[0]
278
+ if r2['initial_count_mtd'] >= r2['monthly_initial_cap']:
279
+ if cc_type == 'visa':
280
+ #self.alert_cb('hard_cap_alert', crm_id=crm_id, gateway_id=r2['gateway_id'], cc_type=cc_type)
281
+ # self.disable(crm_id=crm_id, gateway_id=r2['gateway_id'])
282
+ res = res.loc[res.gateway_id != r2['gateway_id']]
283
+ else:
284
+ self.alert_cb('hard_cap_alert', crm_id=crm_id, gateway_id=r2['gateway_id'], cc_type='Non-Visa')
285
+ return _get_aft_sc()
286
+ self.set_iin(**r2)
287
+ r2['is_tds'] = is_tds
288
+ return r2
289
+
290
+ # SOFT CAP
291
+ if ~res.soft_cap_alerted.any():
292
+ cnt = self.engine.execute(
293
+ f"""select count(*) from {self.schema}.{self.table}
294
+ where date = '{date}'::date and crm_id = '{crm_id}'
295
+ and router_id = '{step if step == 1 else 2}'
296
+ and enabled and enable_initials and fill_pct<1
297
+ """).scalar()
298
+ if cnt == 0 or cnt is None:
299
+ self.alert_cb('soft_cap_alert', crm_id=crm_id, cc_type=cc_type)
300
+ self.set_soft_cap_alerted(crm_id, cc_type=cc_type)
301
+ return _get_aft_sc()
302
+ r = r.to_dict(orient='records')[0]
303
+ if cc_type:
304
+ r['cc_type'] = cc_type
305
+ if cc_first_8:
306
+ r['cc_first_8'] = cc_first_8
307
+
308
+ self.set_iin(**r)
309
+ r['is_tds'] = is_tds
310
+ return r
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modelswrkpi
3
- Version: 8.1.3
3
+ Version: 9.0.1
4
4
  Author: Kelly Kapowski
5
5
  Requires-Python: >=3.10
6
6
  Requires-Dist: psycopg2
@@ -19,7 +19,7 @@ models/crm_errors.cpython-310-x86_64-linux-gnu.so,sha256=HOWYTHpij5vGEn6Y7_AEPSN
19
19
  models/custom_shipping.cpython-310-x86_64-linux-gnu.so,sha256=SopNkxl0GV2KjHTuFnsqUZwOGFq2nYebPWvgOZd9M2g,53584
20
20
  models/db.cpython-310-x86_64-linux-gnu.so,sha256=f9nmfnJ84IFkJk3QP9_Tm8q4lv2zGadUDsZr9NNCMWQ,470128
21
21
  models/discount_stats.cpython-310-x86_64-linux-gnu.so,sha256=jr0Gqkq2_TTHeaST-znR0BwC8bpfH5wUkd1f7PgZROk,65904
22
- models/discounter.cpython-310-x86_64-linux-gnu.so,sha256=Ntiyb6a343xBSwB9xJhYTa2AB-SFHAgW428lqVX06eI,563088
22
+ models/discounter.cpython-310-x86_64-linux-gnu.so,sha256=dNpqpihh1Osrgowo5UpYW3HjQ5reX5eFvzuOeTnAD_4,563088
23
23
  models/email_reconfs.cpython-310-x86_64-linux-gnu.so,sha256=-x74-9M7uhxlepuhL1uKCDbh66ysddraneuf5xFYlHA,49456
24
24
  models/exception_log.cpython-310-x86_64-linux-gnu.so,sha256=R23bYTbB_4JycgfxRbVZhY-SJPka2Qpw-jt_M-4c8J4,53584
25
25
  models/filter_index.cpython-310-x86_64-linux-gnu.so,sha256=_MmKmoRDRQCesNaeZTLPALeRmevkVgee7paEUkDegik,61904
@@ -65,21 +65,22 @@ models/bro_clicks/error_log.cpython-310-x86_64-linux-gnu.so,sha256=I8fwpBrbxaB_A
65
65
  models/bro_clicks/initial_routes.cpython-310-x86_64-linux-gnu.so,sha256=JEM-67AUh3VsAJ9a_rH37jH4tCqdX-E6NMYgiLo9mHg,140368
66
66
  models/bro_clicks/scrub_settings.cpython-310-x86_64-linux-gnu.so,sha256=gKo6LHc-3OCQRl1SAg9XH6XMBJujLoB5F-6sYgKjTZ0,160592
67
67
  models/bro_clicks/splitter.cpython-310-x86_64-linux-gnu.so,sha256=27kzt-JDllwAXMFq8Xe2Av0RIDpwFK4h_t6BvytGsak,57712
68
- models/bro_clicks/load_balancer/__init__.py,sha256=h0UIw3AFm-gdyK-3xR1NgFKC95sJW1hz2Pw2dMdkA3A,370
69
- models/bro_clicks/load_balancer/compile.py,sha256=M1o0NKWcQe6b27e96PZlNUBBe8EFP5CnI3cWDamzquk,600
70
- models/bro_clicks/load_balancer/v1.cpython-310-x86_64-linux-gnu.so,sha256=IJa5FkmwEsQXh8ULGGjoP_hPbxkXWw1KABwmVV1YDUc,160656
71
- models/bro_clicks/load_balancer/v1.py,sha256=Df-LMtS0l0psJCyguSHtSIt_ofLwop55ogWDq3eFrig,8518
68
+ models/bro_clicks/load_balancer/__init__.py,sha256=TMIh-RpmoCaEMTLU7geYtcDpygX5KFM8B4RRsHcKutA,432
69
+ models/bro_clicks/load_balancer/compile.py,sha256=0mD0LCkkR2aasWk8AdxVA6ylHN28l4bV6vwkA2TUQF4,661
70
+ models/bro_clicks/load_balancer/v1.cpython-310-x86_64-linux-gnu.so,sha256=iFWITw0tjieXWku8F2lg06n7Ar29r57AjA_ZUV35SO4,172976
71
+ models/bro_clicks/load_balancer/v1.py,sha256=ikWbsxGFsYNTVbDGp43OvcbAGITFT9pt8JqEiq9zheI,10840
72
72
  models/bro_clicks/load_balancer/v2.cpython-310-x86_64-linux-gnu.so,sha256=VCGHr8KSipO2E0IfJ0zSpdte-xw_xsSK5vRWujtumnU,140368
73
73
  models/bro_clicks/load_balancer/v2.py,sha256=WSM6lKtyLrzx1xdhL3ncuH4QH-FBnS5Gm0uDFAtNHXo,7303
74
74
  models/bro_clicks/load_balancer/v3.cpython-310-x86_64-linux-gnu.so,sha256=f03MbM9KyuKpctvJ-6g6pnhMbnsasPtTkFVeQlRXUeA,256496
75
75
  models/bro_clicks/load_balancer/v3.py,sha256=-seP7t7dVO-O2q4I3wqgKrgTKxGPWVROHvSzVgwd_ug,16542
76
76
  models/bro_clicks/load_balancer/v4.cpython-310-x86_64-linux-gnu.so,sha256=kbQws2ObO2BxOOxjCaB7_H8IA1allHZ-zsX2kYMvrJo,136208
77
77
  models/bro_clicks/load_balancer/v4.py,sha256=wGe66SzYIa4qiPnA4ZZQ5tisvXv_j7XZZCVrsCG23Eg,7732
78
- models/bro_clicks/load_balancer/v5.cpython-310-x86_64-linux-gnu.so,sha256=VkmSqG11rgZTOv5AzhhVga52Ay6rrRKqmrrFVj8gUl0,127568
79
- models/bro_clicks/load_balancer/v5.py,sha256=GLRcbOUAI4n2m8wv7yGNhRZoPHQ8WO_Ra4FeAr3Yxsg,7755
80
- models/bro_clicks/load_balancer/v6.cpython-310-x86_64-linux-gnu.so,sha256=FHmp___9eteGe8pX_kHA5PDSIM7mLGkXhxWHg47imPc,165360
81
- models/bro_clicks/load_balancer/v6.py,sha256=Ekt-wML3bGadz1dOhDBC-L2WKrgzmRJc8ASTcY1rOgI,9608
82
- models/bro_clicks/load_balancer/v7.py,sha256=tkk6FpLgQvKCaFf2kmKsHhW_Pj4gJq4PcSe-DKcIUC4,264
78
+ models/bro_clicks/load_balancer/v5.cpython-310-x86_64-linux-gnu.so,sha256=gHA2J0wZsH9XdQSa13aQQELgOET9qCieiTB5RaJgztQ,127568
79
+ models/bro_clicks/load_balancer/v5.py,sha256=jA1KPoJLcm8szMGhaGuMSH-dZ6d0dwNv1PgGm0UHsJ0,8036
80
+ models/bro_clicks/load_balancer/v6.cpython-310-x86_64-linux-gnu.so,sha256=1X_3SFmkafbH3Ejj8q7aHUHHxNzpP6zlJXNTKehks2s,165360
81
+ models/bro_clicks/load_balancer/v6.py,sha256=oD_VYJ_Yvm5YJAGBx4IYxQHvIbKTeRq-Y00O38adOyQ,9587
82
+ models/bro_clicks/load_balancer/v7.cpython-310-x86_64-linux-gnu.so,sha256=iGvt5u_PYzCMhf4MBbRWhH29sR-PyBSz7yAayf4qBVI,210064
83
+ models/bro_clicks/load_balancer/v7.py,sha256=AJUdUt8vy4g639AAKaS5VWilfSOC74ycB3Pf471UOE0,18121
83
84
  models/bro_clicks/load_balancer/v8.py,sha256=tkk6FpLgQvKCaFf2kmKsHhW_Pj4gJq4PcSe-DKcIUC4,264
84
85
  models/cb911/__init__.py,sha256=Y3tX5WQYFUswdMMUpWqa9U_fNObUAhXcVrix3eXYP4k,64
85
86
  models/cb911/alerts.cpython-310-x86_64-linux-gnu.so,sha256=LCsUfaTzdQKS6ZaKQbfLCNTZbpZqaJmEsWDTUOdHUrI,61808
@@ -135,7 +136,7 @@ models/reports/table_reports/inactive_report.cpython-310-x86_64-linux-gnu.so,sha
135
136
  models/reports/table_reports/mtd_report.cpython-310-x86_64-linux-gnu.so,sha256=dHko7wWia9y9d-gIPC8uxycUnobII6hQgairSPRU168,74096
136
137
  models/vaultx/__init__.py,sha256=PwYMmWXQMojeyFnQuQW3wNlv9dLUmX_uiDfCOHJN7XI,46
137
138
  models/vaultx/ssc_cont.cpython-310-x86_64-linux-gnu.so,sha256=69kGuEko6oJEqxopS_4BxoX5S-Twq94eFwYJFEu_4B8,94992
138
- modelswrkpi-8.1.3.dist-info/METADATA,sha256=XCityP9r2Cx1HypVjO8vH3ZgKaxvq4AuHUoorH_6AqM,346
139
- modelswrkpi-8.1.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
140
- modelswrkpi-8.1.3.dist-info/top_level.txt,sha256=fOgLNy4xnMfp0ihe_kFhY_yH71kNkdEQG68z8FoLR4g,19
141
- modelswrkpi-8.1.3.dist-info/RECORD,,
139
+ modelswrkpi-9.0.1.dist-info/METADATA,sha256=eGnsJVZAHfaAtMyEqhIuUB3bPgfExeaEvjDkZm14RLI,346
140
+ modelswrkpi-9.0.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
141
+ modelswrkpi-9.0.1.dist-info/top_level.txt,sha256=fOgLNy4xnMfp0ihe_kFhY_yH71kNkdEQG68z8FoLR4g,19
142
+ modelswrkpi-9.0.1.dist-info/RECORD,,