コード例 #1
0
ファイル: CreditTrade.py プロジェクト: kuanfandevops/tfrs
    def approve(self, request, pk=None):
        """
        Marks the Credit Trade as Approved
        Transfers the Credits
        Then, marks the Credit Trade as Completed
        """
        credit_trade = self.get_object()
        credit_trade.trade_effective_date = datetime.date.today()
        previous_state = credit_trade

        if credit_trade.compliance_period_id is None:
            credit_trade.compliance_period_id = \
                CreditTradeService.get_compliance_period_id(credit_trade)

        serializer = self.get_serializer(credit_trade, data=request.data)
        serializer.is_valid(raise_exception=True)

        completed_credit_trade = CreditTradeService.approve(
            credit_trade, request.user
        )
        serializer = self.get_serializer(completed_credit_trade)

        CreditTradeService.dispatch_notifications(previous_state,
                                                  completed_credit_trade)

        return Response(serializer.data, status=status.HTTP_200_OK)
コード例 #2
0
    def test_validate_credit(self):
        credit_trade_status, created = CreditTradeStatus.objects.get_or_create(
            status='Approved')

        credit_trade_type, created = CreditTradeType.objects.get_or_create(
            the_type='Sell')

        credit_trade_zero_reason, created = CreditTradeZeroReason.objects \
            .get_or_create(reason='Other', display_order=2)

        CreditTrade.objects.create(
            status=credit_trade_status,
            initiator=self.user_2.organization,
            respondent=self.user_3.organization,
            type=credit_trade_type,
            number_of_credits=1000000000,
            fair_market_value_per_credit=0,
            zero_reason=credit_trade_zero_reason,
            trade_effective_date=datetime.datetime.today().strftime(
                '%Y-%m-%d'))

        credit_trades = CreditTrade.objects.filter(
            status_id=credit_trade_status.id)

        with self.assertRaises(PositiveIntegerException):
            CreditTradeService.validate_credits(credit_trades)
コード例 #3
0
    def test_validate_credit_success(self):
        """
        As a government user, I should be able to validate approved credit
        transfers:
        It should raise an exception if it sees any fuel suppliers with
        insufficient funds
        This test is similar to the one above, but should succeed as we're
        going to allocate the right amount of credits this time
        """
        credit_trades = []

        # Award Test 1 with 1000 credits (new organizations start
        # with 0 credits)
        # (Please note in most cases we should use a different type
        # but to reduce the number of things to keep track, lets just
        # transfer from organization: 1 (BC Government))
        credit_trades.append(
            CreditTrade.objects.create(
                status=self.statuses['recorded'],
                initiator=self.users['gov_analyst'].organization,
                respondent=self.organizations['from'],
                type=self.credit_trade_types['sell'],
                number_of_credits=1000,
                fair_market_value_per_credit=0,
                zero_reason=self.zero_reason['other'],
                trade_effective_date=datetime.datetime.today().strftime(
                    '%Y-%m-%d')))

        # Transfer 500 from Test 1 to Test 2
        credit_trades.append(
            CreditTrade.objects.create(
                status=self.statuses['recorded'],
                initiator=self.organizations['from'],
                respondent=self.organizations['to'],
                type=self.credit_trade_types['sell'],
                number_of_credits=500,
                fair_market_value_per_credit=0,
                zero_reason=self.zero_reason['other'],
                trade_effective_date=datetime.datetime.today().strftime(
                    '%Y-%m-%d')))

        # Transfer 300 from Test 1 to Test 2
        credit_trades.append(
            CreditTrade.objects.create(
                status=self.statuses['recorded'],
                initiator=self.organizations['from'],
                respondent=self.organizations['to'],
                type=self.credit_trade_types['sell'],
                number_of_credits=300,
                fair_market_value_per_credit=0,
                zero_reason=self.zero_reason['other'],
                trade_effective_date=datetime.datetime.today().strftime(
                    '%Y-%m-%d')))

        # no exceptions should be raised
        CreditTradeService.validate_credits(credit_trades)
コード例 #4
0
ファイル: CreditTrade.py プロジェクト: NickPhura/tfrs
    def perform_update(self, serializer):
        previous_state = self.get_object()
        credit_trade = serializer.save()
        CreditTradeService.create_history(credit_trade, False)

        status_cancelled = CreditTradeStatus.objects.get(status="Cancelled")

        if serializer.data['status'] != status_cancelled.id:
            CreditTradeService.dispatch_notifications(previous_state,
                                                      credit_trade)
コード例 #5
0
    def batch_process(self, request):
        status_approved = CreditTradeStatus.objects \
                                           .get(status="Approved")

        credit_trades = CreditTrade.objects.filter(
            status_id=status_approved.id)

        for credit_trade in credit_trades:
            CreditTradeService.approve(credit_trade)

        return Response(None, status=status.HTTP_200_OK)
