Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1057 bar chart for profile statistics #1067

Merged
merged 37 commits into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
a2f486b
Added bar chart for types of activities of profiles in statistics sec…
AlexanderSychev2005 Jan 5, 2025
90c2d53
Merge branch 'refs/heads/develop' into 1057-bar-chart-for-profile-sta…
AlexanderSychev2005 Jan 7, 2025
0cd26da
Merged develop
AlexanderSychev2005 Jan 7, 2025
db50f8d
Added a new api point for statistics of company activities
AlexanderSychev2005 Jan 7, 2025
5f58eff
Added a new api point for statistics of company activities
AlexanderSychev2005 Jan 7, 2025
8a77894
Adjusted frontend for a new api point
AlexanderSychev2005 Jan 7, 2025
cf8920d
Created backend tests for profiles statistics about activities
AlexanderSychev2005 Jan 7, 2025
286b46f
Created backend tests for profiles statistics about activities
AlexanderSychev2005 Jan 7, 2025
f824311
Reformatted backend
AlexanderSychev2005 Jan 8, 2025
f37d733
Merge branch 'refs/heads/develop' into 1057-bar-chart-for-profile-sta…
AlexanderSychev2005 Jan 8, 2025
e60d799
Added horeca category
AlexanderSychev2005 Jan 9, 2025
01c28db
Fixed tests with HORECA activity
AlexanderSychev2005 Jan 9, 2025
67647be
Reformatted backend
AlexanderSychev2005 Jan 10, 2025
00d27d2
Transferred Bar chart for activities into a new component frontend
AlexanderSychev2005 Jan 10, 2025
a433231
Reformatted
AlexanderSychev2005 Jan 10, 2025
e5347a2
Added css for bar chart
AlexanderSychev2005 Jan 10, 2025
8c5e0be
Moved the chart to a different folder
AlexanderSychev2005 Jan 10, 2025
a39e224
Deleted the decimal part of the y in bar chart
AlexanderSychev2005 Jan 10, 2025
bacc7be
Added view and serializer
AlexanderSychev2005 Jan 11, 2025
b69ceb6
Added tests
AlexanderSychev2005 Jan 11, 2025
b6ee3c3
Added files
AlexanderSychev2005 Jan 11, 2025
d2bfd75
Merge remote-tracking branch 'origin/1057-bar-chart-for-profile-stati…
AlexanderSychev2005 Jan 11, 2025
b72f512
Merge branch 'refs/heads/develop' into 1057-bar-chart-for-profile-sta…
AlexanderSychev2005 Jan 11, 2025
9cba01c
Added branch files
AlexanderSychev2005 Jan 11, 2025
37d06a6
Moved chart to another component
AlexanderSychev2005 Jan 12, 2025
8fa2abd
Added distinct value to values in statistics view, adjusted tests wit…
AlexanderSychev2005 Jan 12, 2025
2664c10
Deleted unused tests
AlexanderSychev2005 Jan 12, 2025
b036d00
Formatted files
AlexanderSychev2005 Jan 12, 2025
ae476a6
Changed factories
AlexanderSychev2005 Jan 15, 2025
dfb36f9
Fixed profiles tests
AlexanderSychev2005 Jan 15, 2025
b39b6d2
Converted css into scss
AlexanderSychev2005 Jan 16, 2025
5f418d3
Merge branch 'refs/heads/develop' into 1057-bar-chart-for-profile-sta…
AlexanderSychev2005 Jan 18, 2025
f4f0ec8
Updated branch by develop
AlexanderSychev2005 Jan 18, 2025
d64018d
Changed AdminUserFactory to UserFactory in statistics tests
AlexanderSychev2005 Jan 18, 2025
288e413
Optimised tests profile statistics
AlexanderSychev2005 Jan 20, 2025
83640aa
Deleted unnecessary print in profile statistics tests
AlexanderSychev2005 Jan 20, 2025
a9d6df5
Merge branch 'refs/heads/develop' into 1057-bar-chart-for-profile-sta…
AlexanderSychev2005 Jan 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions BackEnd/administration/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,11 @@ class StatisticsSerializer(serializers.Serializer):
investors_count = serializers.IntegerField()
startups_count = serializers.IntegerField()
blocked_companies_count = serializers.IntegerField()
manufacturers_count = serializers.IntegerField()
importers_count = serializers.IntegerField()
retail_networks_count = serializers.IntegerField()
horeca_count = serializers.IntegerField()
others_count = serializers.IntegerField()


