def _process_lock(self, session, curs, data, operation, balance_updater): lock_f = BalanceLockFilter(session, { 'id': data['lock_id'], 'balance_id': data['balance_id'] }, {}, None) lock = lock_f.filter_one_obj(curs) balance = self._get_active_balance(session, curs, data) currs_id_idx = self._get_currs_idx(curs, 'id') currency = currs_id_idx[balance.currency_id] info = data.get('info', {}) trans_data = { 'environment_id': session.environment_id, 'user_id': balance.user_id, 'balance_id': balance.id, 'currency_code': currency.code, 'type': operation, 'real_amount': cents_to_decimal(currency, lock.real_amount), 'virtual_amount': cents_to_decimal(currency, lock.virtual_amount), 'order_id': lock.order_id, 'info': info } balance_updater(balance, lock) mapping.update(curs, balance) trans = Transaction(**trans_data) mapping.delete(curs, lock) mapping.insert(curs, trans) return response_ok(transaction_id=trans.id)
def _process_lock(self, session, curs, data, operation, balance_updater): lock_f = BalanceLockFilter(session, {'id': data['lock_id'], 'balance_id': data['balance_id']}, {}, None) lock = lock_f.filter_one_obj(curs) balance = self._get_active_balance(session, curs, data) currs_id_idx = self._get_currs_idx(curs, 'id') currency = currs_id_idx[balance.currency_id] info = data.get('info', {}) trans_data = {'environment_id': session.environment_id, 'user_id': balance.user_id, 'balance_id': balance.id, 'currency_code': currency.code, 'type': operation, 'real_amount': cents_to_decimal(currency, lock.real_amount), 'virtual_amount': cents_to_decimal(currency, lock.virtual_amount), 'order_id': lock.order_id, 'info': info} balance_updater(balance, lock) mapping.update(curs, balance) trans = Transaction(**trans_data) mapping.delete(curs, lock) mapping.insert(curs, trans) return response_ok(transaction_id=trans.id)
def viewer(balance): currency = currs_id_idx[balance.currency_id] return { 'id': balance.id, 'user_id': balance.user_id, 'is_active': balance.is_active, 'currency_code': currency.code, 'real_amount': '%s' % cents_to_decimal(currency, balance.real_amount), 'virtual_amount': '%s' % cents_to_decimal(currency, balance.virtual_amount), 'overdraft_limit': '%s' % cents_to_decimal(currency, balance.overdraft_limit), 'locked_amount': '%s' % cents_to_decimal(currency, balance.locked_amount), }
def lock(self, data, session, curs=None): balance = self._get_active_balance(session, curs, data) currs_id_idx = self._get_currs_idx(curs, 'id') currency = currs_id_idx[balance.currency_id] lock_amount_dec = Decimal(data['amount']) lock_amount = decimal_to_cents(currency, lock_amount_dec) if lock_amount < 0: lock_amount *= -1 locking_order = data['locking_order'] amounts_to_lock = compute_locks(balance, lock_amount, locking_order) lock_real = amounts_to_lock.get('real_amount', 0) lock_virtual = amounts_to_lock.get('virtual_amount', 0) order_id = data['order_id'] info = data.get('info', {}) info['locking_order'] = locking_order trans_data = { 'environment_id': session.environment_id, 'user_id': balance.user_id, 'balance_id': balance.id, 'currency_code': currency.code, 'type': 'lock', 'real_amount': cents_to_decimal(currency, lock_real), 'virtual_amount': cents_to_decimal(currency, lock_virtual), 'order_id': order_id, 'info': info } lock_data = { 'environment_id': session.environment_id, 'user_id': balance.user_id, 'balance_id': balance.id, 'real_amount': lock_real, 'locking_order': locking_order, 'order_id': order_id, 'currency_id': currency.id, 'virtual_amount': lock_virtual, 'info': info } lock = BalanceLock(**lock_data) balance.real_amount -= lock_real balance.virtual_amount -= lock_virtual balance.locked_amount += lock_real + lock_virtual mapping.update(curs, balance) trans = Transaction(**trans_data) mapping.insert(curs, lock) mapping.insert(curs, trans) return response_ok(transaction_id=trans.id, lock_id=lock.id)
def viewer(lock): currency = currs_id_idx[lock.currency_id] lock_info = deserialize_field(lock.to_dict(), 'serialized_info', 'info') return { 'id': lock.id, 'user_id': lock.user_id, 'balance_id': lock.balance_id, 'currency_code': currency.code, 'creation_date': '%s' % lock.creation_date, 'real_amount': '%s' % cents_to_decimal(currency, lock.real_amount), 'virtual_amount': '%s' % cents_to_decimal(currency, lock.virtual_amount), 'order_id': lock.order_id, 'info': lock_info['info'], }
def _make_income_transaction(self, curs, data, session, transaction_type): balance = self._get_active_balance(session, curs, data) currs_id_idx = self._get_currs_idx(curs, 'id') currency = currs_id_idx[balance.currency_id] amount_dec = Decimal(data['amount']) amount = decimal_to_cents(currency, amount_dec) enrolled_amount_dec = cents_to_decimal(currency, amount) if amount < 0: amount *= -1 trans_data = {'environment_id': session.environment_id, 'user_id': balance.user_id, 'balance_id': balance.id, 'currency_code': currency.code, 'real_amount': 0, 'virtual_amount': 0, 'type': transaction_type, 'info': data.get('info', {})} if transaction_type == 'receipt': balance.real_amount += amount trans_data['real_amount'] = enrolled_amount_dec elif transaction_type == 'bonus': balance.virtual_amount += amount trans_data['virtual_amount'] = enrolled_amount_dec else: raise HelixbillingError('Unhandled income transaction type: %s' % transaction_type) mapping.update(curs, balance) trans = Transaction(**trans_data) mapping.insert(curs, trans) return trans.id
def test_negative_cents_to_decimal(self): currs_code_idx = self._get_currencies_idx() currencies = {'USD': 100} amounts = [-6, -86, -13000, -53001, -1113036, -3001, -13359] expects = { 'USD': ['-0.06', '-0.86', '-130.0', '-530.01', '-11130.36', '-30.01', '-133.59'], } for code, cent_factor in currencies.items(): db_currency = currs_code_idx[code] self.assertEqual(cent_factor, db_currency.cent_factor) actual = [cents_to_decimal(db_currency, amount) for amount in amounts] self.assertEqual(map(Decimal, expects[db_currency.code]), actual)
def lock(self, data, session, curs=None): balance = self._get_active_balance(session, curs, data) currs_id_idx = self._get_currs_idx(curs, 'id') currency = currs_id_idx[balance.currency_id] lock_amount_dec = Decimal(data['amount']) lock_amount = decimal_to_cents(currency, lock_amount_dec) if lock_amount < 0: lock_amount *= -1 locking_order = data['locking_order'] amounts_to_lock = compute_locks(balance, lock_amount, locking_order) lock_real = amounts_to_lock.get('real_amount', 0) lock_virtual = amounts_to_lock.get('virtual_amount', 0) order_id = data['order_id'] info = data.get('info', {}) info['locking_order'] = locking_order trans_data = {'environment_id': session.environment_id, 'user_id': balance.user_id, 'balance_id': balance.id, 'currency_code': currency.code, 'type': 'lock', 'real_amount': cents_to_decimal(currency, lock_real), 'virtual_amount': cents_to_decimal(currency, lock_virtual), 'order_id': order_id, 'info': info} lock_data = {'environment_id': session.environment_id, 'user_id': balance.user_id, 'balance_id': balance.id, 'real_amount': lock_real, 'locking_order': locking_order, 'order_id': order_id, 'currency_id': currency.id, 'virtual_amount': lock_virtual, 'info': info} lock = BalanceLock(**lock_data) balance.real_amount -= lock_real balance.virtual_amount -= lock_virtual balance.locked_amount += lock_real + lock_virtual mapping.update(curs, balance) trans = Transaction(**trans_data) mapping.insert(curs, lock) mapping.insert(curs, trans) return response_ok(transaction_id=trans.id, lock_id=lock.id)
def test_cents_to_decimal(self): currs_code_idx = self._get_currencies_idx() currencies = {'TND': 1000, 'USD': 100, 'CNY': 10, 'MRO': 5, 'JPY': 1} amounts = [6, 86, 13000, 53001, 1113036, 3001, 13359] expects = { 'TND': ['0.006', '0.086', '13.0', '53.001', '1113.036', '3.001', '13.359'], 'USD': ['0.06', '0.86', '130.0', '530.01', '11130.36', '30.01', '133.59'], 'CNY': ['0.6', '8.6', '1300', '5300.1', '111303.6', '300.1', '1335.9'], 'MRO': ['1.1', '17.1', '2600', '10600.1', '222607.1', '600.1', '2671.4'], 'JPY': ['6', '86', '13000', '53001', '1113036', '3001', '13359'], } for code, cent_factor in currencies.items(): db_currency = currs_code_idx[code] self.assertEqual(cent_factor, db_currency.cent_factor) actual = [cents_to_decimal(db_currency, amount) for amount in amounts] self.assertEqual(map(Decimal, expects[db_currency.code]), actual)
def _make_income_transaction(self, curs, data, session, transaction_type): balance = self._get_active_balance(session, curs, data) currs_id_idx = self._get_currs_idx(curs, 'id') currency = currs_id_idx[balance.currency_id] amount_dec = Decimal(data['amount']) amount = decimal_to_cents(currency, amount_dec) enrolled_amount_dec = cents_to_decimal(currency, amount) if amount < 0: amount *= -1 trans_data = { 'environment_id': session.environment_id, 'user_id': balance.user_id, 'balance_id': balance.id, 'currency_code': currency.code, 'real_amount': 0, 'virtual_amount': 0, 'type': transaction_type, 'info': data.get('info', {}) } if transaction_type == 'receipt': balance.real_amount += amount trans_data['real_amount'] = enrolled_amount_dec elif transaction_type == 'bonus': balance.virtual_amount += amount trans_data['virtual_amount'] = enrolled_amount_dec else: raise HelixbillingError('Unhandled income transaction type: %s' % transaction_type) mapping.update(curs, balance) trans = Transaction(**trans_data) mapping.insert(curs, trans) return trans.id