コード例 #6
0
    def has_permission(self, request, view):
        """Check permissions When an object does not yet exist (POST)"""

        # Fallback to has_object_permission unless it's a POST
        if request.method != 'POST':
            return True

        # Need this information to make a decision
        if not (('privileged_access' in request.data) and ('credit_trade' in request.data)):
            return False

        credit_trade = request.data['credit_trade']
        privileged_access = request.data['privileged_access']

        # Check if the user is a party to this credit_trade (or Government)
        # using CreditTradeService logic
        found = CreditTradeService.get_organization_credit_trades(request.user.organization) \
            .filter(id=credit_trade).first()

        if not found:
            return False

        return CreditTradeCommentPermissions.user_can_comment(
            request.user,
            found,
            privileged_access
        )
コード例 #7
0
    def batch_process(self, request):
        status_approved = CreditTradeStatus.objects \
                                           .get(status="Approved")

        credit_trades = CreditTrade.objects.filter(
            status_id=status_approved.id).order_by('id')

        CreditTradeService.validate_credits(credit_trades)

        for credit_trade in credit_trades:
            credit_trade.update_user_id = request.user.id
            CreditTradeService.approve(credit_trade)

        return Response(
            {"message": "Approved Credit Transactions have been processed."},
            status=status.HTTP_200_OK)
コード例 #8
0
    def approve(self, request, pk=None):

        credit_trade = self.get_object()

        completed_credit_trade = CreditTradeService.approve(credit_trade)
        serializer = self.get_serializer(completed_credit_trade)

        return Response(serializer.data, status=status.HTTP_200_OK)
コード例 #9
0
    def test_validate_credit_complex(self):
        """
        As a government user, I should be able to validate recorded credit
        transfers:
        It should raise an exception if it sees any fuel suppliers with
        insufficient funds
        This is a slightly more complex test where we have multi credit
        trades with new organizations that bounces the number of credits
        up and down
        """

        initial_balance = OrganizationBalance.objects.get(
            organization_id=self.organizations['from'].id,
            expiration_date=None).validated_credits

        # Transfer initial balance from Test 1 to Test 2
        CreditTrade.objects.create(
            status=self.statuses['recorded'],
            initiator=self.organizations['from'],
            respondent=self.organizations['to'],
            type=self.credit_trade_types['sell'],
            number_of_credits=initial_balance,
            fair_market_value_per_credit=0,
            zero_reason=self.zero_reason['other'],
            trade_effective_date=datetime.datetime.today().strftime(
                '%Y-%m-%d'))

        # Transfer 1 from Test 1 to Test 2
        CreditTrade.objects.create(
            status=self.statuses['recorded'],
            initiator=self.organizations['from'],
            respondent=self.organizations['to'],
            type=self.credit_trade_types['sell'],
            number_of_credits=1,
            fair_market_value_per_credit=0,
            zero_reason=self.zero_reason['other'],
            trade_effective_date=datetime.datetime.today().strftime(
                '%Y-%m-%d'))

        credit_trades = CreditTrade.objects.filter(
            status_id=self.statuses['recorded'].id)

        # this should now raise an exception since we tried transferring
        # 1200 credits when only 1000 are available
        with self.assertRaises(PositiveIntegerException):
            CreditTradeService.validate_credits(credit_trades)
コード例 #10
0
ファイル: CreditTrade.py プロジェクト: NickPhura/tfrs
 def get_queryset(self):
     """
     This view should return a list of all the purchases
     for the currently authenticated user.
     """
     user = self.request.user
     return CreditTradeService.get_organization_credit_trades(
         user.organization)
コード例 #11
0
    def approve(self, request, pk=None):
        credit_trade = self.get_object()
        credit_trade.trade_effective_date = datetime.date.today()

        serializer = self.get_serializer(credit_trade, data=request.data)
        serializer.is_valid(raise_exception=True)

        completed_credit_trade = CreditTradeService.approve(credit_trade)
        serializer = self.get_serializer(completed_credit_trade)

        return Response(serializer.data, status=status.HTTP_200_OK)
コード例 #12
0
    def test_validate_credit(self):
        """
        As a government user, I should be able to validate recorded credit
        transfers:
        It should raise an exception if it sees any fuel suppliers with
        insufficient funds
        """
        CreditTrade.objects.create(
            status=self.statuses['recorded'],
            initiator=self.users['fs_user_2'].organization,
            respondent=self.users['fs_user_3'].organization,
            type=self.credit_trade_types['sell'],
            number_of_credits=1000000000,
            fair_market_value_per_credit=0,
            zero_reason=self.zero_reason['other'],
            trade_effective_date=datetime.datetime.today().strftime(
                '%Y-%m-%d'))

        credit_trades = CreditTrade.objects.filter(
            status_id=self.statuses['recorded'].id)

        with self.assertRaises(PositiveIntegerException):
            CreditTradeService.validate_credits(credit_trades)