class ContactInformationSerializer(serializers.ModelSerializer):
Expand Down
77 changes: 66 additions & 11 deletions BackEnd/administration/tests/test_profile_statistics.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,58 @@
from rest_framework.test import APITestCase
from rest_framework import status
from administration.factories import AdminUserFactory, AdminProfileFactory
from administration.factories import AdminUserFactory
from authentication.factories import UserFactory
from profiles.factories import (
ProfileFactory,
ActivityFactory,
ProfileCompanyFactory,
ProfileStartupFactory,
)
from utils.unittest_helper import utc_datetime


class TestProfileStatisticsStaff(APITestCase):
def setUp(self):
self.user = AdminUserFactory()
self.user = UserFactory(is_staff=True)
self.client.force_authenticate(self.user)
self.test_startup_user = AdminUserFactory(is_staff=False)
self.test_investor_user = AdminUserFactory(is_staff=False)
self.test_blocked_company_user = AdminUserFactory(is_staff=False)
self.startup_company = AdminProfileFactory(
person_id=self.test_startup_user.id, is_registered=False

self.activities = {
"Виробник": ActivityFactory(name="Виробник"),
"Імпортер": ActivityFactory(name="Імпортер"),
"Роздрібна мережа": ActivityFactory(name="Роздрібна мережа"),
"HORECA": ActivityFactory(name="HORECA"),
"Інші послуги": ActivityFactory(name="Інші послуги"),
}

self.test_startup_user = UserFactory()
self.test_investor_user = UserFactory()
self.test_blocked_company_user = UserFactory()
self.startup_company = ProfileStartupFactory(
person_id=self.test_startup_user.id,
activities=[
self.activities["Виробник"],
self.activities["HORECA"],
],
)
self.startup_company.created_at = utc_datetime(2023, 12, 7)

self.startup_company.save()
self.investor_company = AdminProfileFactory(
person_id=self.test_investor_user.id, is_startup=False
self.investor_company = ProfileCompanyFactory(
person_id=self.test_investor_user.id,
activities=[
self.activities["Імпортер"],
self.activities["HORECA"],
],
)
self.investor_company.created_at = utc_datetime(2024, 5, 10)

self.investor_company.save()
self.blocked_company = AdminProfileFactory(
person_id=self.test_blocked_company_user.id, status="blocked"
self.blocked_company = ProfileFactory(
is_registered=True,
is_startup=True,
person_id=self.test_blocked_company_user.id,
status="blocked",
activities=[self.activities["Роздрібна мережа"]],
)
self.blocked_company.created_at = utc_datetime(2024, 12, 12)
self.blocked_company.save()
Expand All @@ -34,6 +64,11 @@ def test_get_profile_statistics(self):
"investors_count": 2,
"startups_count": 2,
"blocked_companies_count": 1,
"manufacturers_count": 1,
"importers_count": 1,
"retail_networks_count": 1,
"horeca_count": 2,
"others_count": 0,
}
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, data)
Expand All @@ -45,6 +80,11 @@ def test_get_profile_statistics_filtered_by_year(self):
"investors_count": 2,
"startups_count": 1,
"blocked_companies_count": 1,
"manufacturers_count": 0,
"importers_count": 1,
"retail_networks_count": 1,
"horeca_count": 1,
"others_count": 0,
}
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, data)
Expand All @@ -58,6 +98,11 @@ def test_get_profile_statistics_filtered_by_range(self):
"investors_count": 2,
"startups_count": 1,
"blocked_companies_count": 1,
"manufacturers_count": 0,
"importers_count": 1,
"retail_networks_count": 1,
"horeca_count": 1,
"others_count": 0,
}
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, data)
Expand All @@ -71,6 +116,11 @@ def test_get_profile_statistics_filtered_by_month(self):
"investors_count": 0,
"startups_count": 1,
"blocked_companies_count": 0,
"manufacturers_count": 1,
"importers_count": 0,
"retail_networks_count": 0,
"horeca_count": 1,
"others_count": 0,
}
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, data)
Expand All @@ -84,6 +134,11 @@ def test_get_profile_statistics_filtered_by_day(self):
"investors_count": 0,
"startups_count": 1,
"blocked_companies_count": 0,
"manufacturers_count": 1,
"importers_count": 0,
"retail_networks_count": 0,
"horeca_count": 1,
"others_count": 0,
}
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, data)
Expand Down
34 changes: 29 additions & 5 deletions BackEnd/administration/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
CreateAPIView,
)


