Exemplo n.º 1
0
 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': ''})            
Exemplo n.º 2
0
 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)
Exemplo n.º 3
0
 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'})
Exemplo n.º 4
0
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()
Exemplo n.º 5
0
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})