コード例 #13
0
    def test_get_organization_credit_trades_gov(self):
        """
        As a government user
        I shouldn't see drafts unless I'm the initiator
        I shouldn't see cancelled transfers as they're considered (deleted)
        """
        # the function shouldn't see this as it's only a draft and the
        # initiator is not government
        draft_credit_trade = CreditTrade.objects.create(
            status=self.statuses['draft'],
            initiator=self.organizations['from'],
            respondent=self.organizations['to'],
            type=self.credit_trade_types['sell'],
            number_of_credits=1000,
            fair_market_value_per_credit=1,
            zero_reason=None,
            trade_effective_date=datetime.datetime.today().strftime(
                '%Y-%m-%d'))

        # the function should see this as it's a draft from the government
        draft_credit_trade_from_gov = CreditTrade.objects.create(
            status=self.statuses['draft'],
            initiator=self.users['gov_analyst'].organization,
            respondent=self.organizations['to'],
            type=self.credit_trade_types['sell'],
            number_of_credits=1000,
            fair_market_value_per_credit=1,
            zero_reason=None,
            trade_effective_date=datetime.datetime.today().strftime(
                '%Y-%m-%d'))

        # the function should see this as it's approved
        approved_credit_trade = CreditTrade.objects.create(
            status=self.statuses['approved'],
            initiator=self.organizations['from'],
            respondent=self.organizations['to'],
            type=self.credit_trade_types['sell'],
            number_of_credits=1000,
            fair_market_value_per_credit=1,
            zero_reason=None,
            trade_effective_date=datetime.datetime.today().strftime(
                '%Y-%m-%d'))

        credit_trades = CreditTradeService.get_organization_credit_trades(
            self.users['gov_analyst'].organization)

        self.assertNotIn(draft_credit_trade, credit_trades)
        self.assertIn(draft_credit_trade_from_gov, credit_trades)
        self.assertIn(approved_credit_trade, credit_trades)
コード例 #14
0
    def has_permission(self, request, view):
        """Check permissions When an object does not yet exist (POST)"""

        if not request.user.has_perm('SIGN_CREDIT_TRANSFER'):
            return False

        if isinstance(request.data, list):
            to_check = request.data
        else:
            to_check = [request.data]

        if len(to_check) == 0:
            return False

        # Need this information to make a decision

        for obj in to_check:
            if 'credit_trade' in obj:
                credit_trade = obj['credit_trade']

                # Check if the user is a party to this credit_trade
                # (or Government) using CreditTradeService logic
                found = CreditTradeService.get_organization_credit_trades(
                    request.user.organization).filter(id=credit_trade).first()

                if not found:
                    return False

                if not SigningAuthorityConfirmationPermissions.user_can_sign(
                        request.user, found):
                    return False
            elif 'compliance_report' in obj:
                # check that the compliance report does exist and the user can
                # sign it
                compliance_report = obj['compliance_report']

                found = ComplianceReport.objects.filter(
                    id=compliance_report,
                    organization=request.user.organization)

                if not found:
                    return False
            else:  # Neither credit trade or compliance report was provided
                return False

        return True
コード例 #15
0
    def has_permission(self, request, view):
        """Check permissions When an object does not yet exist (POST)"""

        if not request.user.has_perm('SIGN_CREDIT_TRANSFER'):
            return False

        if isinstance(request.data, list):
            to_check = request.data
        else:
            to_check = [request.data]

        if len(to_check) == 0:
            return False

        # Need this information to make a decision

        for obj in to_check:

            if 'credit_trade' not in obj:
                return False

            credit_trade = obj['credit_trade']

            # Check if the user is a party to this credit_trade (or Government)
            # using CreditTradeService logic
            found = CreditTradeService.get_organization_credit_trades(request.user.organization) \
                .filter(id=credit_trade).first()

            if not found:
                return False

            if not SigningAuthorityConfirmationPermissions.user_can_sign(
                    request.user, found):
                return False

        return True
コード例 #16
0
ファイル: CreditTrade.py プロジェクト: NickPhura/tfrs
    def batch_process(self, request):
        """
        Call the approve function on multiple Credit Trades
        """
        status_approved = CreditTradeStatus.objects \
                                           .get(status="Recorded")

        credit_trades = CreditTrade.objects.filter(
            status_id=status_approved.id).order_by('id')

        CreditTradeService.validate_credits(credit_trades)

        for credit_trade in credit_trades:
            credit_trade.update_user_id = request.user.id
            CreditTradeService.approve(credit_trade)
            CreditTradeService.dispatch_notifications(None, credit_trade)

        return Response(
            {"message": "Approved credit transactions have been processed."},
            status=status.HTTP_200_OK)
コード例 #17
0
 def perform_update(self, serializer):
     credit_trade = serializer.save()
     CreditTradeService.create_history(credit_trade, False)
