def depmut_execute(self, agent_id, type, amount, comment, pin): result = { 'success': 0, 'balance': 0, } try: int(amount) except: result['message'] = 'AMOUNT NOT VALID' return json.dumps(result) # agent must exist bc = AgentNotifier() c_agent = DBCache(const.AGENT_PREFIX, config.DEFAULT_EXPIRE, const.AGENT_SQL) c_agent.setConn(bc.dbconn, bc.cacheconn) #print c_agent.sGet(agentid) ag = c_agent.sGet(agent_id) if not ag: result['message'] = 'AGENT NOT REGISTERED' return json.dumps(result) dm = DepositMutation(20, bc.dbconn, bc.cacheconn) prev_bal = dm.getBalance(agent_id) if type.upper() == 'C': balance = dm.credit(agent_id, int(amount), comment) bc.writeNotifyOut(ag['default_protocol'], 'deposit_credit', { 'mutation': thousandSeparator(amount), 'balance_before': thousandSeparator(prev_bal), 'balance': thousandSeparator(balance), }) elif type.upper() == 'D': balance = dm.debit(agent_id, int(amount), comment) bc.writeNotifyOut(ag['default_protocol'], 'deposit_debit', { 'mutation': thousandSeparator(amount), 'balance_before': thousandSeparator(prev_bal), 'balance': thousandSeparator(balance), }) else: result['message'] = 'TYPE NOT RECOGNIZED' return json.dumps(result) if balance == NOT_ENOUGH_BALANCE: result['message'] = 'NOT ENOUGH BALANCE' return json.dumps(result) elif balance == LOCK_FAILED: result['message'] = 'SERVER BUSY' return json.dumps(result) bc.dbconn.commit() msg = '{0}-{1} Deposit: Rp. {2} Before: Rp. {3} After: Rp. {4} ({5}) ID:{6}'.\ format(ag['agent_id'], ag['agent_name'], thousandSeparator(amount), thousandSeparator(prev_bal), thousandSeparator(balance), comment, dm.last_id) for prot in ('ym://b_martian','ym://inileonard', 'ym://sridwan981'): bc.writeNotifyOut(prot, 'general_message', {'message': msg}) bc.dbconn.commit() result.update({ 'success': 1, 'message': 'SUCCESS', 'balance': balance, 'mutation_id': dm.last_id, }) return json.dumps(result)
def bundle(self, name, agent_id, price, pin): bc = AgentNotifier() c_agent = DBCache(const.AGENT_PREFIX, config.DEFAULT_EXPIRE, const.AGENT_SQL) c_agent.setConn(bc.dbconn, bc.cacheconn) dm = DepositMutation(20, bc.dbconn, bc.cacheconn) ag = c_agent.sGet(agent_id) if not ag: return json.dumps({'success': 0, 'reason': 'AGENT NOT FOUND'}) sql = '''SELECT * FROM `bundle` WHERE `bundle_name`=%s''' c = bc.dbconn.cursor(MySQLdb.cursors.DictCursor) c.execute(sql, (name,)) cs = c.fetchall() if len(cs) == 0: return json.dumps({'success': 0, 'reason': 'BUNDLE NOT FOUND'}) balance = dm.debit(agent_id, int(price), 'Bundle {0}'.format(name)) if balance < 0: return json.dumps({'success': 0, 'reason': 'NOT ENOUGH DEPOSIT'}) um = UnitMutation(5, bc.dbconn, bc.cacheconn) for r in c: um.credit(agent_id, r['product_id'], r['unit'], 0, name) msg = 'Add bundle {0} to {1}-{2} Rp {3}'.\ format(name, agent_id, ag['agent_name'], thousandSeparator(price)) for prot in ('ym://b_martian','ym://inileonard', 'ym://sridwan981'): bc.writeNotifyOut(prot, 'general_message', {'message': msg}) bc.dbconn.commit() return json.dumps({'success': 1, 'reason': ''})
def __init__(self): super(LoadBalance, self).__init__("LB") self.operator = self._loadOperator() self.c_product = DBCache(const.PRODUCT_PREFIX, config.DEFAULT_EXPIRE, const.PRODUCT_SQL) self.c_op_product = DBCache(const.OP_PRODUCT_PREFIX, config.DEFAULT_EXPIRE, const.OP_PRODUCT_SQL) self.c_device = DBCache(const.DEVICES_PREFIX, config.DEFAULT_EXPIRE, const.DEVICES_SQL) self.c_base_price = DBCache(const.CHIP_BASE_PRICE_PREFIX, config.DEFAULT_EXPIRE, const.CHIP_BASE_PRICE_SQL) map( lambda x: x.setConn(self.dbconn, self.cacheconn), [self.c_product, self.c_op_product, self.c_device, self.c_base_price], ) # self.hlr_cache = HLRCacheForLB(self.dbconn, self.cacheconn) # self.hlr_cache.cacheAllTopupDevice() self.lb = LBTopup(self.dbconn) self.lb.cleanRebuild() self.hm = HLRMap(self.dbconn, self.cacheconn) self.hm.rebuild() self.dm = DepositMutation(5, self.dbconn, self.cacheconn) self.last_op_prod = None self.last_device = None self.last_hlr_id = None self.last_tr_id = None self.last_tr_data = None self.change_method = None self.log = mylogger("LoadBalance", "loadbalance.log")
def transaction_success(self, tran_id, pin): bc = AgentNotifier() c = bc.dbconn.cursor(MySQLdb.cursors.DictCursor) c.execute('''SELECT SQL_NO_CACHE `reg_protocol`,`product_id`,`msisdn_destination`, `agent_id`,`base_price`,`sell_price`,`status`,`order`,`deposit`,`type` FROM `transaction` where `transaction_id`=%s''', (tran_id,)) r = c.fetchone() if not r: return json.dumps({'success': 0, 'reason': 'RECORD NOT FOUND'}) if int(r['status']) == const.TR_RETRIED or \ int(r['status']) == const.TR_EXECUTED or \ int(r['status']) > const.TR_FAILED_GENERAL_REV: return json.dumps({'success': 0, 'reason': 'CANNOT SET STATUS'}) if int(r['status']) >= const.TR_FAILED_HLR_REV and \ int(r['status']) <= const.TR_FAILED_GENERAL_REV : dm = DepositMutation(20, bc.dbconn, bc.cacheconn) dm.debit(r['agent_id'], r['sell_price'], 'Manual success {0}'.\ format(tran_id)) c_agent_price = DBCache(const.AGENTPRICE_PREFIX, config.DEFAULT_EXPIRE, const.AGENTPRICE_SQL) owner = '{0:0>{1}}'.format(1, config.AGENT_ID_LENGTH) try: if r['agent_id'] != owner: fl = getFrontline(bc.dbconn, bc.cacheconn, r['agent_id']) if not fl: self.logger.error('<countProfit> Frontline for agent {0} not found'.format(r['agent_id'])) raise else: fl = r['agent_id'] ag = c_agent_price.sGet((fl, r['product_id'],)) if not ag: self.logger.error('<countProfit> Price for agent {0} not found'.format(r['agent_id'])) raise profit = int(ag['sell_price']) - int(r['base_price']) except: profit = 0 c.execute('''UPDATE `transaction` SET `status`=%s,`profit`=%s WHERE `transaction_id`=%s''', (const.TR_EXECUTED, profit, tran_id,)) r['references'] = '0' bc.notifyTopupSucess(r) bc.dbconn.commit() return json.dumps({'success': 1, 'reason': 'SUCCESS'})
def transaction_fail(self, tran_id, pin): bc = AgentNotifier() c = bc.dbconn.cursor(MySQLdb.cursors.DictCursor) c.execute('''SELECT SQL_NO_CACHE `reg_protocol`,`product_id`,`msisdn_destination`, `agent_id`,`sell_price`,`status`,`order`,`deposit`,`type` FROM `transaction` where `transaction_id`=%s''', (tran_id,)) r = c.fetchone() if not r: return json.dumps({'success': 0, 'reason': 'RECORD NOT FOUND'}) if int(r['status']) < const.TR_AUTHORIZED or \ int(r['status']) >= const.TR_RETRIED: return json.dumps({'success': 0, 'reason': 'CANNOT SET STATUS'}) dm = DepositMutation(20, bc.dbconn, bc.cacheconn) dm.credit(r['agent_id'], r['sell_price'], 'reversal Transaction {0}'.\ format(tran_id)) c.execute('UPDATE `transaction` set `status`=%s where `transaction_id`=%s', (const.TR_FAILED_GENERAL_REV, tran_id,)) # r['deposit'] = int(r['deposit']) + int(r['sell_price']) bc.notifyTopupFail(r, False) bc.dbconn.commit() return json.dumps({'success': 1, 'reason': 'SUCCESS'})
def deposit_transfer(self, agent_id_from, agent_id_to, amount, order, pin): '''Transfer deposit from one agent to another''' bc = AgentNotifier() dt = deptran.DepositTransfer(10, bc.dbconn, bc.cacheconn) result = { 'success': 0, 'balance_from': 0, 'balance_to': 0, } am = ManageAgentPrice(bc.dbconn, bc.cacheconn) tmp = am.verifyAgent(agent_id_from, 'xxxx') if tmp['code'] != agent.AGST_WRONGPIN: result['message'] = 'AGENT {0} ERROR'.format(agent_id_from) return json.dumps(result) tmp = am.verifyAgent(agent_id_to, 'xxxx') if tmp['code'] != agent.AGST_WRONGPIN: result['message'] = 'AGENT {0} ERROR'.format(agent_id_to) return json.dumps(result) if dt.searchSameTransfer(agent_id_from, agent_id_to, amount, order): result['message'] = 'TRANSFER EXIST' return json.dumps(result) tmp = dt.transfer(agent_id_from, agent_id_to, amount, order, True) response = { deptran.AMOUNT_ZERO: 'AMOUNT IS ZERO', deptran.NOT_ENOUGH_BALANCE: 'NOT ENOUGH BALANCE', deptran.AMOUNT_NOT_NUMBER: 'AMOUNT NOT NUMBER', deptran.OVER_REVOKE: 'OVER REVOKE', deptran.SOURCE_DEST_SAME: 'SOURCE IS THE SAME AS DESTINATION' } if tmp in response: result['message'] = response[tmp] return json.dumps(result) dm = DepositMutation(20, bc.dbconn, bc.cacheconn) result['balance_from'] = dm.getBalance(agent_id_from) result['balance_to'] = dm.getBalance(agent_id_to) result['message'] = 'SUCCESS' result['success'] = 1 return json.dumps(result)
def __init__(self): BaseComponent.__init__(self, "AU") self.c_operator = DBCache( const.OPERATOR_PREFIX, config.DEFAULT_EXPIRE, const.OPERATOR_SQL, user_func={"prefix": lambda x: x.split(",")}, ) self.c_product = DBCache(const.PRODUCT_PREFIX, config.DEFAULT_EXPIRE, const.PRODUCT_SQL) self.c_agentprice = DBCache(const.AGENTPRICE_PREFIX, config.DEFAULT_EXPIRE, const.AGENTPRICE_SQL) self.dm = DepositMutation(5, self.dbconn, self.cacheconn) self.um = UnitMutation(5, self.dbconn, self.cacheconn) self.log = mylogger("Authorizer", "authorizer.log")
def setUp(self): self.bc = BaseComponent() self.dbconn = self.bc.dbconn self.cacheconn = self.bc.cacheconn self.cacheconn.delete('{0}_00001'.format(const.MUTATION_PREFIX)) cursor = self.dbconn.cursor() self._resetTable('Deposit_Mutation') try: cursor.execute('''INSERT INTO `agent` (`agent_id`, `active`, `agent_name`, `agent_address`, `agent_type`, `pin`, `upline_id`, `markup`, `markup_upline`, `set_price`, `register_date`, `last_activity_date`, `last_update`, `last_update_by`) VALUES ('00001', 1, 'Bernard Martian', 'Test', 1, '9999', '', 100, 0, 'Test', '2010-11-09 18:24:44', '2010-11-09 18:24:51', '2010-11-24 00:50:12', '')''') except: pass cursor.close() self.dbconn.commit() self.c_agent = DBCache(const.AGENT_PREFIX, config.DEFAULT_EXPIRE, const.AGENT_SQL) self.c_agent.setConn(self.dbconn, self.cacheconn) self.dm = DepositMutation(2, self.dbconn, self.cacheconn)
class TestDepositMutation(TestAdminHelper): #---------------------- def setUp(self): self.bc = BaseComponent() self.dbconn = self.bc.dbconn self.cacheconn = self.bc.cacheconn self.cacheconn.delete('{0}_00001'.format(const.MUTATION_PREFIX)) cursor = self.dbconn.cursor() self._resetTable('Deposit_Mutation') try: cursor.execute('''INSERT INTO `agent` (`agent_id`, `active`, `agent_name`, `agent_address`, `agent_type`, `pin`, `upline_id`, `markup`, `markup_upline`, `set_price`, `register_date`, `last_activity_date`, `last_update`, `last_update_by`) VALUES ('00001', 1, 'Bernard Martian', 'Test', 1, '9999', '', 100, 0, 'Test', '2010-11-09 18:24:44', '2010-11-09 18:24:51', '2010-11-24 00:50:12', '')''') except: pass cursor.close() self.dbconn.commit() self.c_agent = DBCache(const.AGENT_PREFIX, config.DEFAULT_EXPIRE, const.AGENT_SQL) self.c_agent.setConn(self.dbconn, self.cacheconn) self.dm = DepositMutation(2, self.dbconn, self.cacheconn) #---------------------- def runTest(self): test_function = [x for x in dir(self) if x[:6] == 'srtest'] map(lambda x: getattr(self, x)(), sorted(test_function)) #---------------------- def srtest010(self): balance = self.dm.debit('00001', 10000, 'srtest010') self.dbconn.commit() self.assertEqual(balance, depmut.NOT_ENOUGH_BALANCE) balance = self.dm.credit('00001', 10000, 'srtest010') self.dbconn.commit() self.assertEqual(balance, 10000) balance = self.dm.debit('00001', 5000, 'srtest010') self.dbconn.commit() self.assertEqual(balance, 5000) #---------------------- def srtest020_lock(self): self.dm.l_mutation.lockNoWait(self.cacheconn, '00001') balance = self.dm.credit('00001', 10000, 'srtest010') self.assertEqual(balance, depmut.LOCK_FAILED) self.dm.l_mutation.release(self.cacheconn, '00001') #---------------------- def srtest030_adminHelperDepositMutation(self): post_data = { 'agent_id': '00001', 'type': 'D', 'amount': 5000 } tmp = self._callAdminHelper('deposit_mutation', post_data) self.assertEqual(tmp['success'], 1) self.assertEqual(tmp['balance'], 0) tmp = self._callAdminHelper('deposit_mutation', post_data) self.assertEqual(tmp['success'], 0) self.assertEqual(tmp['message'], 'NOT ENOUGH BALANCE') post_data['type'] = 'X' tmp = self._callAdminHelper('deposit_mutation', post_data) self.assertEqual(tmp['success'], 0) self.assertEqual(tmp['message'], 'TYPE NOT RECOGNIZED') post_data['agent_id'] = 'xxx' tmp = self._callAdminHelper('deposit_mutation', post_data) self.assertEqual(tmp['success'], 0) self.assertEqual(tmp['message'], 'AGENT NOT REGISTERED') #---------------------- def tearDown(self): self.cacheconn.delete('{0}_00001'.format(const.MUTATION_PREFIX)) self.dbconn.close()
class LoadBalance(AgentNotifier): """Process topup requests and balance them on available devices""" def __init__(self): super(LoadBalance, self).__init__("LB") self.operator = self._loadOperator() self.c_product = DBCache(const.PRODUCT_PREFIX, config.DEFAULT_EXPIRE, const.PRODUCT_SQL) self.c_op_product = DBCache(const.OP_PRODUCT_PREFIX, config.DEFAULT_EXPIRE, const.OP_PRODUCT_SQL) self.c_device = DBCache(const.DEVICES_PREFIX, config.DEFAULT_EXPIRE, const.DEVICES_SQL) self.c_base_price = DBCache(const.CHIP_BASE_PRICE_PREFIX, config.DEFAULT_EXPIRE, const.CHIP_BASE_PRICE_SQL) map( lambda x: x.setConn(self.dbconn, self.cacheconn), [self.c_product, self.c_op_product, self.c_device, self.c_base_price], ) # self.hlr_cache = HLRCacheForLB(self.dbconn, self.cacheconn) # self.hlr_cache.cacheAllTopupDevice() self.lb = LBTopup(self.dbconn) self.lb.cleanRebuild() self.hm = HLRMap(self.dbconn, self.cacheconn) self.hm.rebuild() self.dm = DepositMutation(5, self.dbconn, self.cacheconn) self.last_op_prod = None self.last_device = None self.last_hlr_id = None self.last_tr_id = None self.last_tr_data = None self.change_method = None self.log = mylogger("LoadBalance", "loadbalance.log") def skipError(self): c = self.dbconn.cursor(MySQLdb.cursors.DictCursor) c.execute( """UPDATE `transaction` SET `status`=%s WHERE `transaction_id`=%s""", (const.TR_FAILED_GENERAL, self.last_tr_id), ) c.close() self.writeNotifyOut( "sms://08161940700", "general_message", {"message": "<LoadBalance>: Error while processing " "transaction {0}".format(self.last_tr_id)}, ) tr = self.last_tr_data tr["deposit"] = int(tr["deposit"]) + int(tr["sell_price"]) self.notifyTopupFail(tr) self.dbconn.commit() print "Error while processing transaction {0}".format(self.last_tr_id) self.log.error("Error while processing transaction {0}".format(self.last_tr_id)) def loadBalance(self): sql = """SELECT SQL_NO_CACHE `transaction_id`,`reg_protocol`,`agent_id`, `product_id`,`operator_id`,`msisdn_destination`,`sell_price`, `order`,`deposit` FROM `transaction` WHERE `status`={0} and `method`='CH' LIMIT 100""" cursor = self.dbconn.cursor(MySQLdb.cursors.DictCursor) cursor.execute(sql.format(const.TR_AUTHORIZED)) rows = cursor.fetchall() if len(rows) == 0: cursor.close() return False for tran in rows: tr_id = tran["transaction_id"] self.last_tr_id = tr_id self.last_tr_data = dict(tran) dest_num = tran["msisdn_destination"] print "Topup id {2}, product {0} untuk nomor {1}".format( tran["product_id"], tran["msisdn_destination"], tran["transaction_id"] ) self.log.info( "<loadBalance>Topup id {2}, product {0} untuk nomor {1}".format( tran["product_id"], tran["msisdn_destination"], tran["transaction_id"] ) ) prod = self.c_product.sGet(tran["product_id"]) if not prod: self.log.error( '<loadBalance>Not found row in table "Product" ' "with product_id={0}".format(tran["product_id"]) ) continue op_id = prod["operator_id"] op_type = self.operator[op_id]["type"] opprod_list = self._extractOperatorProduct(prod) if op_type == "G": # GSM result = self._executeTopupGSM(tr_id, op_id, opprod_list, dest_num) self.log.info( "<loadBalance>Operator Product {1}\nTopup GSM {0}\nResult={2}".format(prod, opprod_list, result) ) elif op_type == "C": # CDMA result = self._executeTopupCDMA(tr_id, op_id, opprod_list, dest_num) self.log.info( "<loadBalance>Operator Product {1}\nTopup CDMA {0}\nResult={2}".format(prod, opprod_list, result) ) protocol = tran["reg_protocol"] if result == ET_SUCCESS: self._transactionInProgress(tr_id) if protocol[:3].lower() == "sms": continue self.writeNotifyOut( protocol, "transaction_in_progress", {"product_id": tran["product_id"], "dest": dest_num} ) continue elif result == ET_CHANGE_METHOD: self._moveToNextMethod(tr_id, self.change_method) continue next_method = self._getNextMethod(prod) if next_method: self._moveToNextMethod(tr_id, next_method) elif result == ET_HLR_NOT_SUPPORTED: self._transactionResult(tr_id, const.TR_FAILED_HLR) self.writeNotifyOut(protocol, "hlr_not_supported", {"dest": dest_num}) elif result == ET_OUT_OF_STOCK: self._transactionResult(tr_id, const.TR_OUT_OF_STOCK) agent_bal = int(tran["sell_price"]) + self.dm.getBalance(tran["agent_id"]) self.writeNotifyOut( protocol, "out_of_stock", {"product_id": tran["product_id"], "balance": thousandSeparator(agent_bal)}, ) cursor.close() self.dbconn.commit() return True def _moveToNextMethod(self, tr_id, method): cursor = self.dbconn.cursor() sql = """UPDATE `transaction` set `method`=%s, `hlr_id`=%s WHERE `transaction_id`=%s""" cursor.execute(sql, (method, self.last_hlr_id, tr_id)) cursor.close() def _getNextMethod(self, prod): a = ("method_1_active", "method_2_active", "method_3_active", "method_4_active", "method_5_active") m = ("method_1", "method_2", "method_3", "method_4", "method_5") methods = map(lambda x: prod[x], [_m for _a, _m in zip(a, m) if prod[_a] == 1]) try: i = methods.index("CH") if i >= (len(methods) - 1): return None return methods[i + 1] except: return None def _extractOperatorProduct(self, prod): result = [] tmp = ( "operator_product_id_1", "operator_product_id_2", "operator_product_id_3", "operator_product_id_4", "operator_product_id_5", ) for i in tmp: if len(prod[i]) > 0: result.append(prod[i]) return result def _transactionResult(self, tr_id, status): cursor = self.dbconn.cursor() sql = """UPDATE `transaction` set `status`=%s where `transaction_id`=%s""" cursor.execute(sql, (status, tr_id)) cursor.close() def _transactionInProgress(self, tr_id): supplier_id = self.c_device.sGet(self.last_device)["supplier_id"] base_price = self.c_base_price.sGet((supplier_id, self.last_op_prod))["base_price"] cursor = self.dbconn.cursor() sql = """UPDATE `transaction` set `status`=%s, `operator_product_id`=%s, `device_id`=%s, `hlr_id`=%s, `supplier_id`=%s, `base_price`=%s where `transaction_id`=%s""" cursor.execute( sql, ( const.TR_INPROGRESS, self.last_op_prod, self.last_device, self.last_hlr_id, supplier_id, base_price, tr_id, ), ) cursor.close() def _executeTopupGSM(self, tr_id, op_id, prod_list, dest): hlr = dest[:8] result = self._executeTopup(tr_id, op_id, prod_list, dest, hlr) return result def _executeTopupCDMA(self, tr_id, op_id, prod_list, dest): hlr2 = dest[:4] return self._executeTopup(tr_id, op_id, prod_list, dest, hlr2) def _executeTopup(self, tr_id, op_id, prod_list, dest, hlr): """""" def stockOK(dev_id, prod_list): for prod_id in prod_list: op_prod = self.c_op_product.sGet(prod_id) if not self._checkUnitOrBalance(dev_id, op_prod): continue else: return op_prod return None hlr_id, method = self.hm.getHLRID2(op_id, hlr) if not hlr_id: hlr_id = 0 elif method.upper() != "CH": self.change_method = method return ET_CHANGE_METHOD dev_list = self.lb.getLB(op_id, hlr_id) picked_dev_id = None for dev in dev_list: dev_id = dev["device_id"] op_prod = stockOK(dev_id, prod_list) if not op_prod: continue else: picked_dev_id = dev_id break if not picked_dev_id: return ET_OUT_OF_STOCK topup_parse = op_prod["topup_parse"] self._sendToLeaf(tr_id, dev_id, topup_parse, dest) self.last_op_prod = op_prod["operator_product_id"] self.last_device = picked_dev_id self.last_hlr_id = hlr_id self.lb.use(picked_dev_id) # print('ET_SUCCESS dev: {0}'.format(picked_dev_id)) return ET_SUCCESS def _checkUnitOrBalance(self, dev_id, op_prod): """Check unit or balance of a chip""" def checkUnit(dev_id, prod_id): cursor = self.dbconn.cursor(MySQLdb.cursors.DictCursor) cursor.execute( "SELECT SQL_NO_CACHE `balance_unit` from `unit` WHERE " "`device_id`=%s and `operator_product_id`=%s LIMIT 1", (dev_id, prod_id), ) r = cursor.fetchone() # print('<_checkUnitOrBalance - checkUnit> dev_id={1}, prod_id={2}, result={0}'.format(r, dev_id, prod_id)) cursor.close() if not r: return False if int(r["balance_unit"]) < 1: return False return True def checkBalance(dev_id, amount): cursor = self.dbconn.cursor(MySQLdb.cursors.DictCursor) cursor.execute( "SELECT SQL_NO_CACHE `topup_balance` from `balance` " "WHERE `device_id`=%s LIMIT 1", (dev_id,) ) r = cursor.fetchone() cursor.close() if not r: return False if int(r["topup_balance"]) < amount: return False return True if not op_prod: return False bal_type = op_prod["balance_flag"] unit_used = op_prod["unit_used"] # print('<_checkUnitOrBalance> bal_type={0}, unit_used={1}'.format(bal_type, unit_used)) if bal_type.upper() == "U": if checkUnit(dev_id, unit_used): return True else: if checkBalance(dev_id, int(op_prod["topup_amount_chip"])): return True return False def _sendToLeaf(self, tran_id, dev_id, parse, dest): pin = self.c_device.sGet(dev_id)["pin"] server_id, port = dev_id.split(".") leaf_server = "{0}@{2}/{1}".format(config.LEAFSERVER, server_id, config.MSG_SERVER) parse = multipleReplace({"<dest>": dest, "<pin>": pin}, parse) # msg = '{0},{1},{2},{3},{4}'.format(port, tran_id, parse, dest, pin) msg = "{0}.{1},{2},{3}".format(server_id, port, tran_id, parse) self.sendMessage(leaf_server, "JBDV", msg, commit=False) def _loadOperator(self): """Get self.operator""" result = {} cursor = self.dbconn.cursor(MySQLdb.cursors.DictCursor) cursor.execute( """SELECT `operator_id`,`operator_name`,`type`,`prefix` FROM `operator` order by `operator_id` ASC""" ) for op in cursor: op["prefix"] = op["prefix"].split(",") result[op["operator_id"]] = op cursor.close() return result
def setUp(self): super(TestAuthorizer, self).setUp() self.cacheconn.flush_all() cursor = self.dbconn.cursor() self._resetTable('Transaction') self._resetTable('Notify_Out') self._resetTable('Deposit_Mutation') cursor.execute('DELETE FROM `operator`') cursor.execute('''INSERT INTO `operator` (`operator_id`, `operator_name`, `type`, `prefix`, `stock_check_1`, `stock_check_2`, `sim_balance`, `last_update`, `last_update_by`) VALUES (1, 'Telkomsel', 'G', '0812,0813,0852,0853', 'ussd://*776*<pin>#', 'ussd://*676*<pin>#', 'ussd://*888#', '2010-11-17 17:34:44', ''), (2, 'Indosat', 'G', '0814,0815,0816,0855,0856,0857,0858', 'data://31.<pin>$', '', 'ussd://*388#', '2010-10-29 18:52:34', ''), (3, 'XL', 'G', '0817,0818,0819,0859,0877,0878', 'sms://balance,461', '', 'ussd://*123#', '2010-10-29 18:52:48', ''), (4, 'Three', 'G', '0894,0896,0898,0899', 'data://+13.<pin>$', '', '', '2010-10-20 15:08:41', ''), (5, 'Axis', 'G', '0831,0832,0833,0838', 'data://13.<pin>$', '', '', '2010-10-20 15:08:36', ''), (6, 'Fren', 'G', '0888,0889', '', '', '', '0000-00-00 00:00:00', ''), (7, 'Esia', 'C', '4,6,8,9', 'sms:// bal <pin>,898', '', 'sms://talktime,555', '2010-11-17 20:52:29', ''), (8, 'Flexi', 'C', '2,3,4,5,6,7,8,9', 'sms://qd#<pin,899', '', '', '2010-10-20 15:10:59', ''), (9, 'StarOne', 'C', '3,8', '', '', '', '0000-00-00 00:00:00', ''), (10, 'Hepi', 'C', '3,4,5', '', '', '', '0000-00-00 00:00:00', ''), (11, 'Smart', 'G', '0881,0882,0883,0884,0885,0886,0887', '', '', '', '0000-00-00 00:00:00', '')''') cursor.execute('DELETE FROM `agent_price`') cursor.execute('''INSERT INTO `agent_price` (`agent_id`, `product_id`, `sell_price`, `markup_upline`, `date_time`, `status`, `last_update`, `last_update_by`) VALUES ('00001', 'A10', 10150, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'A5', 5150, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'AP10', 10100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'AP5', 5100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'AX10', 10100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'AX20', 20100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'AX50', 50100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'E25', 25100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'E50', 50100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'F10', 10100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'F20', 20100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'F5', 5100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'FR10', 10100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'FR20', 20100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'FR25', 25100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'H10', 10100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'H25', 25100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'H5', 5100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'M10', 10100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'M5', 5100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'S10', 10100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'S5', 5100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'SM10', 10100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'SM20', 20100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'SM5', 5100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'SO10', 10100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'SO20', 20100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'SO5', 5100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'SP10', 10100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'SP5', 5100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'T10', 10100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'T20', 20100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'T5', 5100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'X10', 10100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'X5', 5100, 0, NULL, 1, '0000-00-00 00:00:00', '')''') cursor.execute('DELETE FROM `product`') cursor.execute('''INSERT INTO `product` (`product_id`, `product_name`, `operator_id`, `active`, `point`, `operator_product_id_1`, `operator_product_id_2`, `operator_product_id_3`, `operator_product_id_4`, `operator_product_id_5`, `method_1`, `method_1_active`, `method_2`, `method_2_active`, `method_3`, `method_3_active`, `method_4`, `method_4_active`, `method_5`, `method_5_active`, `last_update`, `last_update_by`) VALUES ('A10', 'As 10.000', 1, 1, 1, 'SIMPATI10', 'AS10', '', '', '', 'CH', 1, 'H2', 0, 'YM', 0, '', 0, '', 0, '2010-07-08 18:48:06', ''), ('A5', 'As 5.000', 1, 1, 1, 'SIMPATI5', 'AS5', '', '', '', 'CH', 1, 'H2', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:07', ''), ('AP10', 'As 10.000 Promo', 1, 1, 1, 'AS5', 'SIMPATI5', '', '', '', 'CH', 1, 'H2', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:08', ''), ('AP5', 'As 5.000 Promo', 1, 0, 1, 'AS5', 'SIMPATI5', '', '', '', 'CH', 1, 'H2', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:08', ''), ('AX10', 'Axis 10.000', 5, 1, 1, 'AXIS10', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:09', ''), ('AX20', 'Axis 20.000', 5, 1, 1, 'AXIS20', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:10', ''), ('AX50', 'Axis 50.000', 5, 1, 1, 'AXIS50', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:10', ''), ('BR5', 'Broom 5.000', 2, 1, 1, 'INDOSAT5BROOM', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '0000-00-00 00:00:00', ''), ('E25', 'Esia 25.000', 7, 1, 1, 'ESIA25', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:11', ''), ('E50', 'Esia 50.000', 7, 1, 1, 'ESIA50', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:11', ''), ('F10', 'Flexi 10.000', 8, 1, 1, 'FLEXI10', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:12', ''), ('F20', 'Flexi 20.000', 8, 1, 1, 'FLEXI20', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:16', ''), ('F5', 'Flexi 5.000', 8, 1, 1, 'FLEXI5', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:17', ''), ('FR10', 'Fren 10.000', 6, 1, 1, 'FREN10', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:17', ''), ('FR20', 'Fren 20.000', 6, 1, 1, 'FREN20', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:18', ''), ('FR25', 'Fren 25.000', 6, 1, 1, 'FREN25', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:19', ''), ('H10', 'Hepi 10.000', 10, 1, 1, 'HEPI10', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:19', ''), ('H25', 'Hepi 25.000', 10, 1, 1, 'HEPI25', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:20', ''), ('H5', 'Hepi 5.000', 10, 1, 1, 'HEPI5', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:20', ''), ('M10', 'Mentari 10.000', 2, 1, 1, 'MENTARI10', 'IM10', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:21', ''), ('M5', 'Mentari 5.000', 2, 1, 1, 'MENTARI5', 'IM5', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:22', ''), ('S10', 'Simpati 10.000', 1, 1, 1, 'SIMPATI10', 'AS10', '', '', '', 'CH', 1, 'H2', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:22', ''), ('S5', 'Simpati 5.000', 1, 1, 1, 'SIMPATI5', 'AS5', '', '', '', 'CH', 1, 'H2', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:23', ''), ('SM10', 'Smart 10.000', 11, 1, 1, 'SMART10', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:24', ''), ('SM20', 'Smart 20.000', 11, 1, 1, 'SMART20', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:24', ''), ('SM5', 'Smart 5.000', 11, 1, 1, 'SMART5', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:25', ''), ('SO10', 'StarOne 10.000', 9, 1, 1, 'SO10', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:26', ''), ('SO20', 'StarOne 20.000', 9, 1, 1, 'SO20', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:26', ''), ('SO5', 'StarOne 5.000', 9, 1, 1, 'SO5', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:27', ''), ('SP10', 'Simpati 10.000 Promo', 1, 1, 1, 'SIMPATI10', 'AS10', '', '', '', 'CH', 1, 'H2', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:27', ''), ('SP5', 'Simpati 5.000 Promo', 1, 1, 1, 'SIMPATI5', 'AS5', '', '', '', 'CH', 1, 'H2', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:28', ''), ('T10', 'Three 10.000', 4, 1, 1, 'THREE10', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:29', ''), ('T20', 'Three 20.000', 4, 1, 1, 'THREE20', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:29', ''), ('T5', 'Three 5.000', 4, 1, 1, 'THREE5', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:30', ''), ('X10', 'XL 10.000', 3, 1, 1, 'XL10', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:31', ''), ('X25', 'XL 25.000', 3, 1, 1, 'XL25', '', '', '', '', '', 0, '', 0, '', 0, '', 0, '', 0, '0000-00-00 00:00:00', ''), ('X5', 'XL 5.000', 3, 1, 1, 'XL5', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:31', '')''') cursor.close() self.dbconn.commit() self._createProcess(_prAuthorizer) self.ids = [] self.c_message = DBCache(const.MESSAGE_PREFIX, config.DEFAULT_EXPIRE, const.MESSAGE_SQL) self.c_message.setConn(self.dbconn, self.cacheconn) self.idgen = range(50) self.deposit = DepositMutation(1, self.dbconn, self.cacheconn) self.deposit.credit('00001', 25000, 'setup credit', True)
class TestAuthorizer(TestCoreComponent): def setUp(self): super(TestAuthorizer, self).setUp() self.cacheconn.flush_all() cursor = self.dbconn.cursor() self._resetTable('Transaction') self._resetTable('Notify_Out') self._resetTable('Deposit_Mutation') cursor.execute('DELETE FROM `operator`') cursor.execute('''INSERT INTO `operator` (`operator_id`, `operator_name`, `type`, `prefix`, `stock_check_1`, `stock_check_2`, `sim_balance`, `last_update`, `last_update_by`) VALUES (1, 'Telkomsel', 'G', '0812,0813,0852,0853', 'ussd://*776*<pin>#', 'ussd://*676*<pin>#', 'ussd://*888#', '2010-11-17 17:34:44', ''), (2, 'Indosat', 'G', '0814,0815,0816,0855,0856,0857,0858', 'data://31.<pin>$', '', 'ussd://*388#', '2010-10-29 18:52:34', ''), (3, 'XL', 'G', '0817,0818,0819,0859,0877,0878', 'sms://balance,461', '', 'ussd://*123#', '2010-10-29 18:52:48', ''), (4, 'Three', 'G', '0894,0896,0898,0899', 'data://+13.<pin>$', '', '', '2010-10-20 15:08:41', ''), (5, 'Axis', 'G', '0831,0832,0833,0838', 'data://13.<pin>$', '', '', '2010-10-20 15:08:36', ''), (6, 'Fren', 'G', '0888,0889', '', '', '', '0000-00-00 00:00:00', ''), (7, 'Esia', 'C', '4,6,8,9', 'sms:// bal <pin>,898', '', 'sms://talktime,555', '2010-11-17 20:52:29', ''), (8, 'Flexi', 'C', '2,3,4,5,6,7,8,9', 'sms://qd#<pin,899', '', '', '2010-10-20 15:10:59', ''), (9, 'StarOne', 'C', '3,8', '', '', '', '0000-00-00 00:00:00', ''), (10, 'Hepi', 'C', '3,4,5', '', '', '', '0000-00-00 00:00:00', ''), (11, 'Smart', 'G', '0881,0882,0883,0884,0885,0886,0887', '', '', '', '0000-00-00 00:00:00', '')''') cursor.execute('DELETE FROM `agent_price`') cursor.execute('''INSERT INTO `agent_price` (`agent_id`, `product_id`, `sell_price`, `markup_upline`, `date_time`, `status`, `last_update`, `last_update_by`) VALUES ('00001', 'A10', 10150, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'A5', 5150, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'AP10', 10100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'AP5', 5100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'AX10', 10100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'AX20', 20100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'AX50', 50100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'E25', 25100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'E50', 50100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'F10', 10100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'F20', 20100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'F5', 5100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'FR10', 10100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'FR20', 20100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'FR25', 25100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'H10', 10100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'H25', 25100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'H5', 5100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'M10', 10100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'M5', 5100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'S10', 10100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'S5', 5100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'SM10', 10100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'SM20', 20100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'SM5', 5100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'SO10', 10100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'SO20', 20100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'SO5', 5100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'SP10', 10100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'SP5', 5100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'T10', 10100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'T20', 20100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'T5', 5100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'X10', 10100, 0, NULL, 1, '0000-00-00 00:00:00', ''), ('00001', 'X5', 5100, 0, NULL, 1, '0000-00-00 00:00:00', '')''') cursor.execute('DELETE FROM `product`') cursor.execute('''INSERT INTO `product` (`product_id`, `product_name`, `operator_id`, `active`, `point`, `operator_product_id_1`, `operator_product_id_2`, `operator_product_id_3`, `operator_product_id_4`, `operator_product_id_5`, `method_1`, `method_1_active`, `method_2`, `method_2_active`, `method_3`, `method_3_active`, `method_4`, `method_4_active`, `method_5`, `method_5_active`, `last_update`, `last_update_by`) VALUES ('A10', 'As 10.000', 1, 1, 1, 'SIMPATI10', 'AS10', '', '', '', 'CH', 1, 'H2', 0, 'YM', 0, '', 0, '', 0, '2010-07-08 18:48:06', ''), ('A5', 'As 5.000', 1, 1, 1, 'SIMPATI5', 'AS5', '', '', '', 'CH', 1, 'H2', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:07', ''), ('AP10', 'As 10.000 Promo', 1, 1, 1, 'AS5', 'SIMPATI5', '', '', '', 'CH', 1, 'H2', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:08', ''), ('AP5', 'As 5.000 Promo', 1, 0, 1, 'AS5', 'SIMPATI5', '', '', '', 'CH', 1, 'H2', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:08', ''), ('AX10', 'Axis 10.000', 5, 1, 1, 'AXIS10', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:09', ''), ('AX20', 'Axis 20.000', 5, 1, 1, 'AXIS20', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:10', ''), ('AX50', 'Axis 50.000', 5, 1, 1, 'AXIS50', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:10', ''), ('BR5', 'Broom 5.000', 2, 1, 1, 'INDOSAT5BROOM', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '0000-00-00 00:00:00', ''), ('E25', 'Esia 25.000', 7, 1, 1, 'ESIA25', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:11', ''), ('E50', 'Esia 50.000', 7, 1, 1, 'ESIA50', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:11', ''), ('F10', 'Flexi 10.000', 8, 1, 1, 'FLEXI10', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:12', ''), ('F20', 'Flexi 20.000', 8, 1, 1, 'FLEXI20', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:16', ''), ('F5', 'Flexi 5.000', 8, 1, 1, 'FLEXI5', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:17', ''), ('FR10', 'Fren 10.000', 6, 1, 1, 'FREN10', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:17', ''), ('FR20', 'Fren 20.000', 6, 1, 1, 'FREN20', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:18', ''), ('FR25', 'Fren 25.000', 6, 1, 1, 'FREN25', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:19', ''), ('H10', 'Hepi 10.000', 10, 1, 1, 'HEPI10', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:19', ''), ('H25', 'Hepi 25.000', 10, 1, 1, 'HEPI25', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:20', ''), ('H5', 'Hepi 5.000', 10, 1, 1, 'HEPI5', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:20', ''), ('M10', 'Mentari 10.000', 2, 1, 1, 'MENTARI10', 'IM10', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:21', ''), ('M5', 'Mentari 5.000', 2, 1, 1, 'MENTARI5', 'IM5', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:22', ''), ('S10', 'Simpati 10.000', 1, 1, 1, 'SIMPATI10', 'AS10', '', '', '', 'CH', 1, 'H2', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:22', ''), ('S5', 'Simpati 5.000', 1, 1, 1, 'SIMPATI5', 'AS5', '', '', '', 'CH', 1, 'H2', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:23', ''), ('SM10', 'Smart 10.000', 11, 1, 1, 'SMART10', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:24', ''), ('SM20', 'Smart 20.000', 11, 1, 1, 'SMART20', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:24', ''), ('SM5', 'Smart 5.000', 11, 1, 1, 'SMART5', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:25', ''), ('SO10', 'StarOne 10.000', 9, 1, 1, 'SO10', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:26', ''), ('SO20', 'StarOne 20.000', 9, 1, 1, 'SO20', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:26', ''), ('SO5', 'StarOne 5.000', 9, 1, 1, 'SO5', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:27', ''), ('SP10', 'Simpati 10.000 Promo', 1, 1, 1, 'SIMPATI10', 'AS10', '', '', '', 'CH', 1, 'H2', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:27', ''), ('SP5', 'Simpati 5.000 Promo', 1, 1, 1, 'SIMPATI5', 'AS5', '', '', '', 'CH', 1, 'H2', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:28', ''), ('T10', 'Three 10.000', 4, 1, 1, 'THREE10', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:29', ''), ('T20', 'Three 20.000', 4, 1, 1, 'THREE20', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:29', ''), ('T5', 'Three 5.000', 4, 1, 1, 'THREE5', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:30', ''), ('X10', 'XL 10.000', 3, 1, 1, 'XL10', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:31', ''), ('X25', 'XL 25.000', 3, 1, 1, 'XL25', '', '', '', '', '', 0, '', 0, '', 0, '', 0, '', 0, '0000-00-00 00:00:00', ''), ('X5', 'XL 5.000', 3, 1, 1, 'XL5', '', '', '', '', 'CH', 1, '', 0, '', 0, '', 0, '', 0, '2010-07-08 18:48:31', '')''') cursor.close() self.dbconn.commit() self._createProcess(_prAuthorizer) self.ids = [] self.c_message = DBCache(const.MESSAGE_PREFIX, config.DEFAULT_EXPIRE, const.MESSAGE_SQL) self.c_message.setConn(self.dbconn, self.cacheconn) self.idgen = range(50) self.deposit = DepositMutation(1, self.dbconn, self.cacheconn) self.deposit.credit('00001', 25000, 'setup credit', True) #---------------------- def runTest(self): test_function = [x for x in dir(self) if x[:6] == 'srtest'] map(lambda x: getattr(self, x)(), sorted(test_function)) #---------------------- def srtest10_authorized(self): # TR_AUTHORIZED self.newRequest(('1', '00001', 'sms://08161940700', 'A10', '08128191891', 1, 0, 1)) t = self._waitForRow('SELECT `status` from `transaction` WHERE ' '`transaction_id`="1" and `status`={0}'.format(const.TR_AUTHORIZED)) self.assertEqual(t, {'status': const.TR_AUTHORIZED}) t = self._waitForRow('SELECT `mutation`,`type`,`deposit_balance` FROM ' '`deposit_mutation` where `deposit_balance`=14850 and `agent_id`="00001"') self.assertEqual(t, {'mutation': 10150, 'type': "D", 'deposit_balance': 14850}) #---------------------- def srtest20_wrong_number(self): # TR_DENIED_WRONG_NUMBER self.newRequest(('2', '00001', 'sms://08161940700', 'A10', '08168191891', 1, 0, 1)) t = self._waitForRow('SELECT `status` from `transaction` WHERE ' '`transaction_id`="2" and `status`={0}'.format(const.TR_DENIED_WRONG_NUMBER)) self.assertEqual(t, {'status': const.TR_DENIED_WRONG_NUMBER}) t = self._waitForRow('SELECT `command` from `notify_out` where `parameters` ' 'LIKE "sms://08161940700,% 08168191891 %"') self.assertEqual(t, {'command': 'SMSG'}) #---------------------- def srtest30_denied_product(self): # TR_DENIED_PRODUCT self.newRequest(('3', '00001', 'sms://08161940700', 'XXX10', '08168191891', 1, 0, 2)) self.newRequest(('4', '00001', 'sms://08161940700', 'AP5', '08168191891', 1, 0, 1)) t = self._waitForRow('SELECT `status` from `transaction` WHERE ' '`transaction_id`="3" and `status`={0}'.format(const.TR_DENIED_PRODUCT)) self.assertEqual(t, {'status': const.TR_DENIED_PRODUCT}) t = self._waitForRow('SELECT `command` from `notify_out` where `parameters` ' 'LIKE "sms://08161940700,% XXX10 %"') self.assertEqual(t, {'command': 'SMSG'}) t = self._waitForRow('SELECT `status` from `transaction` WHERE ' '`transaction_id`="4" and `status`={0}'.format(const.TR_DENIED_PRODUCT)) self.assertEqual(t, {'status': const.TR_DENIED_PRODUCT}) t = self._waitForRow('SELECT `command` from `notify_out` where `parameters` ' 'LIKE "sms://08161940700,% AP5 %"') self.assertEqual(t, {'command': 'SMSG'}) t = self._waitForRow('SELECT COUNT(*) FROM `deposit_mutation`') self.assertEqual(t, {'COUNT(*)': 3}) #---------------------- def srtest40_denied_balance(self): # TR_DENIED_BALANCE self.newRequest(('5', '00001', 'sms://08161940700', 'AX50', '0838000111', 1, 0, 5)) t = self._waitForRow('SELECT `status` from `transaction` WHERE ' '`transaction_id`="5" and `status`={0}'.format(const.TR_DENIED_BALANCE)) self.assertEqual(t, {'status': const.TR_DENIED_BALANCE}) t = self._waitForRow('SELECT `command` from `notify_out` where `parameters` ' 'LIKE "sms://08161940700,% AX50 %"') self.assertEqual(t, {'command': 'SMSG'}) #---------------------- def newRequest(self, p): cursor = self.dbconn.cursor() cursor.execute('INSERT INTO `transaction` (`transaction_id`,`agent_id`,' '`reg_protocol`,`product_id`,`msisdn_destination`,`order`,`status`,`operator_id`) ' 'VALUES (%s,%s,%s,%s,%s,%s,%s,%s)', p) cursor.close() self.dbconn.commit() #---------------------- def getMessage(self, msg, tosub={}): tmp = self.c_message.sGet(msg)['parse'] tosub = dict(zip(map(lambda x: '<{0}>'.format(x),tosub.keys()), map(str,tosub.values()))) if tosub == {}: return tmp return multipleReplace(tosub, tmp)
class Authorizer(BaseComponent): """Authorize Topup Request """ def __init__(self): BaseComponent.__init__(self, "AU") self.c_operator = DBCache( const.OPERATOR_PREFIX, config.DEFAULT_EXPIRE, const.OPERATOR_SQL, user_func={"prefix": lambda x: x.split(",")}, ) self.c_product = DBCache(const.PRODUCT_PREFIX, config.DEFAULT_EXPIRE, const.PRODUCT_SQL) self.c_agentprice = DBCache(const.AGENTPRICE_PREFIX, config.DEFAULT_EXPIRE, const.AGENTPRICE_SQL) self.dm = DepositMutation(5, self.dbconn, self.cacheconn) self.um = UnitMutation(5, self.dbconn, self.cacheconn) self.log = mylogger("Authorizer", "authorizer.log") def authorize(self): requests = self.checkTopupRequest() if len(requests) == 0: return False for req in requests: agent_id, product_id = (req["agent_id"], req["product_id"]) tr_id, op_id = (req["transaction_id"], req["operator_id"]) prod_status, prod = self.checkProduct(product_id) if prod_status != PRODUCT_AVAILABLE: # self.productNotAvailable(req['reg_protocol'], product_id, prod_status) self.productNotAvailable(req["reg_protocol"], product_id) self.setDenied(tr_id, const.TR_DENIED_PRODUCT) continue ptype = int(prod["type"]) if ptype in (1, 3): num_status, op_name = self.checkDestination(op_id, req["msisdn_destination"]) if num_status != DEST_OP_MATCH: self.destOperatorDontMatch(req["reg_protocol"], req["msisdn_destination"], op_name) self.setDenied(tr_id, const.TR_DENIED_WRONG_NUMBER) continue if ptype in (1, 2, 3): prod_price, markup = self.getPriceForAgent(agent_id, product_id) if not prod_price: self.productNotAvailable(req["reg_protocol"], product_id) self.setDenied(tr_id, const.TR_DENIED_PRODUCT) continue if ptype in (1, 2): bal_stat, balance = self.deductBalance(agent_id, prod_price, tr_id) if ptype == 3: balance = self.um.debit(agent_id, product_id, 1, tr_id, "Topup {0}".format(tr_id)) if balance in (NOT_ENOUGH_BALANCE, LOCK_FAILED): bal_stat = BALANCE_NOT_ENOUGH balance = 0 if bal_stat != BALANCE_OK: self.notEnoughBalance(req["reg_protocol"], product_id, balance, req["msisdn_destination"]) self.setDeniedBalance(tr_id, const.TR_DENIED_BALANCE, balance) continue self.setAuthorized(tr_id, prod_price, balance, markup) self.dbconn.commit() return True def checkTopupRequest(self): cursor = self.dbconn.cursor(MySQLdb.cursors.DictCursor) cursor.execute( "SELECT SQL_NO_CACHE `transaction_id`,`agent_id`," "`product_id`,`reg_protocol`,`msisdn_destination`,`operator_id` " "FROM `transaction` where `status`={0} LIMIT 100".format(const.TR_WAIT) ) requests = cursor.fetchall() cursor.close() return requests def checkProduct(self, prodid): prod = self.c_product.get(self.dbconn, self.cacheconn, prodid) if not prod: return (PRODUCT_NOT_REGISTERED, None) if prod["active"] == 0: return (PRODUCT_NOT_SOLD, None) return (PRODUCT_AVAILABLE, prod) def checkDestination(self, op_id, dest): opdata = self.c_operator.get(self.dbconn, self.cacheconn, op_id) if opdata == None: print "No data for operator id {0}".format(op_id) self.log.critical("No data for operator id {0}".format(op_id)) return None try: if opdata["type"] == "G": if dest[0:4] in opdata["prefix"]: return (DEST_OP_MATCH, opdata["operator_name"]) else: return (DEST_OP_DONT_MATCH, opdata["operator_name"]) elif opdata["type"] == "C": if (dest[3] in opdata["prefix"]) or (dest[4] in opdata["prefix"]): return (DEST_OP_MATCH, opdata["operator_name"]) else: return (DEST_OP_DONT_MATCH, opdata["operator_name"]) except: return (DEST_OP_DONT_MATCH, opdata["operator_name"]) def deductBalance(self, agentid, price, tuid): balance = self.dm.getBalance(agentid) if balance < price: return (BALANCE_NOT_ENOUGH, balance) balance = self.dm.debit(agentid, price, "Topup {0}".format(tuid)) if balance == LOCK_FAILED: return (BALANCE_NOT_ENOUGH, 0) return (BALANCE_OK, balance) def setAuthorized(self, ids, price, balance, markup): cursor = self.dbconn.cursor(MySQLdb.cursors.DictCursor) cursor.execute( """UPDATE `transaction` set `status`={0}, `sell_price`=%s, `deposit`=%s, `markup_margin`=%s where `transaction_id`=%s""".format( const.TR_AUTHORIZED ), (price, balance, markup, ids), ) cursor.close() def setDenied(self, ids, status): cursor = self.dbconn.cursor(MySQLdb.cursors.DictCursor) cursor.execute("UPDATE `transaction` set `status`={0} " "WHERE `transaction_id`=%s".format(status), (ids,)) cursor.close() def setDeniedBalance(self, ids, status, balance): cursor = self.dbconn.cursor(MySQLdb.cursors.DictCursor) cursor.execute( "UPDATE `transaction` set `status`={0}," "`deposit`=%s where `transaction_id`=%s".format(status), (balance, ids), ) cursor.close() def getPriceForAgent(self, agentid, prodid): ap = self.c_agentprice.get(self.dbconn, self.cacheconn, (agentid, prodid)) if not ap: self.log.warning( "<getPriceForAgent> price not found for agent " "{0} and product {1}".format(agentid, prodid) ) return (None, None) return (int(ap["sell_price"]), int(ap["markup_upline"])) def productNotAvailable(self, prot, prodid): self.writeNotifyOut(prot, "prod_not_registered", {"product_id": prodid}) def notEnoughBalance(self, prot, prodid, balance, dest): self.writeNotifyOut( prot, "agent_not_enough_balance", {"product_id": prodid, "balance": thousandSeparator(balance), "dest": dest}, ) def destOperatorDontMatch(self, prot, num, opname): self.writeNotifyOut(prot, "num_op_dont_match", {"dest": num, "operator": opname})