Skip to content
This repository was archived by the owner on Nov 11, 2022. It is now read-only.

Commit 082ccdd

Browse files
Fixed some non-correct behavior. Codestyle. tests
1 parent c70ffa4 commit 082ccdd

File tree

10 files changed

+183
-58
lines changed

10 files changed

+183
-58
lines changed

shop/constants.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
STATUS_400_ERROR_TEXT: str = 'Validation Failed'
2+
STATUS_404_ERROR_TEXT: str = 'Item not found'
3+
4+
SHOP_UNIT_TYPES: tuple = (('CATEGORY', 'CATEGORY'), ('OFFER', 'OFFER'))

shop/custom_types.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
from rest_framework import status
12
import dataclasses
23

3-
SHOP_UNIT_TYPES: tuple = (('CATEGORY', 'CATEGORY'), ('OFFER', 'OFFER'))
4+
from .constants import STATUS_400_ERROR_TEXT, STATUS_404_ERROR_TEXT
45

56

67
@dataclasses.dataclass
@@ -9,4 +10,8 @@ class Error:
910
message: str
1011

1112
def to_dict(self):
12-
return {'code': self.code, 'message': self.message}
13+
return {'code': self.code, 'message': self.message}
14+
15+
16+
ERROR_400: Error = Error(status.HTTP_400_BAD_REQUEST, STATUS_400_ERROR_TEXT)
17+
ERROR_404: Error = Error(status.HTTP_404_NOT_FOUND, STATUS_404_ERROR_TEXT)

shop/models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from django.db import models
2-
from .custom_types import SHOP_UNIT_TYPES
2+
from .constants import SHOP_UNIT_TYPES
33

44

55
class ShopUnit(models.Model):

shop/serializers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from .custom_types import SHOP_UNIT_TYPES
1+
from .constants import SHOP_UNIT_TYPES
22

33

44
def shop_unit_to_dict(data, with_children: bool = True) -> dict:

shop/tests.py

Lines changed: 0 additions & 3 deletions
This file was deleted.

shop/utils.py

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
from .custom_types import SHOP_UNIT_TYPES
1+
from .custom_types import ERROR_400, ERROR_404
2+
from .constants import SHOP_UNIT_TYPES
23
from .models import ShopUnit, HistoryTable, ShopUnitHistory
34
from dateutil import parser
45

@@ -39,11 +40,11 @@ def remove_item_from_history(id_to_delete: str) -> None:
3940

4041

4142
def update_parent_prices_after_creating(item_to_start) -> None:
42-
price_to_add: int = item_to_start.price
43-
4443
if item_to_start.parentId is None:
4544
return
4645

46+
price_to_add: int = item_to_start.price
47+
4748
nexts = ShopUnit.objects.filter(id=item_to_start.parentId)
4849

4950
while len(nexts) != 0:
@@ -55,7 +56,7 @@ def update_parent_prices_after_creating(item_to_start) -> None:
5556
nexts = ShopUnit.objects.filter(id=parent.parentId)
5657

5758

58-
def update_parent_date_after_creating(item_to_start, new_date) -> None:
59+
def update_parent_date_after_item_creating(item_to_start, new_date: str) -> None:
5960
if item_to_start.parentId is None:
6061
return
6162

@@ -68,14 +69,15 @@ def update_parent_date_after_creating(item_to_start, new_date) -> None:
6869
nexts = ShopUnit.objects.filter(id=parent.parentId)
6970

7071

71-
def update_parent_prices_after_deleting(nexts_initial, price_to_subtract: int, goods_count_to_subtract: int) -> None:
72+
def update_parent_prices_after_item_deleting(nexts_initial, price_to_subtract: int, goods_count_to_subtract: int) -> None:
7273
nexts = nexts_initial
7374

7475
while len(nexts) != 0:
7576
parent = nexts[0]
7677

7778
parent.totally_inner_goods_count -= goods_count_to_subtract
7879
parent.total_inner_sum -= price_to_subtract
80+
7981
if parent.totally_inner_goods_count != 0:
8082
parent.price = parent.total_inner_sum // parent.totally_inner_goods_count
8183
else:
@@ -110,7 +112,6 @@ def update_parents_date_after_item_updating(nexts_initial, date: str) -> None:
110112

111113
while len(nexts) != 0:
112114
parent = nexts[0]
113-
#print(f'UPDATING {parent.name} from {parent.date} to {date}')
114115
parent.date = date
115116
parent.save()
116117
nexts = ShopUnit.objects.filter(id=parent.parentId)
@@ -137,30 +138,32 @@ def create_new_item(item: dict, date: str) -> None:
137138
parent.children.add(created_object)
138139
parent.save()
139140