コード例 #18
0
ファイル: CreditTrade.py プロジェクト: kuanfandevops/tfrs
    def validate(self, data):
        """
        Makes sure that the status the credit trade is being updated to
        is valid.
        There are certain states that should lock a credit trade from being
        modified.
        """
        request = self.context['request']
        available_statuses = []

        if self.instance.is_rescinded:
            raise serializers.ValidationError({
                'readOnly':
                "Cannot update a transaction that's already "
                "been rescinded."
            })

        if self.instance.status.status in [
                "Approved", "Cancelled", "Declined", "Refused"
        ]:
            raise serializers.ValidationError({
                'readOnly':
                "Cannot update a transaction that's already "
                "been `{}`.".format(self.instance.status.status)
            })

        # if the user is the respondent, they really shouldn't be modifying
        # other fields. So reset those to be sure that they weren't changed
        if self.instance.respondent == request.user.organization:
            orig_data = data
            data = {
                'compliance_period': self.instance.compliance_period,
                'fair_market_value_per_credit':
                self.instance.fair_market_value_per_credit,
                'initiator': self.instance.initiator,
                'is_rescinded': bool(data.get('is_rescinded')),
                'number_of_credits': self.instance.number_of_credits,
                'respondent': self.instance.respondent,
                'status': data.get('status'),
                'type': self.instance.type,
                'update_user': request.user,
                'zero_reason': self.instance.zero_reason
            }

            # Preserve the comment, if they are making one
            if 'comment' in orig_data:
                data['comment'] = orig_data['comment']

        # if status is being modified, make sure the next state is valid
        if 'status' in request.data:
            credit_trade_status = data.get('status')

            if not data.get('is_rescinded') is True:
                available_statuses = CreditTradeService.get_allowed_statuses(
                    self.instance, request)

                allowed_statuses = list(
                    CreditTradeStatus.objects.filter(
                        status__in=available_statuses).only('id'))

                if credit_trade_status not in allowed_statuses:
                    raise serializers.ValidationError({
                        'invalidStatus':
                        "You do not have permission to set "
                        "the status to `{}`.".format(
                            credit_trade_status.status)
                    })

            if (credit_trade_status != self.instance.status
                    and data.get('is_rescinded') is True):
                raise serializers.ValidationError({
                    'invalidStatus':
                    "Cannot update status and rescind at the "
                    "same time."
                })

            will_create_a_comment = True if 'comment' in data \
                and data['comment'] is not None \
                and len(data['comment'].strip()) > 0 else False

            if credit_trade_status.status == 'Submitted':
                zero_reason = data.get('zero_reason')
                if zero_reason is not None and zero_reason.reason == 'Other':
                    if not (will_create_a_comment
                            or CreditTradeComment.objects.filter(
                                credit_trade_id=self.instance.id,
                                create_user__organization=request.user.
                                organization).exists()):
                        raise serializers.ValidationError({
                            'forbidden':
                            "Please provide an explanation in "
                            "the comments as to why the Credit "
                            "Transfer Proposal has a fair market "
                            "value of zero dollars per credit."
                        })

        if data.get('is_rescinded') is True:
            if request.user.organization not in [
                    self.instance.initiator, self.instance.respondent
            ]:
                raise serializers.ValidationError({
                    'forbidden':
                    "Cannot rescind unless organization is part "
                    "of the proposal."
                })

            if self.instance.status.status == 'Draft':
                raise serializers.ValidationError(
                    {'forbidden': "Cannot rescind a draft"})

            if (self.instance.status.status == 'Submitted'
                    and self.instance.respondent == request.user.organization):
                raise serializers.ValidationError({
                    'forbidden':
                    "Cannot rescind a proposed trade when you're "
                    " the respondent"
                })

        if data.get('fair_market_value_per_credit') is not None and \
                data.get('fair_market_value_per_credit') > 0 and \
                data.get('zero_reason') is not None:
            raise serializers.ValidationError({
                'zeroDollarReason':
                "Zero dollar reason supplied but this "
                "trade has a non-zero value-per-credit"
            })

        if data.get('fair_market_value_per_credit') == 0 and \
                data.get('zero_reason') is None:
            allowed_types = list(
                CreditTradeType.objects.filter(the_type__in=[
                    "Credit Validation", "Credit Reduction", "Part 3 Award"
                ]).only('id'))

            credit_trade_type = data.get('type')

            if credit_trade_type not in allowed_types:
                raise serializers.ValidationError({
                    'zeroDollarReason':
                    "Please select a reason as to "
                    "why the Credit Transfer Proposal "
                    "has a fair market value of zero "
                    "dollars per credit. "
                })

        # If the type is a sell, make sure that the organization
        # selling has enough credits, before they try to save the draft
        # or propose
        # If the type is buy, make sure the organization the credit is
        # coming from has enough credits before they can accept the proposal
        balance = request.user.organization.organization_balance[
            'validated_credits']

        buy_type = CreditTradeType.objects.get(the_type="Buy")

        sell_type = CreditTradeType.objects.get(the_type="Sell")

        if 'type' in data:
            credit_trade_type = data.get('type')
        else:
            credit_trade_type = self.instance.type

        if 'number_of_credits' in data:
            number_of_credits = data.get('number_of_credits')
        else:
            number_of_credits = self.instance.number_of_credits

        previous_state = CreditTrade.objects.get(id=self.instance.id)

        if 'comment' in data and data['comment'] is not None and \
                len(data['comment'].strip()) > 0:
            if 'ADD_COMMENT' not in CreditTradeCommentActions.\
                    available_comment_actions(request, previous_state):
                raise serializers.ValidationError(
                    "Cannot add a comment in this state")

        accepted_status = CreditTradeStatus.objects.get(status="Accepted")
        draft_propose_statuses = list(
            CreditTradeStatus.objects.filter(
                status__in=["Draft", "Submitted"]).only('id'))

        if (self.instance.initiator == request.user.organization and
                credit_trade_status in draft_propose_statuses and
                credit_trade_type == sell_type) or \
            (self.instance.respondent == request.user.organization and
             credit_trade_status == accepted_status and
             credit_trade_type == buy_type):
            if balance < number_of_credits:
                raise serializers.ValidationError({
                    'insufficientCredits':
                    "{} does not have enough credits "
                    "for the proposal.".format(request.user.organization.name)
                })

        return data
