Esempio n. 1
0
    def get_transactions_sum(self, \
                             trx_with_credid, \
                             st_dt=None, \
                             end_dt=None):
        """ get the transactions within the given period inclusively

        @param trx_with_credid: the credential id of the client of interest
        @param st_dt: the start datetime
        @param end_dt: the end datetime
        @return dataframe of the transactions
        """
        if end_dt==None:
            end_dt=dt.datetime.now().strftime(TIMESTAMP_FORMAT)

        stat = "SELECT (ledger.trx_cost, cur.currency_name) FROM ledger INNER JOIN currency AS cur ON (cur.id=ledger.trx_cur_id) WHERE (trx_dest={to_credid} OR trx_src={from_credid});".\
            format(to_credid=sql.Literal(trx_with_credid),\
                   from_credid=sql.Literal(trx_with_credid))

        if not st_dt==None:
            #note! FOR UPDATE is not allowed with aggregate functions
            stat=sql.SQL("SELECT (ledger.trx_cost, cur.currency_name) FROM ledger INNER JOIN currency AS cur ON (cur.id=ledger.trx_cur_id) WHERE (trx_dt>={st_dt} AND trx_dt<{end_dt} AND trx_dest={to_credid}) OR (trx_dt>={st_dt} AND trx_dt<{end_dt} AND trx_src={from_credid});").\
            format(st_dt=sql.Literal(st_dt),\
                   end_dt=sql.Literal(end_dt),\
                   to_credid=sql.Literal(trx_with_credid), \
                   from_credid=sql.Literal(trx_with_credid))
        self.db_log.debug(stat)
        #self.cur.execute(stat)
        #fet=self.cur.fetchone()[0]
        #if fet==None:
            #return 0
        #return fet
        trxs_df=pd.read_sql(stat, self.conn)
        #the transaction sum in euros
        sum=0
        for i in range(len(trxs_df)):
            row=eval(trxs_df.iloc[i][0])
            value=row[0]
            base=row[1]
            currency = Currency(EUR, base)
            ineuro_cost=currency.exchange(value)
            sum+=float(ineuro_cost)
        return sum
Esempio n. 2
0
def get_balance():
    """ get balance of the current client

    @return {'balance': balance, 'base': base}
    """
    balance = None
    logger.info("balance requested")
    db.init()
    try:
        db.repeatable_read()
        cid = db.gets.credid2cid(session['credid'])
        if not db.exists.bank_account_bycid(cid):
            raise Exception("no bank account added yet!")
        #this would return balance in bank base
        balance = db.gets.get_balance_by_credid(session['credid'])
        # transform balance to user preference
        pref_cur = db.gets.get_preference_currency_bycid(cid)
        amount = balance['balance']
        base = balance['base']
        currency = Currency(pref_cur, base)
        pref_balance = currency.exchange(amount)
        payload = {'balance': pref_balance, 'base': pref_cur}
        db.commit()
    except psycopg2.DatabaseError as error:
        db.rollback()
        emsg = "failed request, error: {} ".format(+str(error))
        logger.critical()
        abort(300, emsg)
    except:
        db.rollback()
        emsg = "failed request"
        logger.critical(emsg)
        abort(300, emsg)
    finally:
        db.close()
    return jsonify(payload), 201