140-
# if it is an offer => update prices in all parent
141+
# if it is an offer => update prices in all parents and also update dates !
141142
if created_object.type != SHOP_UNIT_TYPES[0][0]:
142143
update_parent_prices_after_creating(created_object)
143-
144-
update_parent_date_after_creating(created_object, date)
144+
update_parent_date_after_item_creating(created_object, date)
145145

146146
add_parents_changes_to_history(ShopUnit.objects.filter(id=created_object.parentId))
147147

148148

149149
def update_existing_item(item: dict, date: str) -> None:
150150
existing_item = ShopUnit.objects.get(id=item['id'])
151151

152-
# firstly remove price and counts from statistics (maybe we move whole category, for example)
152+
# firstly remove price and counts from statistics (maybe we move to another category)
153153
if existing_item.parentId is not None:
154-
update_parent_prices_after_deleting(
155-
ShopUnit.objects.filter(id=existing_item.parentId),
154+
existing_item_parents = ShopUnit.objects.filter(id=existing_item.parentId)
155+
update_parent_prices_after_item_deleting(
156+
existing_item_parents,
156157
existing_item.total_inner_sum,
157158
existing_item.totally_inner_goods_count
158159
)
160+
update_parents_date_after_item_updating(existing_item_parents, date)
159161

160-
# if moving to another category => update current parent history, than will update new parent history
162+
# if moving to another category => update current parent history, after will update new parent history
161163
if existing_item.parentId != item['parentId']:
162-
add_parents_changes_to_history(ShopUnit.objects.filter(id=existing_item.parentId))
164+
add_parents_changes_to_history(existing_item_parents)
163165

166+
# now updating the item:
164167
existing_item.name = item['name']
165168
existing_item.date = date
166169
existing_item.save()
@@ -186,13 +189,12 @@ def update_existing_item(item: dict, date: str) -> None:
186189
existing_item.save()
187190
add_item_to_history_table(existing_item)
188191

189-
update_parent_prices_after_item_updating(
190-
ShopUnit.objects.filter(id=existing_item.parentId),
191-
existing_item.total_inner_sum, existing_item.totally_inner_goods_count
192-
)
192+
parents = ShopUnit.objects.filter(id=existing_item.parentId)
193+
194+
update_parent_prices_after_item_updating(parents, existing_item.total_inner_sum, existing_item.totally_inner_goods_count)
193195

194-
update_parents_date_after_item_updating(ShopUnit.objects.filter(id=existing_item.parentId), date)
195-
add_parents_changes_to_history(ShopUnit.objects.filter(id=existing_item.parentId))
196+
update_parents_date_after_item_updating(parents, date)
197+
add_parents_changes_to_history(parents)
196198

197199

198200
def remove_item(element) -> None:
@@ -207,13 +209,13 @@ def remove_item(element) -> None:
207209

208210

209211
def satisfies_date_interval(item_date_source: str, right_date_range_border_source: str) -> bool:
210-
SECONDS_IN_DAY: int = 3600
212+
SECONDS_IN_HOUR: int = 60 * 60
211213
HOURS_IN_DAY: int = 24
212214

213215
right_border = parser.parse(right_date_range_border_source)
214216
item_date = parser.parse(item_date_source)
215217

216-
return (right_border >= item_date) and ((right_border - item_date).total_seconds() / SECONDS_IN_DAY <= HOURS_IN_DAY)
218+
return (right_border >= item_date) and (((right_border - item_date).total_seconds() / SECONDS_IN_HOUR) <= HOURS_IN_DAY)
217219

218220

219221
def get_node_statistics_filtered_by_date(row_in_history_table, date_from, date_to):

shop/validators.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from datetime import datetime
22
from uuid import UUID
33

4-
from .custom_types import SHOP_UNIT_TYPES
4+
from .constants import SHOP_UNIT_TYPES
55
from .models import ShopUnit
66

77

shop/views.py

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,29 @@
44

55
from .validators import check_items_for_import, check_valid_uuid, check_date_iso
66
from .utils import create_new_item, update_existing_item, remove_item
7-
from .utils import update_parent_prices_after_deleting
7+
from .utils import update_parent_prices_after_item_deleting
88
from .utils import satisfies_date_interval
99
from .utils import add_parents_changes_to_history
1010
from .utils import get_node_statistics_filtered_by_date
11-
from .custom_types import Error, SHOP_UNIT_TYPES
11+
from .custom_types import ERROR_400, ERROR_404
12+
from .constants import SHOP_UNIT_TYPES
1213
from .models import ShopUnit, HistoryTable
1314
from .serializers import shop_unit_to_dict
1415

1516

1617
class ImportsAPIView(views.APIView):
1718
def post(self, request: Request) -> Response:
18-
received_post_data = request.data
19+
if 'updateDate' not in request.data:
20+
return Response(ERROR_400.to_dict(), status=status.HTTP_400_BAD_REQUEST)
1921

20-
received_update_date = received_post_data['updateDate']
21-
received_items = received_post_data['items']
22+
if 'items' not in request.data:
23+
return Response(ERROR_400.to_dict(), status=status.HTTP_400_BAD_REQUEST)
2224

23-
check_result: bool = check_items_for_import(received_items, received_update_date)
25+
received_update_date = request.data['updateDate']
26+
received_items = request.data['items']
2427

25-
if not check_result:
26-
return Response(Error(400, 'Validation Failed').to_dict(), status=status.HTTP_400_BAD_REQUEST)
28+
if not check_items_for_import(received_items, received_update_date):
29+
return Response(ERROR_400.to_dict(), status=status.HTTP_400_BAD_REQUEST)
2730

2831
for item in received_items:
2932
existing_units = ShopUnit.objects
@@ -40,12 +43,12 @@ def post(self, request: Request) -> Response:
4043
class DeleteAPIView(views.APIView):
4144
def delete(self, request: Request, to_delete: str = None) -> Response:
4245
if not check_valid_uuid(to_delete):
43-
return Response(Error(400, 'Validation Failed').to_dict(), status=status.HTTP_400_BAD_REQUEST)
46+
return Response(ERROR_400.to_dict(), status=status.HTTP_400_BAD_REQUEST)
4447

4548
found_item = ShopUnit.objects.filter(id=to_delete)
4649

4750
if len(found_item) == 0:
48-
return Response(Error(404, 'Item not found').to_dict(), status=status.HTTP_404_NOT_FOUND)
51+
return Response(ERROR_404.to_dict(), status=status.HTTP_404_NOT_FOUND)
4952

5053
deleted_goods_count: int = found_item[0].totally_inner_goods_count
5154
deleted_total_sum: int = found_item[0].total_inner_sum
@@ -54,7 +57,7 @@ def delete(self, request: Request, to_delete: str = None) -> Response:
5457
remove_item(found_item[0])
5558

5659
if len(parent) != 0:
57-
update_parent_prices_after_deleting(parent, deleted_total_sum, deleted_goods_count)
60+
update_parent_prices_after_item_deleting(parent, deleted_total_sum, deleted_goods_count)
5861
add_parents_changes_to_history(parent)
5962

6063
return Response(status=status.HTTP_200_OK)
@@ -63,12 +66,12 @@ def delete(self, request: Request, to_delete: str = None) -> Response:
6366
class NodesAPIView(views.APIView):
6467
def get(self, request: Request, to_get: str) -> Response:
6568
if not check_valid_uuid(to_get):
66-
return Response(Error(400, 'Validation Failed').to_dict(), status=status.HTTP_400_BAD_REQUEST)
69+
return Response(ERROR_400.to_dict(), status=status.HTTP_400_BAD_REQUEST)
6770

6871
found_items = ShopUnit.objects.filter(id=to_get)
6972

7073
if len(found_items) == 0:
71-
return Response(Error(404, 'Item not found').to_dict(), status=status.HTTP_404_NOT_FOUND)
74+
return Response(ERROR_404.to_dict(), status=status.HTTP_404_NOT_FOUND)
7275

7376
found_item = found_items[0]
7477

@@ -78,14 +81,15 @@ def get(self, request: Request, to_get: str) -> Response:
7881
class SalesAPIView(views.APIView):
7982
def get(self, request: Request) -> Response:
8083
if 'date' not in request.query_params:
81-
return Response(Error(400, 'Validation Failed').to_dict(), status=status.HTTP_400_BAD_REQUEST)
84+
return Response(ERROR_400.to_dict(), status=status.HTTP_400_BAD_REQUEST)
8285

8386
date_to_get: str = request.query_params['date']
8487

8588
if not check_date_iso(date_to_get):
86-
return Response(Error(400, 'Validation Failed').to_dict(), status=status.HTTP_400_BAD_REQUEST)
89+
return Response(ERROR_400.to_dict(), status=status.HTTP_400_BAD_REQUEST)
8790

8891
all_offers = ShopUnit.objects.filter(type=SHOP_UNIT_TYPES[1][1])
92+
8993
response: list = list()
9094

9195
for offer in all_offers:
@@ -98,25 +102,23 @@ def get(self, request: Request) -> Response:
98102
class NodeStatisticsAPIView(views.APIView):
99103
def get(self, request: Request, to_get: str) -> Response:
100104
if not check_valid_uuid(to_get):
101-
return Response(Error(400, 'Validation Failed').to_dict(), status=status.HTTP_400_BAD_REQUEST)
102-
103-
query_parameters = request.query_params
105+
return Response(ERROR_400.to_dict(), status=status.HTTP_400_BAD_REQUEST)
104106

105-
if 'dateStart' in query_parameters:
106-
if not check_date_iso(query_parameters['dateStart']):
107-
return Response(Error(400, 'Validation Failed').to_dict(), status=status.HTTP_400_BAD_REQUEST)
107+
if 'dateStart' in request.query_params:
108+
if not check_date_iso(request.query_params['dateStart']):
109+
return Response(ERROR_400.to_dict(), status=status.HTTP_400_BAD_REQUEST)
108110

109-
if 'dateEnd' in query_parameters:
110-
if not check_date_iso(query_parameters['dateEnd']):
111-
return Response(Error(400, 'Validation Failed').to_dict(), status=status.HTTP_400_BAD_REQUEST)
111+
if 'dateEnd' in request.query_params:
112+
if not check_date_iso(request.query_params['dateEnd']):
113+
return Response(ERROR_400.to_dict(), status=status.HTTP_400_BAD_REQUEST)
112114

113115
found_item = HistoryTable.objects.filter(id=to_get)
114116

115117
if len(found_item) == 0:
116-
return Response(Error(404, 'Item not found').to_dict(), status=status.HTTP_404_NOT_FOUND)
118+
return Response(ERROR_404.to_dict(), status=status.HTTP_404_NOT_FOUND)
117119

118-
filtered = get_node_statistics_filtered_by_date(found_item[0], query_parameters.get('dateStart'), query_parameters.get('dateEnd'))
120+
filtered = get_node_statistics_filtered_by_date(found_item[0], request.query_params.get('dateStart'), request.query_params.get('dateEnd'))
119121

120122
response: list[dict] = list(map(lambda item: shop_unit_to_dict(item, False), filtered))
121123

122-
return Response(response, status=status.HTTP_200_OK)
124+
return Response(response, status=status.HTTP_200_OK)

tests/data.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,60 @@
137137
],
138138
'updateDate': '2022-06-08T16:00:00.000Z'
139139
}
140+
141+
DATA_EMPTY_CATEGORY: dict = {
142+
'items': [
143+
{
144+
'type': 'CATEGORY',
145+
'name': 'Умные колонки',
146+
'id': '74b81fad-9cdc-4b36-8927-c123afed5cf4',
147+
'parentId': '069cb8d7-bbdd-47d3-ad8f-82ef4c269df1'
148+
}
149+
],
150+
'updateDate': '2022-06-08T16:00:00.000Z'
151+
}
152+
153+
OFFER_FOR_THIS_CATEGORY: dict = {
154+
'items': [
155+
{
156+
'type': 'OFFER',
157+
'name': 'Тындекс Станция Мега',
158+
'id': '74b81fad-9cdc-4b88-8888-c123afed5cf8',
159+
'price': 1000,
160+
'parentId': '74b81fad-9cdc-4b36-8927-c123afed5cf4'
161+
}
162+
],
163+
'updateDate': '2022-06-08T17:00:00.000Z'
164+
}
165+
166+
UPDATE_OFFER_FOR_THIS_CATEGORY: dict = {
167+
'items': [
168+
{
169+
'type': 'OFFER',
170+
'name': 'ВыНдекс Станция Мега',
171+
'id': '74b81fad-9cdc-4b88-8888-c123afed5cf8',
172+
'price': 1200,
173+
'parentId': '74b81fad-9cdc-4b36-8927-c123afed5cf4'
174+
}
175+
],
176+
'updateDate': '2022-06-08T18:00:00.000Z'
177+
}
178+
179+
LETS_MOVE_OFFER: dict = {
180+
'items': [
181+
{
182+
'type': 'CATEGORY',
183+
'name': 'Не умные колонки',
184+
'id': '74b81fad-9cdc-4b36-7777-c123afed5cf4',
185+
'parentId': '069cb8d7-bbdd-47d3-ad8f-82ef4c269df1'
186+
},
187+
{
188+
'type': 'OFFER',
189+
'name': 'ВыНдекс Станция Мега (теперь обычная колонка)',
190+
'id': '74b81fad-9cdc-4b88-8888-c123afed5cf8',
191+
'price': 1205,
192+
'parentId': '74b81fad-9cdc-4b36-7777-c123afed5cf4'
193+
}
194+
],
195+
'updateDate': '2022-06-08T19:00:00.000Z'
196+
}

0 commit comments

Comments
 (0)