Commit 286ec03f authored by John Red Medrano's avatar John Red Medrano

Merge pull request #489 in RMS/api-main-service from red-develop to RMSv2

* commit 'fe2e0b3b':
  pull latest changes on RMSv2
  added new endpoint for ETL users
parents bd79850f fe2e0b3b
from rest_framework import serializers
from app.entities.models import MasterAttachment
class BatchUploadSerializer(serializers.ModelSerializer):
class Meta:
model = MasterAttachment
fields = '__all__'
read_only_fields = (
'created', 'createdby', 'modified', 'modifiedby', 'code',
)
from rest_framework import viewsets, status
from rest_framework.response import Response
from app.entities.models import MasterAttachment
from app.applicationlayer.utils import (
CustomPagination, status_message_response, log_save
)
# from django_filters.rest_framework import DjangoFilterBackend
from app.applicationlayer.download.batch_upload.serializer import (
BatchUploadSerializer
)
import os
import configparser
config = configparser.ConfigParser()
config_file = os.path.join('./', 'env.ini')
config.read(config_file)
class BatchUploadFormatViewSet(viewsets.ModelViewSet):
queryset = MasterAttachment.objects.filter(
url__contains=config['SETTINGS']['BATCH_UPLOAD_FORMAT_FILENAME']
)
serializer_class = BatchUploadSerializer
from rest_framework import serializers from rest_framework import serializers
from app.entities.models import ExtractTransformLoad, UserHistory from app.entities.models import (
ExtractTransformLoad, UserHistory, MasterAttachment
)
class ExtractTransformLoadSerializer(serializers.ModelSerializer): class ExtractTransformLoadSerializer(serializers.ModelSerializer):
...@@ -18,3 +20,24 @@ class UserHistorySerializer(serializers.ModelSerializer): ...@@ -18,3 +20,24 @@ class UserHistorySerializer(serializers.ModelSerializer):
read_only_fields = ( read_only_fields = (
'created', 'createdby', 'modified', 'code' 'created', 'createdby', 'modified', 'code'
) )
class BatchUploadSerializer(serializers.ModelSerializer):
class Meta:
model = MasterAttachment
fields = '__all__'
read_only_fields = (
'created', 'createdby', 'modified', 'modifiedby', 'code',
)
class BatchUploadSerializer(serializers.ModelSerializer):
class Meta:
model = MasterAttachment
fields = '__all__'
read_only_fields = (
'created', 'createdby', 'modified', 'modifiedby', 'code',
)
import copy import copy, datetime
import threading import threading
import pandas as pd import pandas as pd
import csv
import io, os import io, os
from datetime import datetime
from app.entities import enums from app.entities import enums
from django.db import transaction from django.db import transaction
from app.helper import decorators from app.helper import decorators
...@@ -12,11 +12,12 @@ from rest_framework import status, viewsets ...@@ -12,11 +12,12 @@ from rest_framework import status, viewsets
from rest_framework.response import Response from rest_framework.response import Response
from app.applicationlayer.management.batchupload.serializer import ( from app.applicationlayer.management.batchupload.serializer import (
ExtractTransformLoadSerializer, ExtractTransformLoadSerializer,
UserHistorySerializer UserHistorySerializer,
BatchUploadSerializer
) )
from app.entities.models import ( from app.entities.models import (
User, Application, ExtractTransformLoad, User, Application, ExtractTransformLoad,
AllowedCompany, Company, Department, UserHistory AllowedCompany, Company, Department, UserHistory, MasterAttachment
) )
from app.applicationlayer.utils import ( from app.applicationlayer.utils import (
CustomPagination, status_message_response, CustomPagination, status_message_response,
...@@ -30,6 +31,14 @@ from app.entities import enums ...@@ -30,6 +31,14 @@ from app.entities import enums
from django_filters.rest_framework import DjangoFilterBackend from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import SearchFilter, OrderingFilter from rest_framework.filters import SearchFilter, OrderingFilter
from app.applicationlayer.management.batchupload.table_filters import ExtractTransformLoadFilter from app.applicationlayer.management.batchupload.table_filters import ExtractTransformLoadFilter
from django.db.models import F, Value
from django.core.files.base import ContentFile
import configparser
config = configparser.ConfigParser()
config_file = os.path.join('./', 'env.ini')
config.read(config_file)
class BatchUploadViewSet(viewsets.ModelViewSet): class BatchUploadViewSet(viewsets.ModelViewSet):
...@@ -49,7 +58,7 @@ class BatchUploadViewSet(viewsets.ModelViewSet): ...@@ -49,7 +58,7 @@ class BatchUploadViewSet(viewsets.ModelViewSet):
def list(self, request, *args, **kwargs): def list(self, request, *args, **kwargs):
logged_user = request.user.username logged_user = request.user.username
queryset = self.filter_queryset(self.get_queryset().filter(createdby=logged_user)) queryset = self.filter_queryset(self.get_queryset().filter(createdby=logged_user))
# queryset = self.get_queryset().filter(createdby=logged_user)
page = self.paginate_queryset(queryset) page = self.paginate_queryset(queryset)
...@@ -59,7 +68,7 @@ class BatchUploadViewSet(viewsets.ModelViewSet): ...@@ -59,7 +68,7 @@ class BatchUploadViewSet(viewsets.ModelViewSet):
message = status_message_response( message = status_message_response(
200, 200,
'success', 'success',
'list of Users found', 'list of filename found',
serializer.data serializer.data
) )
...@@ -91,16 +100,128 @@ class BatchUploadViewSet(viewsets.ModelViewSet): ...@@ -91,16 +100,128 @@ class BatchUploadViewSet(viewsets.ModelViewSet):
return self.get_paginated_response(message) return self.get_paginated_response(message)
# @decorators.error_safe @action(
detail=False, methods=['get'],
url_path='user-instruction', name='how to upload bulk users'
)
def UserInstruction(self, request, code=None):
self.serializer_class = BatchUploadSerializer
queryset = MasterAttachment.objects.filter(
url__contains=config['SETTINGS']['BATCH_UPLOAD_FORMAT_FILENAME']
)
page = self.paginate_queryset(queryset)
serializer = self.get_serializer(page, many=True)
message = status_message_response(
200,
'success',
'file been download',
serializer.data
)
return self.get_paginated_response(message)
@action(
detail=False, methods=['get'],
url_path='user-format-download', name='Users file format'
)
def UserFormat(self, request, code=None):
attach_user = MasterAttachment.objects.filter(attch_ref='etl_gen')
if attach_user:
attach_user.first().delete()
departments = Department.objects.exclude(id=1).annotate(
Privilege_Company=F('company__name'),
Privilege_Department=F('name'),
Privilege_Department_Code=F('code')
).values(
'Privilege_Company',
'Privilege_Department',
'Privilege_Department_Code'
)
data = {
'Username': ["ob-john"],
'Name': ["John Doe"],
'Company': [departments[0]['Privilege_Company']],
'Department': [departments[0]['Privilege_Department']],
'Department_Code': [departments[0]['Privilege_Department_Code']],
'Email': ["johndoe@gmail.com"],
'Contact_No': ["123456"],
'Application': ["cms,ams"],
'Default_app': ["cms"],
'Privilege_Company': [departments[0]['Privilege_Company']],
'Privilege_Department': [departments[0]['Privilege_Department']],
'Privilege_Department_Code': [departments[0]['Privilege_Department_Code']],
'Create_CR': ["Yes"],
'Create_Template': ["No"],
'View_All_CR': ["Yes"],
'Approve_CR': ["Yes"]
}
cols = ['Username', 'Name', 'Company', 'Department', 'Department_Code']
cols += ['Email', 'Contact_No', 'Application', 'Default_app']
cols += ['Privilege_Company', 'Privilege_Department', 'Privilege_Department_Code']
cols += ['Create_CR', 'Create_Template', 'View_All_CR', 'Approve_CR']
df = pd.DataFrame(data)
header = {"Privilege_Company": ['Please use this department code as reference']}
df3 = pd.DataFrame(
header
)
df2 = pd.DataFrame(
departments
)
df_row_reindex = pd.concat([df, df3, df2])
df_row_reindex = df_row_reindex.reindex(columns=cols)
df_row_reindex = df_row_reindex.to_csv(index=False)
updated_file = ContentFile(df_row_reindex)
updated_file.name = "user_format.csv"
uploaded = MasterAttachment.objects.create(
url=updated_file,
attch_ref='etl_gen'
)
self.serializer_class = BatchUploadSerializer
queryset = MasterAttachment.objects.filter(id=uploaded.id)
page = self.paginate_queryset(queryset)
serializer = self.get_serializer(page, many=True)
message = status_message_response(
200,
'success',
'List of Change Request Form found',
serializer.data
)
return Response(
{"message": message},
status=status.HTTP_400_BAD_REQUEST
)
@transaction.atomic @transaction.atomic
def create(self, request, **kwargs): def create(self, request, **kwargs):
csv_file = request.FILES['file'] csv_file = request.FILES['file']
df = pd.read_csv(csv_file, sep=',', skiprows=0) extension_file = str(csv_file).split('.')[1]
if extension_file.lower() != 'csv':
return Response(
{"message": "Only csv extension file is allowed"},
status=status.HTTP_400_BAD_REQUEST
)
df = pd.read_csv(csv_file, sep=',', skip_blank_lines=True).dropna()
# df.dropna()
logged_user_type = request.user.user_type logged_user_type = request.user.user_type
logged_user_company = request.user.department.company.name logged_user_company = request.user.department.company.name
logged_user_department = request.user.department.name logged_user_department = request.user.department.name
logged_user_email = request.user.email logged_user_email = request.user.email
email_users = [] email_users = []
department_error = 'Department should be same with the logged user'
company_error = 'Company should be same with the logged user'
etl = ExtractTransformLoad.objects.create( etl = ExtractTransformLoad.objects.create(
file_name=str(csv_file), file_name=str(csv_file),
model_type=enums.GenerateCode.USER.value model_type=enums.GenerateCode.USER.value
...@@ -115,32 +236,30 @@ class BatchUploadViewSet(viewsets.ModelViewSet): ...@@ -115,32 +236,30 @@ class BatchUploadViewSet(viewsets.ModelViewSet):
for data, keys in df.iterrows(): for data, keys in df.iterrows():
try: try:
user_department = Department.objects.filter( default_app = Application.objects.filter(
Q(name__icontains=keys['department']) & excel_code=keys['Default_app']
Q(company__name__icontains=logged_user_company)
).first()
if logged_user_type == enums_company:
user_department = Department.objects.filter(
Q(name__icontains=keys['department']) &
Q(company__name__icontains=logged_user_company)
).first() ).first()
if user_department == None:
msg = f"company is not the same with the logged user at row {data + 2}" # user type authorization and user type per user
transaction.set_rollback(True)
return Response( if request.user.user_type == enums_company:
{"message": msg}, user_company = request.user.department.company.code
status=status.HTTP_400_BAD_REQUEST request_department = Department.objects.filter(
) Q(code=keys['Department_Code']) &
elif logged_user_type == enums_department: Q(company=user_company)
user_department = Department.objects.get(
name__icontains=logged_user_department
) )
elif logged_user_type == enums_user: if not request_department:
transaction.set_rollback(True) raise ParseError(company_error)
return Response(
{"message": "Logged User is not allowed"}, elif request.user.user_type == enums_department:
status=status.HTTP_400_BAD_REQUEST if keys['Department_Code'] != request.user.department.code:
raise ParseError(
department_error
) )
<<<<<<< HEAD
# user type authorization and user type per user
=======
else: else:
user_department = Department.objects.get( user_department = Department.objects.get(
name__icontains=keys['department'] name__icontains=keys['department']
...@@ -149,32 +268,26 @@ class BatchUploadViewSet(viewsets.ModelViewSet): ...@@ -149,32 +268,26 @@ class BatchUploadViewSet(viewsets.ModelViewSet):
default_app = Application.objects.filter( default_app = Application.objects.filter(
excel_code=keys['default_app'] excel_code=keys['default_app']
).first() ).first()
>>>>>>> bd79850f02d697447131ae812adc4b42cf78960a
if keys['user_type'].lower() == 'super user' and logged_user_type == enums_super: dept_code = Department.objects.get(
user_type = enums.UserTypeEnum.SUPER_USER.value code=keys['Department_Code']
elif keys['user_type'].lower() == 'super user' and logged_user_type != enums_super:
transaction.set_rollback(True)
return Response(
{"message": f"This user is not allowed to create super user. data error at row {data + 2}"},
status=status.HTTP_201_CREATED
) )
elif keys['user_type'].lower() == 'overall user admin':
user_type = enums.UserTypeEnum.OVERALL_USER_ADMIN.value
elif keys['user_type'].lower() == 'company user admin':
user_type = enums.UserTypeEnum.COMPANY_USER_ADMIN.value
elif keys['user_type'].lower() == 'department user admin':
user_type = enums.UserTypeEnum.DEPARTMENT_USER_ADMIN.value
else:
user_type = enums.UserTypeEnum.USER.value
users = { users = {
"username": keys['username'], "username": keys['Username'],
"name": keys['name'], "name": keys['Name'],
"department": user_department, "department": dept_code,
"email": keys['email'], "email": keys['Email'],
"contact_no": keys['contact_no'], "contact_no": keys['Contact_No'],
"default_app": default_app, "default_app": default_app,
"user_type": user_type "user_type": enums_user
} }
check_user = User.objects.filter(username=keys['Username'])
if not check_user:
current_user = User.objects.create( current_user = User.objects.create(
**users **users
) )
...@@ -185,82 +298,82 @@ class BatchUploadViewSet(viewsets.ModelViewSet): ...@@ -185,82 +298,82 @@ class BatchUploadViewSet(viewsets.ModelViewSet):
current_user.save() current_user.save()
app = Application.objects.filter( app = Application.objects.filter(
excel_code__in=keys['application'].split(',') excel_code__in=keys['Application'].split(',')
) )
update_user = current_user.application.set(app) current_user.application.set(app)
current_user = User.objects.get(id=current_user.id)
for instance in keys['privilege'].split(';'):
privilege_list = instance.split(',') del users['department']
del users['contact_no']
del users['default_app']
del users['user_type']
users['file_name'] = etl2
this_company = Company.objects.filter( users['password'] = password
name__icontains=privilege_list[0] # users['admin'] = logged_user_email
).first()
this_department = Department.objects.filter( UserHistory.objects.create(
name__icontains=privilege_list[1] **users
).first() )
if privilege_list[2] == 0: elif check_user.count() > 0 and not check_user[0].date_joined.strftime('%Y-%m-%d') == datetime.now().strftime('%Y-%m-%d'):
privilege_list[2] = False # i insert it on database to make an integrity error it means this row is already exist
current_user = User.objects.create(
**users
)
else: else:
privilege_list[2] = True current_user = check_user[0]
if privilege_list[3] == 0: try:
privilege_list[3] = False privilege_department_code = keys['Privilege_Department_Code']
else: privilege_department_code = Department.objects.get(
privilege_list[3] = True code=privilege_department_code
)
if privilege_list[4] == 0: ccr = True if keys['Create_CR'] == 'Yes' else False
privilege_list[4] = False crt = True if keys['Create_Template'] == 'Yes' else False
else: view_all = True if keys['View_All_CR'] == 'Yes' else False
privilege_list[4] = True approve_cr = True if keys['Approve_CR'] == 'Yes' else False
current_user = User.objects.get(id=current_user.id) privilege_ = keys['Privilege_Department']
try:
privilege_object = { privilege_object = {
"id_number": current_user, "id_number": current_user,
"company_pivot": this_company, "company_pivot": privilege_department_code.company,
"group_pivots": this_department, "group_pivots": privilege_department_code,
"create_change_request": privilege_list[2], "create_change_request": ccr,
"create_change_request_template": privilege_list[3], "create_change_request_template": crt,
"view_all_change_request": privilege_list[4], "view_all_change_request": view_all,
"approve_cr": privilege_list[5] "approve_cr": approve_cr
} }
AllowedCompany.objects.create(**privilege_object) AllowedCompany.objects.create(**privilege_object)
except IntegrityError as e: except IntegrityError as e:
transaction.set_rollback(True)
return Response( return Response(
{"message": f"Duplicate user privilege at row {data + 2}"}, {"message": f"Duplicate user privilege at row {data + 2}"},
# {"message": str(e)},
status=status.HTTP_400_BAD_REQUEST status=status.HTTP_400_BAD_REQUEST
) )
except IntegrityError as e: except IntegrityError as e:
transaction.set_rollback(True) # etl2.delete()
# transaction.set_rollback(True)
return Response( return Response(
{"message": f"Record already exist at row {data + 2}"}, {"message": f"Record already exist at row {data + 2}"},
status=status.HTTP_400_BAD_REQUEST status=status.HTTP_400_BAD_REQUEST
) )
except KeyError as e: # except KeyError as e:
return Response( # return Response(
{"message": f"Missing column {e.args[0]}"}, # {"message": f"Missing column {e.args[0]}"},
status=status.HTTP_400_BAD_REQUEST # status=status.HTTP_400_BAD_REQUEST
) # )
del users['department'] # except ValueError as e:
del users['contact_no'] # return Response(
del users['default_app'] # {"message": f"Invalid department code. Please check at line {data + 2}"},
del users['user_type'] # status=status.HTTP_400_BAD_REQUEST
# )
users['password'] = password
UserHistory.objects.create(
**users,
file_name=etl2
)
users['admin'] = logged_user_email
send_mail = UserHistory.objects.filter(sent=False).values( send_mail = UserHistory.objects.filter(sent=False).values(
'name', 'username', 'email', 'password' 'name', 'username', 'email', 'password'
......
...@@ -15,7 +15,6 @@ from app.applicationlayer.management.delegation.views import DelegationViewSet ...@@ -15,7 +15,6 @@ from app.applicationlayer.management.delegation.views import DelegationViewSet
from app.applicationlayer.download.accounts.views import UserDownloadRequest from app.applicationlayer.download.accounts.views import UserDownloadRequest
from app.applicationlayer.download.department.views import DepartmentDownloadRequest from app.applicationlayer.download.department.views import DepartmentDownloadRequest
from app.applicationlayer.download.company.views import CompanyDownloadRequest from app.applicationlayer.download.company.views import CompanyDownloadRequest
from app.applicationlayer.download.batch_upload.views import BatchUploadFormatViewSet
router = routers.DefaultRouter() router = routers.DefaultRouter()
...@@ -29,7 +28,6 @@ router.register(r'notifications', NotificationsViewset) ...@@ -29,7 +28,6 @@ router.register(r'notifications', NotificationsViewset)
router.register(r'user-download', UserDownloadRequest) router.register(r'user-download', UserDownloadRequest)
router.register(r'department-download', DepartmentDownloadRequest) router.register(r'department-download', DepartmentDownloadRequest)
router.register(r'company-download', CompanyDownloadRequest) router.register(r'company-download', CompanyDownloadRequest)
router.register(r'batch-upload-format', BatchUploadFormatViewSet)
router.register(r'delegations', DelegationViewSet) router.register(r'delegations', DelegationViewSet)
router.register(r'extract-transform-load', BatchUploadViewSet) router.register(r'extract-transform-load', BatchUploadViewSet)
......
...@@ -9,7 +9,14 @@ from . import enums ...@@ -9,7 +9,14 @@ from . import enums
from django.utils.text import slugify from django.utils.text import slugify
from datetime import timedelta from datetime import timedelta
import os import os
<<<<<<< HEAD
<<<<<<< HEAD
=======
from django.conf import settings from django.conf import settings
>>>>>>> bd79850f02d697447131ae812adc4b42cf78960a
=======
from django.conf import settings
>>>>>>> bd79850f02d697447131ae812adc4b42cf78960a
# ********************* AUTH TABLES ********************* # ********************* AUTH TABLES *********************
...@@ -525,6 +532,14 @@ class MasterAttachment(models.Model): ...@@ -525,6 +532,14 @@ class MasterAttachment(models.Model):
null=True) null=True)
attch_ref = models.TextField() attch_ref = models.TextField()
def delete(self,*args,**kwargs):
print(self.url.name)
if os.path.isfile(self.url.path):
os.remove(self.url.path)
super(MasterAttachment, self).delete(*args,**kwargs)
class Meta: class Meta:
db_table = 'master_attachments' db_table = 'master_attachments'
......
<<<<<<< HEAD
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
...@@ -30,4 +31,38 @@ ...@@ -30,4 +31,38 @@
<img src="https://s3-ap-southeast-1.amazonaws.com/oneberry/img/logo_oneberry.png" class="img-responsive" style="width:150px;height:auto;" /> <img src="https://s3-ap-southeast-1.amazonaws.com/oneberry/img/logo_oneberry.png" class="img-responsive" style="width:150px;height:auto;" />
</body> </body>
=======
<!DOCTYPE html>
<html>
<head>
<title>RMS: Change Request Cancelled</title>
</head>
<body style="font-family: arial;">
<h3>Resource Management System &#40;RMS&#41;</h3>
<h3 style="color:#888888;">Change Request Cancelled</h3><br>
<p>Dear {name},</p><br>
<p>Your change request has been cancelled. Please see the details of the change request below.</p><br>
<b>Cancelled By</b><br>{action_by}<br><br>
<b>Routing Level</b><br>{routing_level}<br><br>
<b>Status</b><br>{status}<br><br><br>
<b>CR Number</b><br>{cr_number}<br><br>
<b>CR Name</b><br>{cr_name}<br><br>
<b>Company Requested To</b><br>{company_requestedto}<br><br>
<b>Department Requested To</b><br>{department_requestedto}<br><br>
<b>Priority Level</b><br>{priority_level}<br><br>
<p>Please click <u><a href="{url}" style="text-decoration:underline;color:#007bff;" target="_blank">here</a></u> to access your change request.</p><br>
<p>Sincerely,</p>
<p>RMS Team</p><br><br>
<p>Powered by</p>
<img src="https://s3-ap-southeast-1.amazonaws.com/oneberry/img/logo_oneberry.png" class="img-responsive" style="width:150px;height:auto;" />
</body>
>>>>>>> bd79850f02d697447131ae812adc4b42cf78960a
</html> </html>
\ No newline at end of file
<<<<<<< HEAD
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
...@@ -32,4 +33,40 @@ ...@@ -32,4 +33,40 @@
<img src="https://s3-ap-southeast-1.amazonaws.com/oneberry/img/logo_oneberry.png" class="img-responsive" style="width:150px;height:auto;" /> <img src="https://s3-ap-southeast-1.amazonaws.com/oneberry/img/logo_oneberry.png" class="img-responsive" style="width:150px;height:auto;" />
</body> </body>
=======
<!DOCTYPE html>
<html>
<head>
<title>RMS: Change Request Rejected</title>
</head>
<body style="font-family: arial;">
<h3>Resource Management System &#40;RMS&#41;</h3>
<h3 style="color:#888888;">Change Request Revision</h3><br>
<p>Dear {name},</p><br>
<p>A change request has been submitted for your acknowledgement to revise. Please see the details of the change request below.</p><br>
<b>Rejected By</b><br>{action_by}<br><br>
<b>Routing Level</b><br>{routing_level}<br><br>
<b>Status</b><br>{status}<br><br><br>
<b>CR Number</b><br>{cr_number}<br><br>
<b>CR Name</b><br>{cr_name}<br><br>
<b>Company Requested To</b><br>{company_requestedto}<br><br>
<b>Department Requested To</b><br>{department_requestedto}<br><br>
<b>Priority Level</b><br>{priority_level}<br><br>
<b>Remarks</b><br>{remarks}<br><br>
<p>Please click <u><a href="{url}" style="text-decoration:underline;color:#007bff;" target="_blank">here</a></u> to access your change request.</p><br>
<p>Sincerely,</p>
<p>RMS Team</p><br><br>
<p>Powered by</p>
<img src="https://s3-ap-southeast-1.amazonaws.com/oneberry/img/logo_oneberry.png" class="img-responsive" style="width:150px;height:auto;" />
</body>
>>>>>>> bd79850f02d697447131ae812adc4b42cf78960a
</html> </html>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment