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

Feat issueresolve 1 #34

Merged
merged 3 commits into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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: 3 additions & 2 deletions backend-app/file/file_tests/models_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,12 @@ def test_create_file(self):
"project",
"author",
"status",
"is_downloaded"
"is_downloaded",
"validator",
)
.get(id=new_file.id)
),
set(credentials.values()).union({'v', False})
set(credentials.values()).union({'v', False, None})
)
self.assertEqual(init_count + 1, self.case.project.file_set.count())

Expand Down
20 changes: 18 additions & 2 deletions backend-app/file/file_tests/serializers_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,13 @@ def test_file_serializer(self):

self.assertEqual(
set(data.keys()),
data_keys.union({'upload_date', 'attributes', 'author_name'})
data_keys.union({
'upload_date',
"update_date",
'attributes',
'author_name',
"validator_name"
})
)
self.assertEqual(
{val for key, val in data.items() if key in data_keys},
Expand All @@ -42,14 +48,24 @@ def test_file_serializer(self):
self.assertEqual(data["attributes"][0].keys(), {"uid", "attributes"})

def test_update_file_serializer(self):
data = FileSerializer(self.case.file_, {'status': 'a'}, partial=True)
data = FileSerializer(
self.case.file_,
{'status': 'a'},
partial=True,
context={"validator": self.case.user}
)
init_date = data.instance.upload_date

self.assertIsNone(data.instance.validator)

if data.is_valid(): data.update_file()

updated_data = FileSerializer(self.case.file_).data

self.assertEqual(updated_data['status'], 'a')
self.assertFalse(bool(updated_data['attributes']))
self.assertIsNotNone(updated_data.get("validator_name"))
self.assertNotEqual(updated_data.get("update_date"), init_date)

def test_update_attribute_file_serializer(self):
self.case.attribute2 = self.case.attributegroup.attribute.create(
Expand Down
42 changes: 39 additions & 3 deletions backend-app/file/file_tests/services_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,13 @@
from project.models import Project
from user.models import CustomUser
from uuid import uuid4
from datetime import datetime as dt, timedelta as td
from django.utils import timezone as tz


class ViewServicesTest(TestCase, ViewSetServices):
date_format: str = "%Y-%m-%d"

@classmethod
def setUpClass(cls):
super().setUpClass()
Expand Down Expand Up @@ -146,9 +150,18 @@ def test_patch(self):
str(self.case.attributegroup.uid): [new_attr.id],
}
}
request = lambda payload={}: type(
"rq",
(object,),
{"data": payload, "user": self.case.user}
)

res, code = self._patch_file(self.case.file_.id, request_data)
invalid_res, invalid_code = self._patch_file(self.case.file_.id, {"status": 123})
valid_rq_init_date = File.objects.get(id=self.case.file_.id).update_date,

self.assertIsNone(File.objects.get(id=self.case.file_.id).validator)

res, code = self._patch_file(self.case.file_.id, request(request_data))
invalid_res, invalid_code = self._patch_file(self.case.file_.id, request({"status": 123}))

self.assertEqual(invalid_code, 400)
self.assertFalse(invalid_res["ok"])
Expand Down Expand Up @@ -179,6 +192,11 @@ def test_patch(self):
File.objects.get(id=self.case.file_.id).status,
"a"
)
self.assertNotEqual(
File.objects.get(id=self.case.file_.id).update_date,
valid_rq_init_date
)
self.assertIsNotNone(File.objects.get(id=self.case.file_.id).validator)

def test_form_query(self):
query = {}
Expand All @@ -199,6 +217,12 @@ def test_form_query(self):
query["author"] = self.admin
self._form_query_mixin(query)

query["from_"] = dt.now().strftime(self.date_format)
self._form_query_mixin(query)

query["to"] = (dt.now() + td(days=1)).strftime(self.date_format)
self._form_query_mixin(query)