Esempio n. 3
0
def make_transaction():
    print('XXX ---------- make transaction started')
    req = request.get_json(force=True)
    recipt_credid = req['credid']
    # the amount of transaction in Euro
    orig_amount = req['amount']
    currency_base = req.get('currency', EUR)
    #exchange amount to euro for processing
    to_euro = Currency(EUR, currency_base)
    amount = to_euro.exchange(orig_amount)
    trx_name = req.get('trx_name', '')
    #TRANSACTION LIMITS IN EUROS
    max_daily = daily_limit()
    max_weekly = weekly_limit()
    #here the weekly/daily conditions are pivoted by the current moment only, note that the bank system can have specific pivot hour (the first momemnt of the day, it's specific for the bank system, and need to be known before hand)
    week_past = datetime.datetime.now() - datetime.timedelta(days=7)
    day_past = datetime.datetime.now() - datetime.timedelta(days=1)
    #TODO abide to the  the constrains
    logger.info("making purchase")
    if not req or amount == None or recipt_credid == None:
        emsg = "incomplete URL empty request"
        logger.critical(emsg)
        abort(401, emsg)
    #gid=req['id']
    db.init()
    MAKE_TRANSACTION_LOCK = 9
    lock = MAKE_TRANSACTION_LOCK
    print('start transaction')
    try:
        db.lock_advisory(lock)
        #if this client have a bank account yet
        cid = db.gets.credid2cid(session['credid'])
        if not db.exists.bank_account_bycid(cid):
            raise Exception("client doesn't have any associated bank account!")
        #balance in bank base
        src_balance = db.gets.get_balance_by_credid(session['credid'])
        src_balance_exchange = Currency(EUR, src_balance['base'])
        src_balance_euro = src_balance_exchange.exchange(
            src_balance['balance'])
        if src_balance_euro < amount + FEE:
            emsg = "client doesn't have enough credit to make transaction"
            logger.critical(emsg)
            raise Exception(emsg)
        #get transaction sum in euro
        weekly_trx_sum = db.gets.get_transactions_sum(session['credid'],
                                                      week_past)
        daily_trx_sum = db.gets.get_transactions_sum(session['credid'],
                                                     day_past)
        print('got trx sum! weekly: {}, daily{}'.format(
            weekly_trx_sum, daily_trx_sum))
        if weekly_trx_sum + amount > max_weekly or daily_trx_sum + amount > max_daily:
            emsg = "client passed the daily/weekly limit"
            logger.info(emsg)
            raise Exception(emsg)
        cur_id = db.gets.get_currency_id(currency_base)
        #add transaction
        db.inserts.insert_trx(recipt_credid, session['credid'], amount, cur_id,
                              trx_name)
        #TODO this can be minimized directly by credid
        #dest balance in bank base
        print('XXX ---------- start of calculation')
        dest_balance = db.gets.get_balance_by_credid(recipt_credid)
        dest_balance_exchange = Currency(EUR, dest_balance['base'])
        dest_balance_euro = dest_balance_exchange.exchange(
            dest_balance['balance'])
        src_balance_new = src_balance_euro - (amount + FEE)
        dest_balance_new = dest_balance_euro + amount
        #exchange back to bank bas
        src_balance_new = src_balance_exchange.exchange_back(src_balance_new)
        dest_balance_new = dest_balance_exchange.exchange_back(
            dest_balance_new)
        src_cid = db.gets.credid2cid(session['credid'])
        des_cid = db.gets.credid2cid(recipt_credid)
        print('XXX ---------- end of calculation')
        if src_cid == des_cid:
            print("src/dest {}/{}".format(src_cid, des_cid))
            emsg = "you can't make transaction with oneself!"
            logger.critical(emsg)
            raise Exception(emsg)
        print('XXX ---------- update balance?!')
        db.updates.update_account(src_cid, src_balance_new)
        db.updates.update_account(des_cid, dest_balance_new)
        trx = {'trx_dest': recipt_credid,  \
               'trx_src': session['credid'], \
               'trx_cost': orig_amount, \
               'trx_name':trx_name}
        payload={'balance': src_balance_new, \
                 'transactions': trx}
        print('XXX ---------- finished transaction')
        db.commit()
    except psycopg2.DatabaseError as error:
        db.rollback()
        emsg = "transaction failed, error: {}".format(str(error))
        logger.critical(emsg)
        abort(500, emsg)
    except:
        db.rollback()
        emsg = "transaction failed"
        logger.critical(emsg)
        abort(401, emsg)
    finally:
        db.unlock_advisory(lock)
        db.close()
    return jsonify(payload), 201