def __set__(self, obj, value): if isinstance(value, tuple): value = Money(amount=value[0], currency=value[1]) if isinstance(value, Money): obj.__dict__[self.field.name] = value.amount setattr(obj, self.currency_field_name, smart_unicode(value.currency)) elif isinstance(value, ExpressionNode): if isinstance(value.children[1], Money): value.children[1] = value.children[1].amount obj.__dict__[self.field.name] = value else: if value: value = str(value) obj.__dict__[self.field.name] = self.field.to_python(value)
def test_balance_simple(self): account1 = self.account() account2 = self.account() with db_transaction.atomic(): transaction = Transaction.objects.create() Leg.objects.create(transaction=transaction, account=account1, amount=Money(100, "EUR")) Leg.objects.create(transaction=transaction, account=account2, amount=Money(-100, "EUR")) self.assertEqual(account1.simple_balance(), Balance(100, "EUR")) self.assertEqual(account2.simple_balance(), Balance(-100, "EUR"))
def test_mul_float_warning(self): # This should be changed to TypeError exception after deprecation period is over. with warnings.catch_warnings(record=True) as warning_list: warnings.simplefilter("always") Money(amount="10") * 1.2 assert "Multiplying Money instances with floats is deprecated" in [ w.message.args[0] for w in warning_list ] with warnings.catch_warnings(record=True) as warning_list: warnings.simplefilter("always") 1.2 * Money(amount="10") assert "Multiplying Money instances with floats is deprecated" in [ w.message.args[0] for w in warning_list ]
def test_init_omit_currency(self): with pytest.raises( TypeError, match= r"__init__\(\) missing 1 required positional argument: 'currency'", ): Money(amount=self.one_million_decimal)
def to_python(self, value): if value is None: return None if isinstance(value, Money): return value if not isinstance(value, tuple) or len(value) != 2: raise Exception( "Invalid money input, expected amount and currency, got: %s." % value) amount, currency = value if not currency: raise forms.ValidationError(_('Currency is missing')) if not isinstance(currency, basestring): raise forms.ValidationError( _("Unrecognized currency type '%s'." % currency)) currency = currency.upper() if currency not in CURRENCIES or currency == DEFAULT_CURRENCY_CODE: raise forms.ValidationError( _("Unrecognized currency type '%s'." % currency)) amount = super(MoneyField, self).to_python(amount) return Money(amount=amount, currency=currency)
def setUp(self): super(VitepayUpdateApiTest, self).setUp() order_payment = VitepayOrderPaymentFactory.create( amount=Money(2000, XOF)) self.payment = VitepayPaymentFactory.create( order_id='opc-1', order_payment=order_payment)
def test_authorization_action(self, mock_post, create_hash, get_current_host): """ Play some posts that Vitepay might fire at us. """ self.init_projects() order = OrderFactory.create() DonationFactory.create(amount=Money(2000, XOF), order=order) order_payment = OrderPaymentFactory.create(payment_method='vitepayOrangemoney', order=order) adapter = VitepayPaymentAdapter(order_payment) authorization_action = adapter.get_authorization_action() data = { u"api_key": u"123", u"hash": u"123123", u"redirect": 0, u"payment": { u"description": u"Thanks for your donation!", u"order_id": u"opc-{}".format(order_payment.id), u"decline_url": u"https://onepercentclub.com/orders/{}/failed".format(order_payment.order.id), u"p_type": u"orange_money", u"country_code": u"ML", u"language_code": u"fr", u"amount_100": 200000, u"cancel_url": u"https://onepercentclub.com/orders/{}/failed".format(order_payment.order.id), u"currency_code": u"XOF", u"callback_url": u"https://onepercentclub.com/payments_vitepay/status_update/", u"return_url": u"https://onepercentclub.com/orders/{}/success".format(order_payment.order.id) } } self.assertEqual(mock_post.call_args[0][0], 'https://api.vitepay.com/v1/prod/payments') self.assertEqual(json.loads(mock_post.call_args[1]['data']), data) self.assertEqual(mock_post.call_args[1]['headers'], {'Content-Type': 'application/json'}) self.assertEqual(authorization_action['url'], 'https://vitepay.com/some-path-to-pay')
def Deserializer(stream_or_string, **options): """ Deserialize a stream or string of JSON data. """ if not isinstance(stream_or_string, (bytes, six.string_types)): stream_or_string = stream_or_string.read() if isinstance(stream_or_string, bytes): stream_or_string = stream_or_string.decode('utf-8') try: for obj in json.loads(stream_or_string): money_fields = {} fields = {} Model = _get_model(obj["model"]) for (field_name, field_value) in six.iteritems(obj['fields']): field = Model._meta.get_field(field_name) if isinstance(field, MoneyField) and field_value is not None: money_fields[field_name] = Money( field_value, obj['fields'][get_currency_field_name(field_name)]) else: fields[field_name] = field_value obj['fields'] = fields for obj in PythonDeserializer([obj], **options): for field, value in money_fields.items(): setattr(obj.object, field, value) yield obj except GeneratorExit: raise
def test_rmod_float_warning(self): # This should be changed to TypeError exception after deprecation period is over. with warnings.catch_warnings(record=True) as warning_list: warnings.simplefilter("always") 2.0 % Money(amount="10") assert ("Calculating percentages of Money instances using floats is deprecated" in [w.message.args[0] for w in warning_list])
def test_create_payment_redirect(self, charge, get_current_host): """ Test Flutterwave payment that turns to success without otp (one time pin) """ self.init_projects() order = OrderFactory.create() DonationFactory.create(amount=Money(150000, NGN), order=order) order_payment = OrderPaymentFactory.create( payment_method='flutterwaveCreditcard', order=order, integration_data=integration_data) adapter = FlutterwaveCreditcardPaymentAdapter(order_payment) authorization_action = adapter.get_authorization_action() self.assertEqual(adapter.payment.amount, '150000.00') self.assertEqual(adapter.payment.status, 'started') self.assertEqual(adapter.payment.transaction_reference, 'FLW005') self.assertEqual( authorization_action, { 'method': 'get', 'payload': { 'method': 'flutterwave-otp', 'text': redirect_response['data']['responsemessage'] }, 'type': 'redirect', 'url': redirect_response['data']['authurl'] })
def compress(self, data_list): try: if data_list[0] is None: return None except IndexError: return None return Money(*data_list[:2])
def get_open_orders(self, symbol='btc_usd'): params = {'order_id': -1, 'symbol': symbol} resp = self.okcoin_request('order_info.do', params) if resp and 'result' in resp and resp['result']: rawos = resp['orders'] else: raise ExchangeError( 'okcoin', 'unable to get open orders. response was %r' % resp) orders = [] for o in rawos: side = 'ask' if o['type'] == 'sell' else 'bid' orders.append( MyOrder(Money(o['price'], self.fiatcurrency), Money(o['amount']), side, self.name, str(o['order_id']))) return orders
def test_account_balance_after_out_of_order_ids(self): src = self.account() dst = self.account() # Take test_account_balance_after() as a reference test, # here we reverse the order of creation (to make the IDs go # backwards), and set the dates to force the order we want dst.transfer_to(src, Money(70, "EUR"), date="2000-01-15") src.transfer_to(dst, Money(50, "EUR"), date="2000-01-10") src.transfer_to(dst, Money(100, "EUR"), date="2000-01-05") src.transfer_to(dst, Money(100, "EUR"), date="2000-01-01") legs = Leg.objects.filter(account=dst).order_by("transaction__date").all() self.assertEqual(legs[0].account_balance_after(), Balance("100", "EUR")) self.assertEqual(legs[1].account_balance_after(), Balance("200", "EUR")) self.assertEqual(legs[2].account_balance_after(), Balance("250", "EUR")) self.assertEqual(legs[3].account_balance_after(), Balance("180", "EUR"))
def test_transfer_pos_to_pos(self): src = self.account(type=Account.TYPES.income) dst = self.account(type=Account.TYPES.income) src.transfer_to(dst, Money(100, 'EUR')) self.assertEqual(src.balance(), Balance(-100, 'EUR')) self.assertEqual(dst.balance(), Balance(100, 'EUR')) Account.validate_accounting_equation()
def test_arithmetic_operations_return_real_subclass_instance(self): """ Arithmetic operations on a subclass instance should return instances in the same subclass type. """ extended_money = ExtendedMoney(amount=2, currency=self.USD) operated_money = +extended_money assert type(extended_money) == type(operated_money) operated_money = -extended_money assert type(extended_money) == type(operated_money) operated_money = ExtendedMoney( amount=1, currency=self.USD) + ExtendedMoney(amount=1, currency=self.USD) assert type(extended_money) == type(operated_money) operated_money = ExtendedMoney(amount=3, currency=self.USD) - Money( amount=1, currency=self.USD) assert type(extended_money) == type(operated_money) operated_money = (1 * extended_money) assert type(extended_money) == type(operated_money) operated_money = (extended_money / 1) assert type(extended_money) == type(operated_money) operated_money = abs(ExtendedMoney(amount=-2, currency=self.USD)) assert type(extended_money) == type(operated_money) operated_money = (50 % ExtendedMoney(amount=4, currency=self.USD)) assert type(extended_money) == type(operated_money)
def setUp(self): super(InterswitchUpdateApiTest, self).setUp() self.order_payment = InterswitchOrderPaymentFactory.create( amount=Money(2000, XOF)) self.payment = InterswitchPaymentFactory.create( order_payment=self.order_payment)
def test_authorization_action(self, get_current_host, create_hash): """ Play some posts that Vitepay might fire at us. """ self.init_projects() order = OrderFactory.create() DonationFactory.create(amount=Money(2000, NGN), order=order) order_payment = OrderPaymentFactory.create(payment_method='interswitchWebpay', order=order) adapter = InterswitchPaymentAdapter(order_payment) authorization_action = adapter.get_authorization_action() redirect_url = 'https://onepercentclub.com/payments_interswitch/payment_response/{0}'.format(order_payment.id) data = { 'hash': '123123', 'product_id': '1234', 'site_redirect_url': redirect_url, 'local_date_time': None, 'txn_ref': '-{0}'.format(order_payment.id), 'cust_name': None, 'currency': '566', 'amount': 200000, 'pay_item_name': None, 'cust_id': None, 'pay_item_id': '123', 'site_name': 'testserver', 'cust_id_desc': None, 'cust_name_desc': None } self.assertEqual(authorization_action['url'], 'https://stageserv.interswitchng.com/test_paydirect/pay') self.assertEqual(authorization_action['payload'], data)
def test_create_success_payment(self, mock_client): """ Test Lipisha M-PESA payment that turns to success. """ authorization_action = self.adapter.get_authorization_action() self.assertEqual(int(self.adapter.payment.reference), self.order_payment.id) self.assertEqual(authorization_action, { 'payload': { 'account_number': '353535#{}'.format(self.order_payment.id), 'amount': 1500, 'business_number': '1234' }, 'type': 'process' }) # Now confirm the payment by user and have Lipisha send a success instance = mock_client.return_value instance.get_transactions.return_value = lipisha_success_response self.order_payment.integration_data = {} adapter = LipishaPaymentAdapter(self.order_payment) adapter.check_payment_status() authorization_action = adapter.get_authorization_action() self.assertEqual(adapter.payment.transaction_amount, '2500.0000') self.assertEqual(adapter.payment.status, 'settled') self.assertEqual(authorization_action, { "type": "success" }) # Donation amount should have been updated self.donation.refresh_from_db() self.assertEqual(self.donation.amount, Money(2500.00, 'KES'))
def test_multiple_donations(self): DonationFactory.create( order=OrderFactory.create(status=StatusDefinition.SUCCESS), fundraiser=self.fundraiser, amount=Money(100, 'USD') ) DonationFactory.create( order=OrderFactory.create(status=StatusDefinition.SUCCESS), fundraiser=self.fundraiser, amount=Money(100, 'EUR') ) self.assertEqual( self.fundraiser.amount_donated, Money(250, 'EUR') )
def test_transfer_to(self): account1 = self.account(type=Account.TYPES.income) account2 = self.account(type=Account.TYPES.income) transaction = account1.transfer_to(account2, Money(500, "EUR")) self.assertEqual(transaction.legs.count(), 2) self.assertEqual(account1.balance(), Balance(-500, "EUR")) self.assertEqual(account2.balance(), Balance(500, "EUR"))
def test_transfer_neg_to_neg(self): src = self.account(type=Account.TYPES.asset) dst = self.account(type=Account.TYPES.asset) src.transfer_to(dst, Money(100, "EUR")) self.assertEqual(src.balance(), Balance(-100, "EUR")) self.assertEqual(dst.balance(), Balance(100, "EUR")) Account.validate_accounting_equation()
def compress(self, data_list): if data_list: if not self.required and data_list[0] in self.empty_values: return None else: return Money(*data_list[:2]) return None
def __mul__(self, other): if isinstance(other, Money): raise TypeError('Cannot multiply two Money instances.') else: return Money( amount=(self.amount * Decimal(str(other))), currency=self.currency)
def _handle_orders(self, data): """Expected fields for Order import: completed (string<date>) user (string<email>) total (string) donations (array) project (string<title>) amount (float) reward (string<title>) name (string) """ try: user = Member.objects.get(email=data['user']) except (TypeError, Member.DoesNotExist): user = None completed = data['completed'] created = data['created'] total = data['total'] order, new = Order.objects.get_or_create(user=user, created=created, total=total, completed=completed) if new: if data['donations']: for don in data['donations']: try: project = Project.objects.get(slug=don['project']) except Project.DoesNotExist: print "Could not find project {0}".format( don['project']) continue try: reward = project.reward_set.get(title=don['reward']) except Reward.MultipleObjectsReturned: reward = project.reward_set.filter( title=don['reward']).all()[0] except (Reward.DoesNotExist, KeyError): reward = None donation = Donation.objects.create( project=project, reward=reward, name=don.get('name', '')[:199], order=order, amount=Money(don['amount'], 'EUR')) Donation.objects.filter(pk=donation.pk).update( created=created, updated=completed or created) order_payment = OrderPayment.objects.create(order=order) order_payment.payment_method = 'externalLegacy' OrderPayment.objects.filter(pk=order_payment.pk).update( created=created, status='settled', closed=completed) Order.objects.filter(pk=order.pk).update(created=created, status='success', updated=completed or created, confirmed=completed, completed=completed)
def totals_donated(self): confirmed = [StatusDefinition.PENDING, StatusDefinition.SUCCESS] donations = self.donation_set.filter(order__status__in=confirmed) totals = [ Money(data['amount__sum'], data['amount_currency']) for data in donations.values('amount_currency').annotate(Sum('amount')).order_by() ] return totals
def test_account_balance_after(self): src = self.account() dst = self.account() src.transfer_to(dst, Money(100, "EUR")) src.transfer_to(dst, Money(100, "EUR")) src.transfer_to(dst, Money(50, "EUR")) dst.transfer_to(src, Money(70, "EUR")) legs = Leg.objects.filter(account=dst).order_by("pk").all() self.assertEqual(legs[0].account_balance_after(), Balance("100", "EUR")) self.assertEqual(legs[1].account_balance_after(), Balance("200", "EUR")) self.assertEqual(legs[2].account_balance_after(), Balance("250", "EUR")) self.assertEqual(legs[3].account_balance_after(), Balance("180", "EUR"))
def test_str(self): one_million_pln = Money('1000000', 'PLN') if PYTHON2: assert str(one_million_pln) == 'PLN1,000,000.00' assert str(self.one_million_bucks) == 'USD1,000,000.00' else: assert str(one_million_pln) == '1,000,000.00 zł' assert str(self.one_million_bucks) == 'US$1,000,000.00'
def setUp(self): super(TestFundraiserAmountDonated, self).setUp() self.init_projects() campaign = ProjectPhase.objects.get(slug="campaign") project = ProjectFactory.create(status=campaign) self.fundraiser = FundraiserFactory(project=project, amount=Money(1000, 'EUR'))
def test_transfer_expense_to_liability(self): # This should perform the reverse action to that in the above test_transfer_liability_to_expense() src = self.account(type=Account.TYPES.expense) dst = self.account(type=Account.TYPES.liability) src.transfer_to(dst, Money(100, "EUR")) self.assertEqual(src.balance(), Balance(100, "EUR")) self.assertEqual(dst.balance(), Balance(100, "EUR")) Account.validate_accounting_equation()
def setUp(self): self.order = OrderFactory.create() self.donation = DonationFactory.create(amount=Money(1500, KES), order=self.order) self.order_payment = OrderPaymentFactory.create( payment_method='lipishaMpesa', order=self.order ) self.adapter = LipishaPaymentAdapter(self.order_payment)
def test_account_balance_after(self): src = self.account() dst = self.account() src.transfer_to(dst, Money(100, 'EUR')) src.transfer_to(dst, Money(100, 'EUR')) src.transfer_to(dst, Money(50, 'EUR')) dst.transfer_to(src, Money(70, 'EUR')) legs = Leg.objects.filter(account=dst).order_by('pk').all() self.assertEqual(legs[0].account_balance_after(), Balance('100', 'EUR')) self.assertEqual(legs[1].account_balance_after(), Balance('200', 'EUR')) self.assertEqual(legs[2].account_balance_after(), Balance('250', 'EUR')) self.assertEqual(legs[3].account_balance_after(), Balance('180', 'EUR'))
def test_round_context_override(self): import decimal x = Money(amount='2.5', currency=self.USD) assert x.round(0) == Money(amount=2, currency=self.USD) x = Money(amount='3.5', currency=self.USD) assert x.round(0) == Money(amount=4, currency=self.USD) with decimal.localcontext() as ctx: ctx.rounding = decimal.ROUND_HALF_UP x = Money(amount='2.5', currency=self.USD) assert x.round(0) == Money(amount=3, currency=self.USD) x = Money(amount='3.5', currency=self.USD) assert x.round(0) == Money(amount=4, currency=self.USD)
def test_round(self): x = Money(amount='1234.33569', currency=self.USD) assert x.round(-4) == Money(amount='0', currency=self.USD) assert x.round(-3) == Money(amount='1000', currency=self.USD) assert x.round(-2) == Money(amount='1200', currency=self.USD) assert x.round(-1) == Money(amount='1230', currency=self.USD) assert x.round(0) == Money(amount='1234', currency=self.USD) assert x.round(None) == Money(amount='1234', currency=self.USD) assert x.round(1) == Money(amount='1234.3', currency=self.USD) assert x.round(2) == Money(amount='1234.34', currency=self.USD) assert x.round(3) == Money(amount='1234.336', currency=self.USD) assert x.round(4) == Money(amount='1234.3357', currency=self.USD)
def test_get_sub_unit(self): m = Money(amount=123, currency=self.USD) assert m.get_amount_in_sub_unit() == 12300