コード例 #19
0
    def test_get_organization_credit_trades_fuel_supplier(self):
        completed_status, created = CreditTradeStatus.objects.get_or_create(
            status='Completed')

        cancelled_status, created = CreditTradeStatus.objects.get_or_create(
            status='Cancelled')

        draft_status, created = CreditTradeStatus.objects.get_or_create(
            status='Draft')

        submitted_status, created = CreditTradeStatus.objects.get_or_create(
            status='Submitted')

        credit_trade_type, created = CreditTradeType.objects.get_or_create(
            the_type='Sell')

        test_organization_1 = Organization.objects.create(name="Test 1",
                                                          actions_type_id=1,
                                                          status_id=1)
        test_organization_2 = Organization.objects.create(name="Test 2",
                                                          actions_type_id=1,
                                                          status_id=1)
        test_organization_3 = Organization.objects.create(name="Test 3",
                                                          actions_type_id=1,
                                                          status_id=1)

        # the function shouldn't see this as it's only a draft and the
        # initiator is not fuel_supplier
        # (even though the fuel supplier is the respondent)
        draft_credit_trade = CreditTrade.objects.create(
            status=draft_status,
            initiator=test_organization_2,
            respondent=test_organization_1,
            type=credit_trade_type,
            number_of_credits=1000,
            fair_market_value_per_credit=1,
            zero_reason=None,
            trade_effective_date=datetime.datetime.today().strftime(
                '%Y-%m-%d'))

        # the function should see this as it's a draft from the fuel supplier
        draft_credit_trade_from_fuel_supplier = CreditTrade.objects.create(
            status=draft_status,
            initiator=test_organization_1,
            respondent=test_organization_2,
            type=credit_trade_type,
            number_of_credits=1000,
            fair_market_value_per_credit=1,
            zero_reason=None,
            trade_effective_date=datetime.datetime.today().strftime(
                '%Y-%m-%d'))

        # the function shouldn't see this as it's a submitted transaction
        # not involving the fuel supplier
        submitted_credit_trade = CreditTrade.objects.create(
            status=submitted_status,
            initiator=test_organization_2,
            respondent=test_organization_3,
            type=credit_trade_type,
            number_of_credits=1000,
            fair_market_value_per_credit=1,
            zero_reason=None,
            trade_effective_date=datetime.datetime.today().strftime(
                '%Y-%m-%d'))

        # the function should see this as it's a submitted transaction
        # involving the fuel supplier
        submitted_credit_trade_as_respondent = CreditTrade.objects.create(
            status=submitted_status,
            initiator=test_organization_2,
            respondent=test_organization_1,
            type=credit_trade_type,
            number_of_credits=1000,
            fair_market_value_per_credit=1,
            zero_reason=None,
            trade_effective_date=datetime.datetime.today().strftime(
                '%Y-%m-%d'))

        # the function should see this as it's completed
        completed_credit_trade = CreditTrade.objects.create(
            status=completed_status,
            initiator=test_organization_1,
            respondent=test_organization_2,
            type=credit_trade_type,
            number_of_credits=1000,
            fair_market_value_per_credit=1,
            zero_reason=None,
            trade_effective_date=datetime.datetime.today().strftime(
                '%Y-%m-%d'))

        credit_trades = CreditTradeService.get_organization_credit_trades(
            test_organization_1)

        self.assertNotIn(draft_credit_trade, credit_trades)
        self.assertIn(draft_credit_trade_from_fuel_supplier, credit_trades)
        self.assertNotIn(submitted_credit_trade, credit_trades)
        self.assertIn(submitted_credit_trade_as_respondent, credit_trades)
        self.assertIn(completed_credit_trade, credit_trades)