def _form_query_mixin(self, data={}):
query, filter = self._get_query(**data)
res = self._form_query(
Expand All @@ -215,7 +239,9 @@ def _get_query(
status="",
downloaded=False,
author=[],
user=None
user=None,
from_="",
to=""
):
request_query = type(
"query",
Expand Down Expand Up @@ -248,6 +274,16 @@ def _get_query(
if author:
query.set("author[]", author)
filter["author__in"] = author
if from_:
query.set("from", from_)
filter["upload_date__gte"] = tz.make_aware(
dt.strptime(from_, self.date_format)
)
if to:
query.set("to", to)
filter["upload_date__lte"] = tz.make_aware(
dt.strptime(to, self.date_format)
)

return query, filter

Expand Down
9 changes: 8 additions & 1 deletion backend-app/file/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,18 @@ class File(Model):
file_name: CharField = CharField(max_length=255)
file_type: CharField = CharField(max_length=10)
status: CharField = CharField(max_length=1, choices=STATUSES, default='v')
upload_date: DateTimeField = DateTimeField(auto_now_add=True)
is_downloaded: BooleanField = BooleanField(default=False)
upload_date: DateTimeField = DateTimeField(auto_now_add=True)
update_date: DateTimeField = DateTimeField(auto_now_add=True, null=True)

project: ForeignKey = ForeignKey("project.Project", on_delete=DO_NOTHING)
author: ForeignKey = ForeignKey("user.CustomUser", on_delete=DO_NOTHING)
validator: ForeignKey = ForeignKey(
"user.CustomUser",
null=True,
on_delete=DO_NOTHING,
related_name="validator"
)

class Meta:
db_table = "file"
Expand Down
19 changes: 16 additions & 3 deletions backend-app/file/serializers.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,40 @@
from rest_framework.serializers import SerializerMethodField, ModelSerializer
from typing import Any
from django.utils import timezone
from collections import OrderedDict
from attribute.serializers import AttributeGroupSerializer
from .models import File
from user.models import CustomUser
from typing import Optional


class FileSerializer(ModelSerializer):
attributes: SerializerMethodField = SerializerMethodField()
author_name: SerializerMethodField = SerializerMethodField()
validator_name: SerializerMethodField = SerializerMethodField()

class Meta:
model = File
exclude = ("project", "author")
exclude = ("project", "author", "validator")

def get_attributes(self, instance: File) -> list[OrderedDict[str, Any]]:
return AttributeGroupSerializer(instance.attributegroup_set.all(), many=True).data

def get_author_name(self, instance: File) -> str: return instance.author.username

def get_validator_name(self, instance: File) -> str:
validator: Optional[CustomUser] = instance.validator
return validator and validator.username

def update_file(self) -> File:
super().save()
self.validated_data["update_date"] = timezone.now()
self.validated_data["validator"] = self.context.get("validator")

super().update(self.instance, self.validated_data)

self.instance.update_attributes(self.initial_data.get("attribute", {}))
self.instance.update_attributes(
self.initial_data.get("attribute", {}),
)

return self.instance

Expand Down
29 changes: 22 additions & 7 deletions backend-app/file/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@
from rest_framework.views import Request
from django.db import connection
from django.db.models import Count, Subquery, QuerySet
from django.utils import timezone as tz
from attribute.models import Level, AttributeGroup as AGroup
from user.models import CustomUser
from json import loads
from typing import Any
from uuid import UUID
from datetime import datetime as dt
from .serializers import File, FileSerializer


Expand All @@ -28,21 +30,28 @@ class ViewSetServices:
("file_type__in", "type[]", True),
("status", "status", False),
("is_downloaded", "downloaded", False),
("author__in", "author[]", True)
("author__in", "author[]", True),
("upload_date__gte", "from", False),
("upload_date__lte", "to", False)
)

def _patch_file(
self,
file_id: str,
request_data: dict[str, Any]
request: Request
) -> tuple[dict[str, Any], int]:
# TODO: no handler for nofile case. imp tests after
file = File.objects \
.select_related("author") \
.prefetch_related("attributegroup_set") \
.get(id=file_id)

updated_file = FileSerializer(file, request_data, partial=True)
updated_file = FileSerializer(
file,
request.data,
partial=True,
context={"validator": request.user}
)
update_valid = updated_file.is_valid()

if update_valid: updated_file.update_file()
Expand Down Expand Up @@ -87,13 +96,19 @@ def _form_query(
else request_query.get(param)
)

if query_param: query[filter_name] = (
False if filter_name == "is_downloaded"
else query_param
)
if query_param:
query[filter_name] = self._get_param(filter_name, query_param)

return query

def _get_param(self, filter_name: str, query_param: Any) -> Any:
date_from_str = lambda d: tz.make_aware(dt.strptime(d, "%Y-%m-%d"))
match filter_name:
case "is_downloaded": return False
case "upload_date__gte": return date_from_str(query_param)
case "upload_date__lte": return date_from_str(query_param)
case _: return query_param

def _get_files(
self,
project_id: int,
Expand Down
2 changes: 1 addition & 1 deletion backend-app/file/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class FileViewSet(APIView, ViewSetServices):
permission_classes = (IsAuthenticated, FilePermission)

def patch(self, request: Request, fileID: str) -> Response:
response, status = self._patch_file(fileID, request.data)
response, status = self._patch_file(fileID, request)
return Response(response, status=status)

def delete(self, _, fileID: str) -> Response:
Expand Down
3 changes: 2 additions & 1 deletion frontend-app/src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { UserContext } from "./context/User";
import { AlertContext } from "./context/Alert";
import { useState, useEffect } from "react";
import { ReactElement, useState, useEffect } from "react";
import { useUser, useAlerts } from "./hooks";
import { api } from "./config/api";
import AppRouter from "./components/AppRouter";
Expand All @@ -9,6 +9,7 @@ import StatusLoad from "./components/ui/StatusLoad";
import AlertManager from "./components/AlertManager";
import './app.css';

/** @returns {ReactElement} */
export default function App() {
const { user, initUser } = useUser();
const alertManager = useAlerts();
Expand Down
2 changes: 1 addition & 1 deletion frontend-app/src/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
/* --issLightGreen: #99ff62; */
/* --issBrand: #004077; */
/* --issLightBrand: #01a4e0; */
--maxWidth: 1320px;
--maxWidth: 1920px;
}

* {
Expand Down
Loading
Loading