from administration.serializers import (
AdminRegistrationSerializer,
AdminCompanyListSerializer,
AdminCompanyDetailSerializer,
AdminUserListSerializer,
Expand All @@ -36,6 +36,7 @@
StatisticsSerializer,
ContactInformationSerializer,
MonthlyProfileStatisticsSerializer,
AdminRegistrationSerializer,
)
from administration.pagination import ListPagination
from administration.models import (
Expand Down Expand Up @@ -166,10 +167,33 @@ class ProfileStatisticsView(RetrieveAPIView):
def get_object(self):
queryset = self.filter_queryset(Profile.objects.all())
return queryset.aggregate(
companies_count=Count("pk"),
investors_count=Count("pk", filter=Q(is_registered=True)),
startups_count=Count("pk", filter=Q(is_startup=True)),
blocked_companies_count=Count("pk", filter=Q(status="blocked")),
companies_count=Count("pk", distinct=True),
investors_count=Count(
"pk", filter=Q(is_registered=True), distinct=True
),
startups_count=Count(
"pk", filter=Q(is_startup=True), distinct=True
),
blocked_companies_count=Count(
"pk", filter=Q(status="blocked"), distinct=True
),
manufacturers_count=Count(
"pk", filter=Q(activities__name="Виробник"), distinct=True
),
importers_count=Count(
"pk", filter=Q(activities__name="Імпортер"), distinct=True
),
retail_networks_count=Count(
"pk",
filter=Q(activities__name="Роздрібна мережа"),
distinct=True,
),
horeca_count=Count(
"pk", filter=Q(activities__name="HORECA"), distinct=True
),
others_count=Count(
"pk", filter=Q(activities__name="Інші послуги"), distinct=True
),
)


Expand Down
30 changes: 30 additions & 0 deletions FrontEnd/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions FrontEnd/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@
"@testing-library/user-event": "^13.5.0",
"antd": "^5.21.5",
"axios": "^1.5.0",
"chart.js": "^4.4.7",
"hamburger-react": "^2.5.1",
"prop-types": "^15.8.1",
"react": "^18.2.0",
"react-chartjs-2": "^5.2.0",
"react-cookie": "^6.1.0",
"react-dom": "^18.2.0",
"react-google-recaptcha": "^3.1.0",
Expand Down
83 changes: 83 additions & 0 deletions FrontEnd/src/pages/AdminPage/Charts/ActivitiesBarChart.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import React from 'react';
import {
Chart as ChartJS,
CategoryScale,
LinearScale,
BarElement,
Title,
Tooltip,
Legend,
} from 'chart.js';
ChartJS.register(
CategoryScale,
LinearScale,
BarElement,
Title,
Tooltip,
Legend
);
import { Bar } from 'react-chartjs-2';
import css from './ActivitiesBarChart.module.scss';
import Loader from '../../../components/Loader/Loader';


function ActivitiesBarChart({statistics, isLoading, error}) {
const chartData = statistics
? {
labels: ['Виробники', 'Імпортери', 'Роздрібніки', 'HORECA', 'Інші'],
datasets: [
{
label: 'Типи компаній',
data: [
statistics.manufacturers_count,
statistics.importers_count,
statistics.retail_networks_count,
statistics.horeca_count,
statistics.others_count
],
backgroundColor: [
'#87f3b0',
]
},
]
} : {labels: [], datasets: []};
const options = {
responsive: true,
plugins: {
legend: {
position: 'top',
},
title: {
display: true,
text: 'Статистика по типам компаній',
},
scales: {
y: {
ticks: {
stepSize: 1,
},
},
},
},
};
return (
<div className={css['chart-container']}>
{isLoading && (
<div className={css['loader-container']}>
<Loader/>
</div>
)
}
{error && (
<div className={css['error']}>Не вдалося отримати статистику компаній</div>
)
}
{!isLoading && !error && (
<Bar data={chartData} options={options}/>
)
}
</div>
);
}

export default ActivitiesBarChart;
18 changes: 18 additions & 0 deletions FrontEnd/src/pages/AdminPage/Charts/ActivitiesBarChart.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.chart-container {
width: 400px;
}

.error {
color: #f5222d;
background-color: #fff1f0;
border: 1px solid #ffa39e;
padding: 10px;
border-radius: 4px;
margin-top: 10px;

}

.loader-container {
width: 200px;
height: 300px;
}
Loading
Loading