コード例 #20
0
    def test_get_organization_credit_trades_gov(self):
        completed_status, created = CreditTradeStatus.objects.get_or_create(
            status='Completed')

        cancelled_status, created = CreditTradeStatus.objects.get_or_create(
            status='Cancelled')

        draft_status, created = CreditTradeStatus.objects.get_or_create(
            status='Draft')

        credit_trade_type, created = CreditTradeType.objects.get_or_create(
            the_type='Sell')

        from_organization = Organization.objects.create(name="Test 1",
                                                        actions_type_id=1,
                                                        status_id=1)
        to_organization = Organization.objects.create(name="Test 2",
                                                      actions_type_id=1,
                                                      status_id=1)

        # the function shouldn't see this as it's only a draft and the
        # initiator is not government
        draft_credit_trade = CreditTrade.objects.create(
            status=draft_status,
            initiator=from_organization,
            respondent=to_organization,
            type=credit_trade_type,
            number_of_credits=1000,
            fair_market_value_per_credit=1,
            zero_reason=None,
            trade_effective_date=datetime.datetime.today().strftime(
                '%Y-%m-%d'))

        # the function should see this as it's a draft from the government
        draft_credit_trade_from_gov = CreditTrade.objects.create(
            status=draft_status,
            initiator=self.gov_user.organization,
            respondent=to_organization,
            type=credit_trade_type,
            number_of_credits=1000,
            fair_market_value_per_credit=1,
            zero_reason=None,
            trade_effective_date=datetime.datetime.today().strftime(
                '%Y-%m-%d'))

        # the function should see this as it's completed
        completed_credit_trade = CreditTrade.objects.create(
            status=completed_status,
            initiator=from_organization,
            respondent=to_organization,
            type=credit_trade_type,
            number_of_credits=1000,
            fair_market_value_per_credit=1,
            zero_reason=None,
            trade_effective_date=datetime.datetime.today().strftime(
                '%Y-%m-%d'))

        credit_trades = CreditTradeService.get_organization_credit_trades(
            self.gov_user.organization)

        self.assertNotIn(draft_credit_trade, credit_trades)
        self.assertIn(draft_credit_trade_from_gov, credit_trades)
        self.assertIn(completed_credit_trade, credit_trades)
コード例 #21
0
    def test_validate_credit_success(self):

        credit_trades = []

        credit_trade_status, created = CreditTradeStatus.objects.get_or_create(
            status='Approved')

        credit_trade_type, created = CreditTradeType.objects.get_or_create(
            the_type='Sell')

        credit_trade_zero_reason, created = CreditTradeZeroReason.objects \
            .get_or_create(reason='Other', display_order=2)

        from_organization = Organization.objects.create(name="Test 1",
                                                        actions_type_id=1,
                                                        status_id=1)
        to_organization = Organization.objects.create(name="Test 2",
                                                      actions_type_id=1,
                                                      status_id=1)

        # Award Test 1 with 1000 credits (new organizations start
        # with 0 credits)
        # (Please note in most cases we should use a different type
        # but to reduce the number of things to keep track, lets just
        # transfer from organization: 1 (BC Government))
        credit_trades.append(
            CreditTrade.objects.create(
                status=credit_trade_status,
                initiator=self.gov_user.organization,
                respondent=from_organization,
                type=credit_trade_type,
                number_of_credits=1000,
                fair_market_value_per_credit=0,
                zero_reason=credit_trade_zero_reason,
                trade_effective_date=datetime.datetime.today().strftime(
                    '%Y-%m-%d')))

        # Transfer 500 from Test 1 to Test 2
        credit_trades.append(
            CreditTrade.objects.create(
                status=credit_trade_status,
                initiator=from_organization,
                respondent=to_organization,
                type=credit_trade_type,
                number_of_credits=500,
                fair_market_value_per_credit=0,
                zero_reason=credit_trade_zero_reason,
                trade_effective_date=datetime.datetime.today().strftime(
                    '%Y-%m-%d')))

        # Transfer 300 from Test 1 to Test 2
        credit_trades.append(
            CreditTrade.objects.create(
                status=credit_trade_status,
                initiator=from_organization,
                respondent=to_organization,
                type=credit_trade_type,
                number_of_credits=300,
                fair_market_value_per_credit=0,
                zero_reason=credit_trade_zero_reason,
                trade_effective_date=datetime.datetime.today().strftime(
                    '%Y-%m-%d')))

        # no exceptions should be raised
        CreditTradeService.validate_credits(credit_trades)
