def test__GgoComposer__build_batch__total_amount_exceeds_available_amount__should_raise_AmountUnavailable( datahub, transfer_amounts, retire_amounts): # -- Arrange ------------------------------------------------------------ sector = 'DK1' begin = datetime(2020, 1, 1, 0, 0, 0) ggo = Mock(amount=100, begin=begin, sector=sector, user_id=1) ggo.is_tradable.return_value = True ggo.is_expired.return_value = False datahub.get_consumption.return_value = Mock(measurement=Mock( sector=sector, begin=begin, amount=100, )) composer = GgoComposer(ggo=ggo, session=Mock()) composer.get_retired_amount = Mock() composer.get_retired_amount.return_value = 0 # -- Act + Assert ------------------------------------------------------- for transfer_amount in transfer_amounts: composer.add_transfer(user=Mock(), amount=transfer_amount) for retire_amount in retire_amounts: composer.add_retire(meteringpoint=Mock( user_id=1, type=MeteringPointType.CONSUMPTION), amount=retire_amount) with pytest.raises(composer.AmountUnavailable): composer.build_batch()
def test__GgoComposer__build_batch__multiple_retires_and_transfers__should_build_batch_with_one_SplitTransaction_and_multiple_RetireTransactions( datahub): # -- Arrange ------------------------------------------------------------ sector = 'DK1' begin = datetime(2020, 1, 1, 0, 0, 0) ggo = Mock(amount=100, begin=begin, sector=sector, stored=True, retired=False, locked=False, synchronized=True, user_id=1) ggo.is_tradable.return_value = True ggo.is_expired.return_value = False ggo.create_child.side_effect = lambda amount, user: Mock( amount=amount, user=user, begin=begin) user1 = Mock() user2 = Mock() meteringpoint1 = Mock(gsrn='GSRN1', user_id=1, type=MeteringPointType.CONSUMPTION) meteringpoint2 = Mock(gsrn='GSRN2', user_id=1, type=MeteringPointType.CONSUMPTION) measurement = Mock(sector=sector, begin=begin, amount=100, address='MEASUREMENT-ADDRESS') datahub.get_consumption.return_value = Mock(measurement=measurement) composer = GgoComposer(ggo=ggo, session=Mock()) composer.get_retired_amount = Mock() composer.get_retired_amount.return_value = 0 # -- Act ---------------------------------------------------------------- composer.add_transfer(user=user1, amount=15, reference='REF1') composer.add_transfer(user=user2, amount=30, reference='REF2') composer.add_retire(meteringpoint=meteringpoint1, amount=10) composer.add_retire(meteringpoint=meteringpoint2, amount=40) # Sum of transfers + retires = 95 (5 remaining) batch, recipients = composer.build_batch() # -- Assert ------------------------------------------------------------- assert len(recipients) == 3 assert len(batch.transactions) == 3 split = batch.transactions[0] retire1 = batch.transactions[1] retire2 = batch.transactions[2] # SplitTransaction assert type(split) is SplitTransaction assert len(split.targets) == 5 assert split.parent_ggo is ggo assert split.targets[0].ggo.user is user1 assert split.targets[0].ggo.amount == 15 assert split.targets[0].reference == 'REF1' assert split.targets[1].ggo.user is user2 assert split.targets[1].ggo.amount == 30 assert split.targets[1].reference == 'REF2' assert split.targets[2].ggo.user is ggo.user assert split.targets[2].ggo.amount == 5 assert split.targets[2].reference is None # RetireTransaction 1 assert type(retire1) is RetireTransaction assert retire1.begin == begin assert retire1.parent_ggo is split.targets[3].ggo assert retire1.parent_ggo.retire_gsrn == 'GSRN1' assert retire1.parent_ggo.retire_address == 'MEASUREMENT-ADDRESS' assert retire1.parent_ggo.amount == 10 assert retire1.meteringpoint is meteringpoint1 assert retire1.measurement_address == 'MEASUREMENT-ADDRESS' # RetireTransaction 2 assert type(retire2) is RetireTransaction assert retire2.begin == begin assert retire2.parent_ggo is split.targets[4].ggo assert retire2.parent_ggo.retire_gsrn == 'GSRN2' assert retire2.parent_ggo.retire_address == 'MEASUREMENT-ADDRESS' assert retire2.parent_ggo.amount == 40 assert retire2.meteringpoint is meteringpoint2 assert retire2.measurement_address == 'MEASUREMENT-ADDRESS'
def test__GgoComposer__build_batch__only_transfer__should_build_batch_and_add_remaining_to_current_owner( datahub, transfer_amounts, remaining_amount): """ :param list[int] transfer_amounts: :param int remaining_amount: """ # -- Arrange ------------------------------------------------------------ sector = 'DK1' begin = datetime(2020, 1, 1, 0, 0, 0) ggo = Mock(amount=100, begin=begin, sector=sector, stored=True, retired=False, locked=False, synchronized=True) ggo.is_tradable.return_value = True ggo.is_expired.return_value = False ggo.create_child.side_effect = lambda amount, user: Mock(amount=amount, user=user) datahub.get_consumption.return_value = Mock(measurement=Mock( sector=sector, begin=begin, amount=100, )) composer = GgoComposer(ggo=ggo, session=Mock()) composer.get_retired_amount = Mock() composer.get_retired_amount.return_value = 0 transfer_users = [ Mock(name=f'User {i}') for i in range(len(transfer_amounts)) ] # -- Act ---------------------------------------------------------------- for user, amount in zip(transfer_users, transfer_amounts): composer.add_transfer(user, amount) batch, recipients = composer.build_batch() # -- Assert ------------------------------------------------------------- assert len(batch.transactions) == 1 assert type(batch.transactions[0]) is SplitTransaction if remaining_amount > 0: assert len(recipients) == len(transfer_amounts) + 1 else: assert len(recipients) == len(transfer_amounts) recipients_dict = dict(recipients) # {User: Ggo} for i, (user, amount) in enumerate(zip(transfer_users, transfer_amounts)): assert user in recipients_dict assert recipients_dict[user].amount == amount assert batch.transactions[0].parent_ggo is ggo assert batch.transactions[0].targets[i].ggo.user is user assert batch.transactions[0].targets[i].ggo.amount == amount