def make_exchange(self, route, amount, fee, participant, status='succeeded', error='', vat=0): amount = amount if isinstance(amount, Money) else Money(amount, 'EUR') fee = fee if isinstance(fee, Money) else Money(fee, amount.currency) vat = vat if isinstance(vat, Money) else Money(vat, fee.currency) if not isinstance(route, ExchangeRoute): network = route currency = amount.currency if network == 'mango-cc' else None routes = ExchangeRoute.from_network(participant, network, currency=currency) if routes: route = routes[0] else: from .mangopay import MangopayHarness address = MangopayHarness.card_id if network == 'mango-cc' else -participant.id route = ExchangeRoute.insert(participant, network, address, 'chargeable', currency=currency) assert route e_id = record_exchange(self.db, route, amount, fee, vat, participant, 'pre').id record_exchange_result(self.db, e_id, -e_id, status, error, participant) return e_id
def test_cbor_serialization_of_Money_with_extra_attribute(self): expected = Money('0.01', 'EUR') expected.fuzzy = True actual = cbor.loads(cbor.dumps(expected)) assert expected.__dict__ == { 'amount': Decimal('0.01'), 'currency': 'EUR', 'fuzzy': True, } assert expected.__dict__ == actual.__dict__
def test_cbor_serialization_of_Money_with_extra_attribute(self): expected = Money('0.01', 'EUR') expected.fuzzy = True actual = cbor.loads(cbor.dumps(expected)) assert expected.__dict__ == { 'amount': Decimal('0.01'), 'currency': 'EUR', 'fuzzy': True, } assert expected.__dict__ == actual.__dict__
def fake_participant(db, kind=None): """Create a fake User. """ username = faker.first_name() + fake_text_id(3) kind = kind or random.choice(('individual', 'organization')) is_a_person = kind in ('individual', 'organization') try: p = _fake_thing( db, "participants", username=username, email=username+'@example.org', balance=Money('0.00', 'EUR'), hide_giving=is_a_person and (random.randrange(5) == 0), hide_receiving=is_a_person and (random.randrange(5) == 0), status='active', join_time=faker.date_time_this_year(), kind=kind, mangopay_user_id=username, _cast=True, ) except IntegrityError: return fake_participant(db) # Create wallet _fake_thing( db, "wallets", remote_id='-%i' % p.id, balance=p.balance, owner=p.id, remote_owner_id=p.mangopay_user_id, ) return p
def add_member(self, member, cursor=None): """Add a member to this team. """ if self.nmembers >= 149: raise MemberLimitReached if member.status != 'active': raise InactiveParticipantAdded self.set_take_for(member, Money(-1, member.main_currency), self, cursor=cursor)
def fake_tip(db, tipper, tippee): """Create a fake tip. """ period = random.choice(DONATION_PERIODS) limits = [l.amount for l in DONATION_LIMITS['EUR'][period]] periodic_amount = random_money_amount(*limits) amount = (periodic_amount * PERIOD_CONVERSION_RATES[period]).quantize(D_CENT) return _fake_thing( db, "tips", ctime=faker.date_time_this_year(), mtime=faker.date_time_this_month(), tipper=tipper.id, tippee=tippee.id, amount=Money(amount, 'EUR'), period=period, periodic_amount=Money(periodic_amount, 'EUR'), )
def compute_max_this_week(self, member_id, last_week, currency): """2x the member's take last week, or the member's take last week + the leftover, or last week's median take, or one currency unit (e.g. €1.00). """ nonzero_last_week = [a.convert(currency).amount for a in last_week.values() if a] member_last_week = last_week.get(member_id, Money.ZEROS[currency]).convert(currency) return max( member_last_week * 2, member_last_week + last_week.initial_leftover.convert(currency), Money(median(nonzero_last_week or (0,)), currency), TAKE_THROTTLING_THRESHOLD[currency] )
def test_convert_non_euro(self): original = Money('1.00', 'CHF') expected = Money('0.82', 'GBP') actual = self.db.one("SELECT convert(%s, %s)", (original, expected.currency)) assert expected == actual actual = original.convert(expected.currency) assert expected == actual original = Money('1.20', 'USD') expected = Money('125', 'JPY') actual = self.db.one("SELECT convert(%s, %s)", (original, expected.currency)) assert expected == actual actual = original.convert(expected.currency) assert expected == actual
def test_sign_in_through_donation_form(self): alice = self.make_participant('alice', accepted_currencies=None) extra = { 'amount': '10000', 'currency': 'KRW', 'period': 'weekly', 'form.repost': 'true' } r = self.sign_in(url='/~1/tip', extra=extra) assert r.code == 302, r.text assert r.headers[b'Location'].startswith( b'http://localhost/bob/giving/') bob = Participant.from_username('bob') tip = bob.get_tip_to(alice) assert tip.amount == Money('10000', 'KRW') assert bob.main_currency == 'KRW'
def cast_currency_amount(v, cursor): return None if v in (None, '(,)') else Money(*v[1:-1].split(','))
def USD(amount): return Money(amount, 'USD')
def JPY(amount): return Money(amount, 'JPY')
def EUR(amount): return Money(amount, 'EUR')
def test_sorting(self): amounts = [JPY('130'), EUR('99.58'), Money('79', 'KRW'), USD('35.52')] expected = sorted(amounts, key=lambda m: -m.convert('EUR').amount) actual = self.db.all("SELECT x FROM unnest(%s) x ORDER BY x DESC", (amounts, )) assert expected == actual
def KRW(amount): return Money(amount, 'KRW')
def test_rounding(self): assert Money('0.001', 'EUR').round() == Money('0.00', 'EUR') assert Money('0.009', 'EUR').round_down() == Money('0.00', 'EUR') assert Money('0.002', 'EUR').round_up() == Money('0.01', 'EUR') assert Money('0.1', 'JPY').round() == Money('0', 'JPY') assert Money('0.9', 'JPY').round_down() == Money('0', 'JPY') assert Money('0.2', 'JPY').round_up() == Money('1', 'JPY')
def test_cbor_serialization_of_Money(self): expected = Money('9999999999.99', 'EUR') actual = cbor.loads(cbor.dumps(expected)) assert expected == actual
def test_cbor_serialization_of_Money_with_extra_attribute(self): expected = Money('0.01', 'EUR', fuzzy=True) actual = cbor.loads(cbor.dumps(expected)) assert expected == actual assert expected.fuzzy == actual.fuzzy
def populate_db(website, num_participants=100, num_tips=200, num_teams=5, num_transfers=5000, num_communities=20): """Populate DB with fake data. """ db = website.db # Speed things up db.run(""" DO $$ BEGIN EXECUTE 'ALTER DATABASE '||current_database()||' SET synchronous_commit TO off'; END $$ """) print("Making Participants") participants = [] for i in range(num_participants): participants.append(fake_participant(db)) print("Making Teams") teams = [] for i in range(num_teams): team = fake_participant(db, kind="group") # Add 1 to 3 members to the team members = random.sample(participants, random.randint(1, 3)) for p in members: team.add_member(p) teams.append(team) participants.extend(teams) print("Making Elsewheres") platforms = [p.name for p in website.platforms] for p in participants: # All participants get between 0 and 3 elsewheres num_elsewheres = random.randint(0, 3) for platform_name in random.sample(platforms, num_elsewheres): fake_elsewhere(db, p, platform_name) print("Making Communities") for i in range(num_communities): creator = random.sample(participants, 1) community = fake_community(db, creator[0]) members = random.sample(participants, random.randint(1, 3)) for p in members: p.upsert_community_membership(True, community.id) print("Making Tips") tips = [] for i in range(num_tips): tipper, tippee = random.sample(participants, 2) tips.append(fake_tip(db, tipper, tippee)) # Transfers min_amount, max_amount = [l.amount for l in DONATION_LIMITS['EUR']['weekly']] transfers = [] for i in range(num_transfers): tipper, tippee = random.sample(participants, 2) while tipper.kind in ('group', 'community') or \ tippee.kind in ('group', 'community'): tipper, tippee = random.sample(participants, 2) sys.stdout.write("\rMaking Transfers (%i/%i)" % (i+1, num_transfers)) sys.stdout.flush() amount = Money(random_money_amount(min_amount, max_amount), 'EUR') zero = amount.zero() ts = faker.date_time_this_year() fake_exchange(db, tipper, amount, zero, zero, (ts - datetime.timedelta(days=1))) transfers.append(fake_transfer(db, tipper, tippee, amount, ts)) print("") # Paydays # First determine the boundaries - min and max date min_date = min(min(x.ctime for x in tips), min(x.timestamp for x in transfers)) max_date = max(max(x.ctime for x in tips), max(x.timestamp for x in transfers)) # iterate through min_date, max_date one week at a time payday_counter = 1 date = min_date paydays_total = (max_date - min_date).days/7 + 1 while date < max_date: sys.stdout.write("\rMaking Paydays (%i/%i)" % (payday_counter, paydays_total)) sys.stdout.flush() payday_counter += 1 end_date = date + datetime.timedelta(days=7) week_tips = [x for x in tips if date < x.ctime < end_date] week_transfers = [x for x in transfers if date < x.timestamp < end_date] week_participants = [x for x in participants if x.join_time < end_date] actives = set() tippers = set() for xfers in week_tips, week_transfers: actives.update(x.tipper for x in xfers) actives.update(x.tippee for x in xfers) tippers.update(x.tipper for x in xfers) payday = { 'ts_start': date, 'ts_end': end_date, 'ntips': len(week_tips), 'ntransfers': len(week_transfers), 'nparticipants': len(week_participants), 'ntippers': len(tippers), 'nactive': len(actives), 'transfer_volume': MoneyBasket(x.amount for x in week_transfers), 'public_log': '', } _fake_thing(db, "paydays", **payday) date = end_date print("")