コード例 #22
0
    def test_validate_credit_complex(self):
        credit_trade_status, created = CreditTradeStatus.objects.get_or_create(
            status='Approved')

        credit_trade_type, created = CreditTradeType.objects.get_or_create(
            the_type='Sell')

        credit_trade_zero_reason, created = CreditTradeZeroReason.objects \
            .get_or_create(reason='Other', display_order=2)

        from_organization = Organization.objects.create(name="Test 1",
                                                        actions_type_id=1,
                                                        status_id=1)
        to_organization = Organization.objects.create(name="Test 2",
                                                      actions_type_id=1,
                                                      status_id=1)

        # Award Test 1 with 1000 credits (new organizations start
        # with 0 credits)
        # (Please note in most cases we should use a different type
        # but to reduce the number of things to keep track, lets just
        # transfer from organization: 1 (BC Government))
        CreditTrade.objects.create(
            status=credit_trade_status,
            initiator=self.gov_user.organization,
            respondent=from_organization,
            type=credit_trade_type,
            number_of_credits=1000,
            fair_market_value_per_credit=0,
            zero_reason=credit_trade_zero_reason,
            trade_effective_date=datetime.datetime.today().strftime(
                '%Y-%m-%d'))

        # Transfer 500 from Test 1 to Test 2
        CreditTrade.objects.create(
            status=credit_trade_status,
            initiator=from_organization,
            respondent=to_organization,
            type=credit_trade_type,
            number_of_credits=500,
            fair_market_value_per_credit=0,
            zero_reason=credit_trade_zero_reason,
            trade_effective_date=datetime.datetime.today().strftime(
                '%Y-%m-%d'))

        # Transfer 700 from Test 1 to Test 2
        CreditTrade.objects.create(
            status=credit_trade_status,
            initiator=from_organization,
            respondent=to_organization,
            type=credit_trade_type,
            number_of_credits=700,
            fair_market_value_per_credit=0,
            zero_reason=credit_trade_zero_reason,
            trade_effective_date=datetime.datetime.today().strftime(
                '%Y-%m-%d'))

        credit_trades = CreditTrade.objects.filter(
            status_id=credit_trade_status.id)

        # this should now raise an exception since we tried transferring
        # 1200 credits when only 1000 are available
        with self.assertRaises(PositiveIntegerException):
            CreditTradeService.validate_credits(credit_trades)
コード例 #23
0
    def test_get_organization_credit_trades_fuel_supplier(self):
        """
        As a fuel supplier
        I shouldn't see drafts unless I'm the initiator
        I shouldn't see cancelled transfers as they're considered (deleted)
        I shouldn't see submitted transfers unless I'm involved somehow
        """
        # the function shouldn't see this as it's only a draft and the
        # initiator is not fuel_supplier
        # (even though the fuel supplier is the respondent)
        draft_credit_trade = CreditTrade.objects.create(
            status=self.statuses['draft'],
            initiator=self.organizations['to'],
            respondent=self.organizations['from'],
            type=self.credit_trade_types['sell'],
            number_of_credits=1000,
            fair_market_value_per_credit=1,
            zero_reason=None,
            trade_effective_date=datetime.datetime.today().strftime(
                '%Y-%m-%d'))

        # the function should see this as it's a draft from the fuel supplier
        draft_from_fuel_supplier = CreditTrade.objects.create(
            status=self.statuses['draft'],
            initiator=self.organizations['from'],
            respondent=self.organizations['to'],
            type=self.credit_trade_types['sell'],
            number_of_credits=1000,
            fair_market_value_per_credit=1,
            zero_reason=None,
            trade_effective_date=datetime.datetime.today().strftime(
                '%Y-%m-%d'))

        # the function shouldn't see this as it's a submitted transaction
        # not involving the fuel supplier
        submitted_credit_trade = CreditTrade.objects.create(
            status=self.statuses['submitted'],
            initiator=self.organizations['to'],
            respondent=self.users['fs_user_3'].organization,
            type=self.credit_trade_types['sell'],
            number_of_credits=1000,
            fair_market_value_per_credit=1,
            zero_reason=None,
            trade_effective_date=datetime.datetime.today().strftime(
                '%Y-%m-%d'))

        # the function should see this as it's a submitted transaction
        # involving the fuel supplier
        credit_trade_as_respondent = CreditTrade.objects.create(
            status=self.statuses['submitted'],
            initiator=self.organizations['to'],
            respondent=self.organizations['from'],
            type=self.credit_trade_types['sell'],
            number_of_credits=1000,
            fair_market_value_per_credit=1,
            zero_reason=None,
            trade_effective_date=datetime.datetime.today().strftime(
                '%Y-%m-%d'))

        # the function should see this as it's approved
        approved_credit_trade = CreditTrade.objects.create(
            status=self.statuses['approved'],
            initiator=self.organizations['from'],
            respondent=self.organizations['to'],
            type=self.credit_trade_types['sell'],
            number_of_credits=1000,
            fair_market_value_per_credit=1,
            zero_reason=None,
            trade_effective_date=datetime.datetime.today().strftime(
                '%Y-%m-%d'))

        credit_trades = CreditTradeService.get_organization_credit_trades(
            self.organizations['from'])

        self.assertNotIn(draft_credit_trade, credit_trades)
        self.assertIn(draft_from_fuel_supplier, credit_trades)
        self.assertNotIn(submitted_credit_trade, credit_trades)
        self.assertIn(credit_trade_as_respondent, credit_trades)
        self.assertIn(approved_credit_trade, credit_trades)
