diff --git a/backend/api/serializers/credit_transfer.py b/backend/api/serializers/credit_transfer.py
index d08613177..f39250941 100644
--- a/backend/api/serializers/credit_transfer.py
+++ b/backend/api/serializers/credit_transfer.py
@@ -19,7 +19,7 @@
from api.serializers.credit_transfer_content import \
CreditTransferContentSerializer, CreditTransferContentSaveSerializer
from api.serializers.user import UserBasicSerializer
-from api.serializers.organization import OrganizationNameSerializer
+from api.serializers.organization import OrganizationNameSerializer, OrganizationSerializer
from api.services.credit_transaction import calculate_insufficient_credits
from api.services.send_email import notifications_credit_transfers
@@ -200,6 +200,15 @@ class Meta:
)
+class CreditTransferOrganizationBalancesSerializer(ModelSerializer):
+ credit_to = OrganizationSerializer()
+ debit_from = OrganizationSerializer()
+
+ class Meta:
+ model = CreditTransfer
+ fields = ('credit_to', 'debit_from')
+
+
class CreditTransferSaveSerializer(ModelSerializer):
"""
Serializer to create a transfer
diff --git a/backend/api/serializers/organization.py b/backend/api/serializers/organization.py
index 95e40f6ba..eb17e53de 100644
--- a/backend/api/serializers/organization.py
+++ b/backend/api/serializers/organization.py
@@ -16,7 +16,7 @@ class OrganizationNameSerializer(serializers.ModelSerializer):
class Meta:
model = Organization
fields = (
- 'name', 'short_name', 'is_government'
+ 'id', 'name', 'short_name', 'is_government'
)
diff --git a/backend/api/tests/test_credit_transfers.py b/backend/api/tests/test_credit_transfers.py
index 26f463507..f25acb89b 100644
--- a/backend/api/tests/test_credit_transfers.py
+++ b/backend/api/tests/test_credit_transfers.py
@@ -14,6 +14,7 @@
from ..models.organization import Organization
from ..models.signing_authority_confirmation import SigningAuthorityConfirmation
from ..models.signing_authority_assertion import SigningAuthorityAssertion
+from ..models.credit_transfer_statuses import CreditTransferStatuses
from unittest.mock import patch
@@ -26,19 +27,19 @@ def setUp(self):
gov_user = self.users['RTAN'].organization
- transfer = CreditTransfer.objects.create(
+ self.transfer = CreditTransfer.objects.create(
status='SUBMITTED',
credit_to=org1,
debit_from=org2,
)
- transfer2 = CreditTransfer.objects.create(
+ self.transfer2 = CreditTransfer.objects.create(
status='DRAFT',
credit_to=org1,
debit_from=org2,
)
- transfer3 = CreditTransfer.objects.create(
+ self.transfer3 = CreditTransfer.objects.create(
status='APPROVED',
credit_to=org1,
debit_from=org2,
@@ -180,3 +181,47 @@ def test_credit_transfer_create(self):
# Test that email method is called properly
mock_send_credit_transfer_emails.assert_called()
+
+
+ def test_get_transfer(self):
+ transfer = self.transfer
+ transfer_initial_status = transfer.status
+ transfer_id = transfer.id
+ users = ["EMHILLIE_BCEID", "RTAN"]
+ for status in CreditTransferStatuses:
+ transfer.status = status
+ transfer.save()
+ for user in users:
+ response = self.clients[user].get("/api/credit-transfers/" + str(transfer_id))
+ data = response.data
+ credit_to = data.get("credit_to")
+ debit_from = data.get("debit_from")
+ if credit_to is not None:
+ self.assertEqual(len(credit_to), 4)
+ self.assertFalse("balance" in credit_to or "ldv_sales" in credit_to or "avg_ldv_sales" in credit_to)
+ if debit_from is not None:
+ self.assertEqual(len(debit_from), 4)
+ self.assertFalse("balance" in debit_from or "ldv_sales" in debit_from or "avg_ldv_sales" in debit_from)
+ transfer.status = transfer_initial_status
+ transfer.save()
+
+
+ def test_get_org_balances(self):
+ gov_user = "RTAN"
+ non_gov_user = "EMHILLIE_BCEID"
+ transfer = self.transfer
+ transfer_initial_status = transfer.status
+ transfer_id = transfer.id
+ for user in (gov_user, non_gov_user):
+ for status in CreditTransferStatuses:
+ transfer.status = status
+ transfer.save()
+ response = self.clients[user].get("/api/credit-transfers/" + str(transfer_id) + "/org_balances")
+ response_status = response.status_code
+ data = response.data
+ if user == gov_user and status == CreditTransferStatuses.APPROVED:
+ self.assertEqual(response_status, 200)
+ else:
+ self.assertTrue(response_status == 403 or not data)
+ transfer.status = transfer_initial_status
+ transfer.save()
diff --git a/backend/api/viewsets/credit_transfer.py b/backend/api/viewsets/credit_transfer.py
index 474fe3b1e..878419e73 100644
--- a/backend/api/viewsets/credit_transfer.py
+++ b/backend/api/viewsets/credit_transfer.py
@@ -8,7 +8,7 @@
from api.models.credit_transfer_statuses import CreditTransferStatuses
from api.permissions.credit_transfer import CreditTransferPermissions
from api.serializers.credit_transfer import CreditTransferSerializer, \
- CreditTransferSaveSerializer, CreditTransferListSerializer
+ CreditTransferSaveSerializer, CreditTransferListSerializer, CreditTransferOrganizationBalancesSerializer
from api.serializers.credit_transfer_comment import CreditTransferCommentSerializer
from auditable.views import AuditableMixin
from api.services.send_email import notifications_credit_transfers
@@ -125,3 +125,13 @@ def delete_comment(self, request, pk):
delete_comment(comment_id)
return Response(status=status.HTTP_200_OK)
return Response(status=status.HTTP_403_FORBIDDEN)
+
+ @action(detail=True, methods=["GET"])
+ def org_balances(self, request, pk):
+ transfer = self.get_queryset().filter(pk=pk).first()
+ if transfer is None:
+ return Response({})
+ if request.user.is_government and transfer.status == CreditTransferStatuses.APPROVED:
+ serializer = CreditTransferOrganizationBalancesSerializer(transfer)
+ return Response(serializer.data)
+ return Response(status=status.HTTP_403_FORBIDDEN)
diff --git a/frontend/src/app/routes/CreditTransfers.js b/frontend/src/app/routes/CreditTransfers.js
index 22f3ab11f..874b0811e 100644
--- a/frontend/src/app/routes/CreditTransfers.js
+++ b/frontend/src/app/routes/CreditTransfers.js
@@ -7,6 +7,7 @@ const CREDIT_REQUESTS = {
EDIT: `${API_BASE_PATH}/:id/edit`,
UPDATE_COMMENT: `${API_BASE_PATH}/:id/update_comment`,
DELETE_COMMENT: `${API_BASE_PATH}/:id/delete_comment`,
+ ORG_BALANCES: `${API_BASE_PATH}/:id/org_balances`,
}
export default CREDIT_REQUESTS
diff --git a/frontend/src/app/utilities/getSupplierSummary.js b/frontend/src/app/utilities/getSupplierSummary.js
index 9b0b075c2..125026907 100644
--- a/frontend/src/app/utilities/getSupplierSummary.js
+++ b/frontend/src/app/utilities/getSupplierSummary.js
@@ -1,17 +1,17 @@
-const getSupplierSummary = (submission) => {
+const getSupplierSummary = (submission, orgBalances) => {
const initiatingSupplier = {
- currentBalanceA: parseFloat(submission.debitFrom.balance.A),
- currentBalanceB: parseFloat(submission.debitFrom.balance.B),
- newBalanceA: parseFloat(submission.debitFrom.balance.A),
- newBalanceB: parseFloat(submission.debitFrom.balance.B),
- supplierLabel: submission.debitFrom.name
+ currentBalanceA: parseFloat(orgBalances.debitFrom.balance.A),
+ currentBalanceB: parseFloat(orgBalances.debitFrom.balance.B),
+ newBalanceA: parseFloat(orgBalances.debitFrom.balance.A),
+ newBalanceB: parseFloat(orgBalances.debitFrom.balance.B),
+ supplierLabel: orgBalances.debitFrom.name
}
const receivingSupplier = {
- currentBalanceA: parseFloat(submission.creditTo.balance.A),
- currentBalanceB: parseFloat(submission.creditTo.balance.B),
- newBalanceA: parseFloat(submission.creditTo.balance.A),
- newBalanceB: parseFloat(submission.creditTo.balance.B),
- supplierLabel: submission.creditTo.name
+ currentBalanceA: parseFloat(orgBalances.creditTo.balance.A),
+ currentBalanceB: parseFloat(orgBalances.creditTo.balance.B),
+ newBalanceA: parseFloat(orgBalances.creditTo.balance.A),
+ newBalanceB: parseFloat(orgBalances.creditTo.balance.B),
+ supplierLabel: orgBalances.creditTo.name
}
submission.creditTransferContent.forEach((item) => {
if (item.creditClass.creditClass === 'A') {
diff --git a/frontend/src/credits/CreditTransfersDetailsContainer.js b/frontend/src/credits/CreditTransfersDetailsContainer.js
index e25c1423c..f19320539 100644
--- a/frontend/src/credits/CreditTransfersDetailsContainer.js
+++ b/frontend/src/credits/CreditTransfersDetailsContainer.js
@@ -23,6 +23,7 @@ const CreditTransfersDetailsContainer = (props) => {
const [sufficientCredit, setSufficientCredit] = useState(true)
const { id } = match.params
const [submission, setSubmission] = useState({})
+ const [orgBalances, setOrgBalances] = useState({})
const [loading, setLoading] = useState(true)
const refreshDetails = () => {
@@ -49,6 +50,14 @@ const CreditTransfersDetailsContainer = (props) => {
refreshDetails()
}, [id])
+ useEffect(() => {
+ if (user.isGovernment && submission.status === 'APPROVED') {
+ axios.get(ROUTES_CREDIT_TRANSFERS.ORG_BALANCES.replace(':id', id)).then((response) => {
+ setOrgBalances(response.data)
+ })
+ }
+ }, [id, user, submission])
+
const handleCheckboxClick = (event) => {
if (!event.target.checked) {
const checked = checkboxes.filter(
@@ -170,6 +179,7 @@ const CreditTransfersDetailsContainer = (props) => {
submission={submission}
user={user}
errorMessage={errorMessage}
+ orgBalances={orgBalances}
/>
]
}
diff --git a/frontend/src/credits/components/CreditTransfersDetailsPage.js b/frontend/src/credits/components/CreditTransfersDetailsPage.js
index 39b853e5a..5a749d11e 100644
--- a/frontend/src/credits/components/CreditTransfersDetailsPage.js
+++ b/frontend/src/credits/components/CreditTransfersDetailsPage.js
@@ -32,7 +32,8 @@ const CreditTransfersDetailsPage = (props) => {
sufficientCredit,
submission,
user,
- errorMessage
+ errorMessage,
+ orgBalances
} = props
const { id } = useParams()
const [comment, setComment] = useState('')
@@ -501,9 +502,10 @@ const CreditTransfersDetailsPage = (props) => {
)}
- {transferRole.governmentAnalyst && (
+ {transferRole.governmentAnalyst && Object.keys(orgBalances).length !== 0 && (