Merge pull request #4 from SDSRV-IDP/vietanh99-request-update
Vietanh99 request update
This commit is contained in:
commit
a32506aeb4
@ -10,6 +10,9 @@ from django.db.models import Q
|
|||||||
from drf_spectacular.utils import extend_schema, OpenApiParameter, OpenApiTypes
|
from drf_spectacular.utils import extend_schema, OpenApiParameter, OpenApiTypes
|
||||||
# from drf_spectacular.types import OpenApiString
|
# from drf_spectacular.types import OpenApiString
|
||||||
from ..models import SubscriptionRequest
|
from ..models import SubscriptionRequest
|
||||||
|
from ..exception.exceptions import RequiredFieldException
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
class AccuracyViewSet(viewsets.ViewSet):
|
class AccuracyViewSet(viewsets.ViewSet):
|
||||||
@ -165,7 +168,7 @@ class AccuracyViewSet(viewsets.ViewSet):
|
|||||||
'Client Request Time (ms)': request.client_request_time,
|
'Client Request Time (ms)': request.client_request_time,
|
||||||
'Server Processing Time (ms)': request.preprocessing_time + request.ai_inference_time,
|
'Server Processing Time (ms)': request.preprocessing_time + request.ai_inference_time,
|
||||||
'Is Reviewed': request.is_reviewed,
|
'Is Reviewed': request.is_reviewed,
|
||||||
'Is Bad Quality': request.is_bad_image_quality,
|
# 'Is Bad Quality': request.is_bad_image_quality,
|
||||||
'created_at': request.created_at.isoformat()
|
'created_at': request.created_at.isoformat()
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -180,4 +183,90 @@ class AccuracyViewSet(viewsets.ViewSet):
|
|||||||
|
|
||||||
return JsonResponse(response)
|
return JsonResponse(response)
|
||||||
|
|
||||||
return JsonResponse({'error': 'Invalid request method.'}, status=405)
|
return JsonResponse({'error': 'Invalid request method.'}, status=405)
|
||||||
|
|
||||||
|
|
||||||
|
class RequestViewSet(viewsets.ViewSet):
|
||||||
|
lookup_field = "username"
|
||||||
|
|
||||||
|
@extend_schema(request = {
|
||||||
|
'multipart/form-data': {
|
||||||
|
'type': 'object',
|
||||||
|
'properties': {
|
||||||
|
'reviewed_result': {
|
||||||
|
'type': 'string',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}, responses=None, tags=['Request']
|
||||||
|
)
|
||||||
|
@action(detail=False, url_path=r"request/(?P<request_id>[\w\-]+)", methods=["GET", "POST"])
|
||||||
|
def get_subscription_request(self, request, request_id=None):
|
||||||
|
if request.method == 'GET':
|
||||||
|
base_query = Q(request_id=request_id)
|
||||||
|
|
||||||
|
subscription_request = SubscriptionRequest.objects.filter(base_query).first()
|
||||||
|
|
||||||
|
data = []
|
||||||
|
|
||||||
|
imeis = []
|
||||||
|
purchase_date = []
|
||||||
|
retailer = ""
|
||||||
|
try:
|
||||||
|
if subscription_request.reviewed_result is not None:
|
||||||
|
imeis = subscription_request.reviewed_result.get("imei_number", [])
|
||||||
|
purchase_date = subscription_request.reviewed_result.get("purchase_date", [])
|
||||||
|
retailer = subscription_request.reviewed_result.get("retailername", "")
|
||||||
|
elif subscription_request.feedback_result is not None :
|
||||||
|
imeis = subscription_request.feedback_result.get("imei_number", [])
|
||||||
|
purchase_date = subscription_request.feedback_result.get("purchase_date", [])
|
||||||
|
retailer = subscription_request.feedback_result.get("retailername", "")
|
||||||
|
elif subscription_request.predict_result is not None:
|
||||||
|
if subscription_request.predict_result.get("status", 404) == 200:
|
||||||
|
imeis = subscription_request.predict_result.get("content", {}).get("document", [])[0].get("content", [])[3].get("value", [])
|
||||||
|
purchase_date = subscription_request.predict_result.get("content", {}).get("document", [])[0].get("content", [])[2].get("value", [])
|
||||||
|
retailer = subscription_request.predict_result.get("content", {}).get("document", [])[0].get("content", [])[0].get("value", [])
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[ERROR]: {e}")
|
||||||
|
print(f"[ERROR]: {subscription_request}")
|
||||||
|
data.append({
|
||||||
|
'RequestID': subscription_request.request_id,
|
||||||
|
'RedemptionID': subscription_request.redemption_id,
|
||||||
|
'IMEIs': imeis,
|
||||||
|
'Purchase Date': purchase_date,
|
||||||
|
'Retailer': retailer,
|
||||||
|
'Reviewed result': subscription_request.reviewed_result,
|
||||||
|
'Feedback result': subscription_request.feedback_result,
|
||||||
|
'Client Request Time (ms)': subscription_request.client_request_time,
|
||||||
|
'Server Processing Time (ms)': subscription_request.preprocessing_time + subscription_request.ai_inference_time,
|
||||||
|
'Is Reviewed': subscription_request.is_reviewed,
|
||||||
|
# 'Is Bad Quality': subscription_request.is_bad_image_quality,
|
||||||
|
'created_at': subscription_request.created_at.isoformat(),
|
||||||
|
'updated_at': subscription_request.updated_at.isoformat()
|
||||||
|
})
|
||||||
|
|
||||||
|
response = {
|
||||||
|
'subscription_requests': data
|
||||||
|
}
|
||||||
|
|
||||||
|
return JsonResponse(response)
|
||||||
|
|
||||||
|
elif request.method == 'POST':
|
||||||
|
data = request.data
|
||||||
|
|
||||||
|
base_query = Q(request_id=request_id)
|
||||||
|
|
||||||
|
subscription_request = SubscriptionRequest.objects.filter(base_query).first()
|
||||||
|
|
||||||
|
reviewed_result = json.loads(data["reviewed_result"][1:-1])
|
||||||
|
for field in ['retailername', 'sold_to_party', 'purchase_date', 'imei_number']:
|
||||||
|
if not field in reviewed_result.keys():
|
||||||
|
raise RequiredFieldException(excArgs=f'reviewed_result.{field}')
|
||||||
|
subscription_request.reviewed_result = reviewed_result
|
||||||
|
subscription_request.reviewed_result['request_id'] = request_id
|
||||||
|
subscription_request.is_reviewed = True
|
||||||
|
subscription_request.save()
|
||||||
|
|
||||||
|
return JsonResponse({'message': 'success.'}, status=200)
|
||||||
|
else:
|
||||||
|
return JsonResponse({'error': 'Invalid request method.'}, status=405)
|
@ -2,7 +2,7 @@ from django.conf import settings
|
|||||||
from rest_framework.routers import DefaultRouter, SimpleRouter
|
from rest_framework.routers import DefaultRouter, SimpleRouter
|
||||||
|
|
||||||
from fwd_api.api.ctel_view import CtelViewSet
|
from fwd_api.api.ctel_view import CtelViewSet
|
||||||
from fwd_api.api.accuracy_view import AccuracyViewSet
|
from fwd_api.api.accuracy_view import AccuracyViewSet, RequestViewSet
|
||||||
|
|
||||||
from fwd_api.api.ctel_user_view import CtelUserViewSet
|
from fwd_api.api.ctel_user_view import CtelUserViewSet
|
||||||
|
|
||||||
@ -16,6 +16,7 @@ else:
|
|||||||
router.register("ctel", CtelViewSet, basename="CtelAPI")
|
router.register("ctel", CtelViewSet, basename="CtelAPI")
|
||||||
router.register("ctel", CtelUserViewSet, basename="CtelUserAPI")
|
router.register("ctel", CtelUserViewSet, basename="CtelUserAPI")
|
||||||
router.register("ctel", AccuracyViewSet, basename="AccuracyAPI")
|
router.register("ctel", AccuracyViewSet, basename="AccuracyAPI")
|
||||||
|
router.register("ctel", RequestViewSet, basename="RequestAPI")
|
||||||
|
|
||||||
app_name = "api"
|
app_name = "api"
|
||||||
urlpatterns = router.urls
|
urlpatterns = router.urls
|
||||||
|
@ -19,6 +19,9 @@ from ..celery_worker.client_connector import c_connector
|
|||||||
import imagesize
|
import imagesize
|
||||||
import csv
|
import csv
|
||||||
|
|
||||||
|
from openpyxl import load_workbook
|
||||||
|
from openpyxl.styles import Font, Border, Side, PatternFill, NamedStyle
|
||||||
|
|
||||||
def validate_feedback_file(csv_file_path):
|
def validate_feedback_file(csv_file_path):
|
||||||
required_columns = ['redemptionNumber', 'requestId', 'imeiNumber', 'imeiNumber2', 'Purchase Date', 'retailer', 'Sold to party', 'timetakenmilli']
|
required_columns = ['redemptionNumber', 'requestId', 'imeiNumber', 'imeiNumber2', 'Purchase Date', 'retailer', 'Sold to party', 'timetakenmilli']
|
||||||
missing_columns = []
|
missing_columns = []
|
||||||
@ -327,21 +330,122 @@ def build_media_url_v2(media_id: str, user_id: int, sub_id: int, u_sync_id: str)
|
|||||||
token = image_authenticator.generate_img_token_v2(user_id, sub_id, u_sync_id)
|
token = image_authenticator.generate_img_token_v2(user_id, sub_id, u_sync_id)
|
||||||
return f'{settings.BASE_URL}/api/ctel/v2/media/request/{media_id}/?token={token}'
|
return f'{settings.BASE_URL}/api/ctel/v2/media/request/{media_id}/?token={token}'
|
||||||
|
|
||||||
def json2xlsx(input: json):
|
|
||||||
"""_summary_
|
|
||||||
|
|
||||||
Args:
|
def get_value(_dict, keys):
|
||||||
input (json):
|
keys = keys.split('.')
|
||||||
: [{
|
value = _dict
|
||||||
Subs: Jan, # Subtotal name
|
for key in keys:
|
||||||
Metadata: {num_imei: 1,
|
if not key in value.keys():
|
||||||
...: ...}
|
return "-"
|
||||||
Data: [{num_imei: 1,
|
else:
|
||||||
...: ...}]
|
value = value.get(key, {})
|
||||||
}]
|
|
||||||
OR
|
if value != 0:
|
||||||
input (json):
|
return value
|
||||||
: []
|
else:
|
||||||
Return xlsx (object)
|
return "-"
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
def dict2xlsx(input: json, _type='report'):
|
||||||
|
red = "FF0000"
|
||||||
|
black = "000000"
|
||||||
|
green = "E2EFDA"
|
||||||
|
yellow = "FFF2CC"
|
||||||
|
gray = "D0CECE"
|
||||||
|
font_black = Font(name="Calibri", size=11, color=black)
|
||||||
|
font_black_bold = Font(name="Calibri", size=11, color=black, bold=True)
|
||||||
|
font_red = Font(name="Calibri", size=11, color=red)
|
||||||
|
thin = Side(border_style="thin", color=black)
|
||||||
|
border = Border(left=thin, right=thin, top=thin, bottom=thin)
|
||||||
|
fill_green = PatternFill(start_color=green, end_color=green, fill_type = "solid")
|
||||||
|
fill_yellow = PatternFill(start_color=yellow, end_color=yellow, fill_type = "solid")
|
||||||
|
fill_gray = PatternFill(start_color=gray, end_color=gray, fill_type = "solid")
|
||||||
|
normal_cell = NamedStyle(name="normal_cell", font=font_black, border=border)
|
||||||
|
normal_cell_red = NamedStyle(name="normal_cell_red", font=font_red, border=border)
|
||||||
|
|
||||||
|
if _type == 'report':
|
||||||
|
wb = load_workbook(filename = 'report.xlsx')
|
||||||
|
ws = wb['Sheet1']
|
||||||
|
mapping = {
|
||||||
|
'A': 'subs',
|
||||||
|
'B': 'extraction_date',
|
||||||
|
'C': 'num_imei',
|
||||||
|
'D': 'num_invoice',
|
||||||
|
'E': 'total_images',
|
||||||
|
'F': 'images_quality.successful',
|
||||||
|
'G': 'images_quality.successful_percent',
|
||||||
|
'H': 'images_quality.bad',
|
||||||
|
'I': 'images_quality.bad_percent',
|
||||||
|
'J': 'average_accuracy_rate.imei',
|
||||||
|
'K': 'average_accuracy_rate.purchase_date',
|
||||||
|
'L': 'average_accuracy_rate.retailer_name',
|
||||||
|
'M': 'average_processing_time.imei',
|
||||||
|
'N': 'average_processing_time.invoice',
|
||||||
|
'O': 'usage.imei',
|
||||||
|
'P': 'usage.invoice',
|
||||||
|
}
|
||||||
|
start_index = 5
|
||||||
|
|
||||||
|
elif _type == 'report_detail':
|
||||||
|
wb = load_workbook(filename = 'report_detail.xlsx')
|
||||||
|
ws = wb['Sheet1']
|
||||||
|
mapping = {
|
||||||
|
'A': 'request_id',
|
||||||
|
'B': 'redemption_number',
|
||||||
|
'C': 'image_type',
|
||||||
|
'D': 'imei_user_submitted',
|
||||||
|
'E': "imei_ocr_retrieved",
|
||||||
|
'F': "imei1_accuracy",
|
||||||
|
'G': "purchase_date_user_submitted",
|
||||||
|
'H': "purchase_date_ocr_retrieved",
|
||||||
|
'I': "purchase_date_accuracy",
|
||||||
|
'J': "retailer_user_submitted",
|
||||||
|
'K': "retailer_ocr_retrieved",
|
||||||
|
'L': "retailer_accuracy",
|
||||||
|
'M': "average_accuracy",
|
||||||
|
'N': "ocr_processing_time",
|
||||||
|
'O': "is_reviewed",
|
||||||
|
'P': "bad_image_reasons",
|
||||||
|
'Q': "countermeasures",
|
||||||
|
}
|
||||||
|
start_index = 4
|
||||||
|
|
||||||
|
for subtotal in input:
|
||||||
|
for key_index, key in enumerate(mapping.keys()):
|
||||||
|
value = get_value(subtotal, mapping[key])
|
||||||
|
ws[key + str(start_index)] = value
|
||||||
|
ws[key + str(start_index)].border = border
|
||||||
|
|
||||||
|
if _type == 'report':
|
||||||
|
ws[key + str(start_index)].font = font_black_bold
|
||||||
|
if key_index == 0 or (key_index >= 9 and key_index <= 15):
|
||||||
|
ws[key + str(start_index)].fill = fill_gray
|
||||||
|
elif key_index >= 4 and key_index <= 8:
|
||||||
|
ws[key + str(start_index)].fill = fill_yellow
|
||||||
|
elif _type == 'report_detail':
|
||||||
|
if 'accuracy' in mapping[key] and type(value) in [int, float] and value < 95:
|
||||||
|
ws[key + str(start_index)].style = normal_cell_red
|
||||||
|
elif 'time' in mapping[key] and type(value) in [int, float] and value > 2.0:
|
||||||
|
ws[key + str(start_index)].style = normal_cell_red
|
||||||
|
else:
|
||||||
|
ws[key + str(start_index)].style = normal_cell
|
||||||
|
|
||||||
|
start_index += 1
|
||||||
|
|
||||||
|
if 'data' in subtotal.keys():
|
||||||
|
for record in subtotal['data']:
|
||||||
|
for key in mapping.keys():
|
||||||
|
value = get_value(record, mapping[key])
|
||||||
|
ws[key + str(start_index)] = value
|
||||||
|
if 'average_accuracy_rate' in mapping[key] and type(value) in [int, float] and value < 95:
|
||||||
|
ws[key + str(start_index)].style = normal_cell_red
|
||||||
|
elif 'average_processing_time' in mapping[key] and type(value) in [int, float] and value > 2.0:
|
||||||
|
ws[key + str(start_index)].style = normal_cell_red
|
||||||
|
elif 'bad_percent' in mapping[key] and type(value) in [int, float] and value > 10:
|
||||||
|
ws[key + str(start_index)].style = normal_cell_red
|
||||||
|
else :
|
||||||
|
ws[key + str(start_index)].style = normal_cell
|
||||||
|
|
||||||
|
start_index += 1
|
||||||
|
|
||||||
|
return wb
|
||||||
|
BIN
cope2n-api/report.xlsx
Normal file
BIN
cope2n-api/report.xlsx
Normal file
Binary file not shown.
BIN
cope2n-api/report_detail.xlsx
Normal file
BIN
cope2n-api/report_detail.xlsx
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user