コード例 #24
0
ファイル: CreditTrade.py プロジェクト: NickPhura/tfrs
 def perform_create(self, serializer):
     credit_trade = serializer.save()
     CreditTradeService.create_history(credit_trade, True)
     CreditTradeService.dispatch_notifications(None, credit_trade)
コード例 #25
0
    def create_director_transactions(compliance_report, creating_user):
        """
        Validate or Reduce credits when the director accepts a compliance
        report

        Always use the snapshot as the basis for calculation, so we don't
        recompute anything and possibly alter the values

        :param compliance_report:
        :return:
        """
        previous_transactions = []
        current = compliance_report
        while current.supplements is not None:
            current = current.supplements
            if current.credit_transaction is not None:
                previous_transactions.append(current.credit_transaction)

        total_previous_reduction = Decimal(0.0)
        total_previous_validation = Decimal(0.0)

        for transaction in previous_transactions:
            if transaction.type.the_type in ['Credit Validation']:
                total_previous_validation += transaction.number_of_credits
            if transaction.type.the_type in ['Credit Reduction']:
                total_previous_reduction += transaction.number_of_credits

        if settings.DEVELOPMENT:
            print('we have {} previous transactions to consider'.format(
                len(previous_transactions)))
            print('Total of previous reductions: {}'.format(
                total_previous_reduction))
            print('Total of previous validations: {}'.format(
                total_previous_validation))

        if compliance_report.snapshot is None:
            raise InvalidStateException()

        snapshot = compliance_report.snapshot

        if 'summary' not in snapshot:
            raise InvalidStateException()
        if 'lines' not in snapshot['summary']:
            raise InvalidStateException()

        lines = snapshot['summary']['lines']

        desired_net_credit_balance_change = Decimal(0.0)

        if Decimal(lines['25']) > Decimal(0):
            desired_net_credit_balance_change = Decimal(lines['25'])
        else:
            if Decimal(lines['25']) < 0 and Decimal(lines['26']) > Decimal(0):
                desired_net_credit_balance_change = Decimal(
                    lines['26']) * Decimal(-1.0)

        required_credit_transaction = desired_net_credit_balance_change - \
                                      (total_previous_validation - total_previous_reduction)

        if settings.DEVELOPMENT:
            print('line 25 of current report: {}'.format(lines['25']))
            print('desired credit balance change: {}'.format(
                desired_net_credit_balance_change))
            print('required transaction to effect change: {}'.format(
                required_credit_transaction))

        if required_credit_transaction > Decimal(0):
            # do validation for Decimal(lines['25'])
            credit_transaction = CreditTrade(
                initiator=Organization.objects.get(id=1),
                respondent=compliance_report.organization,
                status=CreditTradeStatus.objects.get(status='Draft'),
                type=CreditTradeType.objects.get(the_type='Credit Validation'),
                number_of_credits=required_credit_transaction,
                compliance_period=compliance_report.compliance_period,
                create_user=creating_user,
                update_user=creating_user)
            credit_transaction.save()
            credit_transaction.refresh_from_db()
            CreditTradeService.approve(credit_transaction)
            compliance_report.credit_transaction = credit_transaction
            compliance_report.save()
            CreditTradeService.pvr_notification(None, credit_transaction)
        else:
            if required_credit_transaction < Decimal(0):
                # do_reduction for Decimal(lines['26'])
                credit_transaction = CreditTrade(
                    initiator=Organization.objects.get(id=1),
                    respondent=compliance_report.organization,
                    status=CreditTradeStatus.objects.get(status='Draft'),
                    type=CreditTradeType.objects.get(
                        the_type='Credit Reduction'),
                    number_of_credits=required_credit_transaction *
                    Decimal(-1.0),
                    compliance_period=compliance_report.compliance_period,
                    create_user=creating_user,
                    update_user=creating_user)
                credit_transaction.save()
                credit_transaction.refresh_from_db()
                CreditTradeService.approve(credit_transaction)
                compliance_report.credit_transaction = credit_transaction
                compliance_report.save()
                CreditTradeService.pvr_notification(None, credit_transaction)