Esempio n. 1
0
def view(request):
    """
    Standard view for dashboard, is empty as all data will be requested through AJAX
    """
    get_admin_executive_or_403(request)

    return render(request, 'dashboard.html')
Esempio n. 2
0
def ajax_roles_from_tuple(request):
    """
    parameters:
    project_id: ID del proyecto seleccionado
    department_id: ID del proyecto seleccionado

    returns:
    lista de objetos {id, nombre} de los roles seleccionables
    """

    logged = get_admin_executive_or_403(request)
    if "project_id" not in request.GET or "department_id" not in request.GET:
        raise SuspiciousOperation

    if is_executive(logged):
        roles = Role.objects.filter(tier__lt=50)
    elif logged.user_type == "E":
        try:
            myrole = ProjectDepartmentEmployeeRole.objects.get(
                employee_id=logged,
                projectDepartment_id__project_id__id=request.GET["project_id"],
                projectDepartment_id__department_id__id=request.
                GET["department_id"])
            roles = Role.objects.filter(tier__lt=myrole.role_id.tier)
        except:
            raise PermissionDenied
    else:
        roles = Role.objects.all()

    data = []
    for r in roles:
        data.append({'id': r.id, 'name': r.name})

    return JsonResponse(data, safe=False)
Esempio n. 3
0
def manage_async(request):
    """
    parameters:
    form: el formulario con los datos del departamento

    returns:

    JSON con un mensaje de respuesta. Es un dict que contiene lo siguiente
    success: true si hubo exito, false si no
    errors: array de códigos de error (vacío si success == true)
    """

    logged = get_admin_executive_or_403(request)

    if request.method == 'POST':

        form = RoleManagementForm(request.POST)
        if form.is_valid():
            result = process_post_form(logged, form)
            return JsonResponse({
                'success': result["ok"],
                'errors': result['errors']
            })
        else:
            return JsonResponse({
                'success': False,
                'errors': ['roleCreation_formNotValid']
            })
    else:
        raise SuspiciousOperation
Esempio n. 4
0
def ajax_departments_from_projects(request):
    """
    parameters:
    project_id: ID del proyecto seleccionado

    returns:
    lista de objetos {id, nombre} de los departamentos seleccionables
    """

    logged = get_admin_executive_or_403(request)
    if "project_id" not in request.GET:
        raise SuspiciousOperation

    if logged.user_type == "E" and not is_executive(logged):
        ids = ProjectDepartmentEmployeeRole.objects.values_list(
            'projectDepartment_id__department_id', flat=True).filter(
                employee_id=logged,
                role_id__tier__gt=10,
                projectDepartment_id__department_id__active=True,
                projectDepartment_id__project_id__id=request.GET["project_id"])
        dpts = Department.objects.filter(id__in=ids)
    else:
        dpts = Department.objects.filter(active=True,
                                         company_id=logged.company_id)

    data = []
    for d in dpts:
        data.append({'id': d.id, 'name': d.name})

    return JsonResponse(data, safe=False)
Esempio n. 5
0
def recover(request, username):
    """
    url = employee/recover/<username>

    parameters/returns:
    Nada, redirecciona a la vista de listado de empleados

    template: ninguna
    """

    admin = get_admin_executive_or_403(request)
    employee = get_object_or_404(Employee,
                                 user__username=username,
                                 user__is_active=False)

    # Check that the admin has permission to view that employee
    same_company_or_403(admin, employee)

    employee_user = employee.user
    employee_user.is_active = True
    employee_user.save()

    EmployeeLog.objects.create(employee_id=employee,
                               event="A",
                               price_per_hour=employee.price_per_hour)
    return HttpResponseRedirect('/employee/list')
Esempio n. 6
0
def edit(request, department_id):
    """
    url = department/edit/(department_id)/

    parameters/returns:
    form: el formulario con los datos del departamento
    repeated_name:true si el nombre ya existe para otro departamento

    template:
    department_form.html
    """

    # Check that the current user is an administrator or executive
    department = get_object_or_404(Department, pk=department_id)
    admin = get_admin_executive_or_403(request)
    same_company_or_403(admin, department)

    repeated_name = False

    # if this is a POST request we need to process the form data
    if request.method == 'POST':
        # create a form instance and populate it with data from the request:
        form = DepartmentForm(request.POST)
        # check whether it's valid:
        if form.is_valid():
            # process the data in form.cleaned_data as required
            # ...
            # redirect to a new URL:

            dep = find_name(form.cleaned_data['name'], admin)
            # dep does not exists or it's the same
            if dep is None or dep.id == department.id:
                edit_department(department, form)
                return HttpResponseRedirect('/department/view/' +
                                            str(department.id) + "/")
            else:
                repeated_name = True
    # if a GET (or any other method) we'll create a blank form
    else:
        department = get_object_or_404(Department, pk=department_id)
        form = DepartmentForm(initial={
            "name": department.name,
            "department_id": department.id
        })

    return render(request, 'department/department_form.html', {
        'form': form,
        'repeated_name': repeated_name
    })
Esempio n. 7
0
def ajax_time_per_project(request):
    """ Devuelve un objeto cuyas claves son las ID de los proyectos y sus valores un objeto {'name': ..., 'time': X} (X en minutos)

    # Parámetros opcionales:
    # start_date - fecha en formato YYYY-MM-DD que indica el inicio de la medición. Por defecto, 30 días antes de la fecha actual.
    # end_date - fecha en formato YYYY-MM-DD que indica el final de la medición. Por defecto, fecha actual.
    # offset - desplazamiento (huso) horario en formato +/-HH:MM - Por defecto +00:00

    # Si se proporcionan pero no tienen el formato correcto se lanzará un error HTTP 400 Bad Request
    """
    logged = get_admin_executive_or_403(request)

    # Get and parse the dates
    start_date = request.GET.get("start_date",
                                 str(date.today() - timedelta(days=30)))
    end_date = request.GET.get("end_date", str(date.today()))
    date_regex = re.compile("^\d{4}-\d{2}-\d{2}$")

    if date_regex.match(start_date) is None or date_regex.match(
            end_date) is None:
        raise SuspiciousOperation("Start/end date are not valid")

    offset = request.GET.get("offset", "+00:00")
    offset_regex = re.compile("^(\+|-)\d{2}:\d{2}$")

    if offset_regex.match(offset) is None:
        raise SuspiciousOperation("Time offset is not valid")

    # Append time offsets
    start_date += " 00:00" + offset
    end_date += " 00:00" + offset

    company_projects = Project.objects.filter(deleted=False,
                                              company_id=logged.company_id)

    data = {}
    # Sum timelogs for each project
    for project in company_projects:
        time_total = TimeLog.objects.filter(
            task_id__active=True,
            task_id__projectDepartment_id__project_id=project,
            workDate__range=[start_date, end_date
                             ]).aggregate(Sum('duration'))["duration__sum"]
        if time_total is None:
            time_total = 0

        data[project.id] = {'name': project.name, 'time': time_total}

    return JsonResponse(data)
Esempio n. 8
0
def edit(request, project_id):
    """
    parameters/returns:
    form: el formulario con los datos del proyecto

    template:
    project_form.html
    """
    # Check that the user is logged in
    admin = get_admin_executive_or_403(request)
    project = get_object_or_404(Project, pk=project_id)
    same_company_or_403(admin, project)

    repeated_name = False
    error = False
    # if this is a POST request we need to process the form data
    if request.method == 'POST':
        # create a form instance and populate it with data from the request:
        form = ProjectForm(request.POST)
        # check whether it's valid:
        if form.is_valid():
            # process the data in form.cleaned_data as required
            pro = find_name(form.cleaned_data['name'], admin)
            # pro does not exists or it's the same
            if pro is None or pro.id == project.id:
                update_project(project, form)
                return redirect('project_list')
            else:
                repeated_name = True
        else:
            error = True

    # if a GET (or any other method) we'll create a blank form
    else:
        #Check is same company
        form = ProjectForm(initial={
            "name": project.name,
            "project_id": project.id
        })

    return render(request, 'project/project_form.html', {
        'form': form,
        'repeated_name': repeated_name,
        'error': error
    })
Esempio n. 9
0
def delete(request, project_id):
    """
    parameters:
    project_id: the project id to delete

    returns:
    nothing

    template:
    project_list.html
    """
    # Check that the user is logged in
    admin = get_admin_executive_or_403(request)
    project = get_object_or_404(Project, pk=project_id, deleted=False)
    same_company_or_403(admin, project)
    delete_project(project)

    return HttpResponseRedirect('/project/list')
Esempio n. 10
0
def ajax_departments_per_project(request):
    """
    Gets the number of departments per project
    """

    logged = get_admin_executive_or_403(request)
    company_projects = Project.objects.filter(deleted=False,
                                              company_id=logged.company_id)
    data = {}
    for project in company_projects:
        data[project.id] = {
            'name':
            project.name,
            'departments':
            list(
                Department.objects.filter(
                    projectdepartment__project_id=project).values(
                        'id', 'name'))
        }
    return JsonResponse(data)
Esempio n. 11
0
def recover(request, department_id):
    """
    url = department/recover/(department_id)/
    parameters:
    department_id: the department id to recover

    returns:
    nothing

    template:
    deparment_list.html
    """
    department = get_object_or_404(Department, pk=department_id, active=False)
    # Check that the current user is an administrator or executive
    admin = get_admin_executive_or_403(request)
    same_company_or_403(admin, department)

    recover_department(department)

    return HttpResponseRedirect('/department/list')
Esempio n. 12
0
def ajax_employees_per_project(request):
    """
    Gets the number of employees per project
    """

    logged = get_admin_executive_or_403(request)
    company_projects = Project.objects.filter(deleted=False,
                                              company_id=logged.company_id)
    data = {}
    for project in company_projects:
        data[project.id] = {
            'name':
            project.name,
            'employees':
            list(
                Employee.objects.filter(
                    projectdepartmentemployeerole__projectDepartment_id__project_id
                    =project).values('id', 'identifier', 'user__username',
                                     'registryDate'))
        }
    return JsonResponse(data)
Esempio n. 13
0
def create(request):
    """
    parameters/returns:
    form: el formulario con los datos del departamento
    repeated_name:true si el nombre ya existe para otro departamento

    template:
    department_form.html
    """

    # Check that the current user is an administrator
    admin = get_admin_executive_or_403(request)
    repeated_name = False

    # if this is a POST request we need to process the form data
    if request.method == 'POST':
        # create a form instance and populate it with data from the request:
        form = DepartmentForm(request.POST)
        # check whether it's valid:
        if form.is_valid():
            # process the data in form.cleaned_data as required
            # ...
            # redirect to a new URL:
            dname = form.cleaned_data['name']
            dep = find_name(dname, admin)
            if dep is not None:
                repeated_name = True
            else:
                department = create_department(form, admin)
                return HttpResponseRedirect('/department/view/' +
                                            str(department.id) + "/")

    # if a GET (or any other method) we'll create a blank form
    else:
        form = DepartmentForm(initial={"department_id": 0, "name": ""})

    return render(request, 'department/department_form.html', {
        'form': form,
        'repeated_name': repeated_name
    })
Esempio n. 14
0
def create_async(request):
    """
    parameters:
    form: el formulario con los datos del proyecto

    returns:
    data: JSON con un mensaje de respuesta. Es un dict que contiene lo siguiente
    repeated_name: true si se ha repetido el nombre
    success:true si hubo exito, false si no

    """

    # Check that the current user is an administrator
    admin = get_admin_executive_or_403(request)

    data = {'repeated_name': False, 'success': True}

    # if this is a POST request we need to process the form data
    if request.method == 'POST':
        # create a form instance and populate it with data from the request:
        form = ProjectForm(request.POST)
        # check whether it's valid:
        if form.is_valid():
            # process the data in form.cleaned_data as required
            # ...
            # redirect to a new URL:
            pname = form.cleaned_data['name']
            pro = find_name(pname, admin)
            if pro is not None:
                data['repeated_name'] = True
            else:
                create_project(form, admin)
                return JsonResponse(data)

    # if a GET (or any other method) we'll create a blank form
    else:
        return redirect('project_list')

    data['success'] = False
    return JsonResponse(data)
Esempio n. 15
0
def create(request):
    """
    parameters/returns:
    form: el formulario con los datos del proyecto

    template:
    project_form.html
    """
    # Check that the user is logged in
    admin = get_admin_executive_or_403(request)
    repeated_name = False
    error = False
    # if this is a POST request we need to process the form data
    if request.method == 'POST':
        # create a form instance and populate it with data from the request:
        form = ProjectForm(request.POST)
        # check whether it's valid:
        if form.is_valid():
            # process the data in form.cleaned_data as required
            # ...
            # redirect to a new URL:
            pname = form.cleaned_data['name']
            pro = find_name(pname, admin)
            if pro is not None:
                repeated_name = True
            else:
                project = create_project(form, admin)
                return redirect('project_view', project_id=project.id)
        else:
            error = True
    # if a GET (or any other method) we'll create a blank form
    else:
        form = ProjectForm(initial={"project_id": 0})

    return render(request, 'project/project_form.html', {
        'form': form,
        'repeated_name': repeated_name,
        'error': error
    })
Esempio n. 16
0
def delete(request, role_id):
    """
    url: /roles/delete/<role_id>

    parameters/returns:
    role_id: id del rol a borrar

    returns: redirecciona a la vista del empleado en cuestión o devuelve 404 (si no existe) / 403 (si no está autorizado)

    El botón de borrar sólo se debería mostrar si el usuario en cuestión está autorizado a borrar el rol, por lo que no se devuelven códigos de error.
    """

    logged = get_admin_executive_or_403(request)
    role = get_object_or_404(ProjectDepartmentEmployeeRole, id=role_id)
    check_companies_match(logged, role.employee_id)

    if not is_role_updatable_by_user(logged, role_id):
        raise PermissionDenied

    employee_username = role.employee_id.user.username
    role.delete()

    return HttpResponseRedirect('/employee/view/' + employee_username)
Esempio n. 17
0
def update_password(request, username):
    """
    url = employee/updatePassword/<username>

    parameters:
        password1: contraseña a establecer
        password2: repetición de la contraseña

    returns:
        {'success': true/false: 'errors': [...]}

    errors:
        'employeeCreation_formNotValid': si el formulario no es válido
        'employeeCreation_passwordsDontMatch' : si las contraseñas no coinciden

    template: ninguna (ajax)
    """

    # Check that the user is logged in and it's an administrator
    admin = get_admin_executive_or_403(request)
    employee = get_object_or_404(Employee,
                                 user__username=username,
                                 user__is_active=True)

    # Check that the admin has permission to view that employee
    same_company_or_403(admin, employee)

    if request.method == 'POST':
        # Process the form
        form = EmployeePasswordForm(request.POST)

        if form.is_valid():
            pass1 = form.cleaned_data["newpass1"]
            pass2 = form.cleaned_data["newpass2"]

            # Check password validation
            if not validate_pass(pass1):
                return JsonResponse({
                    'success': False,
                    'errors': ['newPasswordInvalid']
                })

            if pass1 != pass2:
                return JsonResponse({
                    'success':
                    False,
                    'errors': ['employeeCreation_passwordsDontMatch']
                })

            user = employee.user
            user.set_password(pass1)
            user.save()

            if form.cleaned_data["send_password_notification"]:
                notify_password_change(
                    user.email,
                    user.first_name,
                    newpass=pass1,
                    notifynewpass=form.cleaned_data["notify_new_pass"])

            return JsonResponse({'success': True, 'errors': []})
        else:
            # Invalid form
            return JsonResponse({
                'success': False,
                'errors': ['employeeCreation_formNotValid']
            })
    else:
        # Invalid HTTP operation
        raise SuspiciousOperation
Esempio n. 18
0
def create(request):
    """
    parameters:
        redirect: opcional, incluir en la URL de la petición si se quiere redirigir a la página del empleado creado
    returns:
        form: formulario con los datos necesarios para el registro del empleado
        success: opcional, si se ha tenido éxito al crear un empleado
        errors: opcional, array de mensajes de error si ha habido algún error

    errores: (todos empiezan por employeeCreation_)
        passwordsDontMatch: las contraseñas no coinciden
        usernameNotUnique: el nombre de usuario ya existe
        imageNotValid: la imagen no es válida por formato y/o tamaño
        formNotValid: el formulario contiene errores
        priceNotValid: el precio debe ser mayor que 0
        emailNotUnique:si el correo no es úinco

    template:
        employee_register.html
    """

    # Check that the user is logged in and it's an administrator
    admin = get_admin_executive_or_403(request)

    # If it's a GET request, return an empty form
    if request.method == "GET":
        return render(request, 'employee/employee_register.html',
                      {'form': EmployeeRegisterForm()})

    elif request.method == "POST":
        # We are serving a POST request
        form = EmployeeRegisterForm(request.POST, request.FILES)

        if form.is_valid():

            errors = []

            # Check that the passwords match
            if not check_passwords(form):
                errors.append('employeeCreation_passwordsDontMatch')

            #Check password validation
            if not validate_pass(form.cleaned_data["password1"]):
                errors.append('newPasswordInvalid')

            # Check that the username is unique
            if not is_username_unique(form.cleaned_data["username"]):
                errors.append('employeeCreation_usernameNotUnique')

            # Check that the email is unique
            if not is_email_unique(form.cleaned_data["email"]):
                errors.append('employeeCreation_emailNotUnique')

            # Check that the image is OK
            if not check_image(form, 'photo'):
                errors.append('employeeCreation_imageNotValid')

            # Check that the price is OK
            if form.cleaned_data['price_per_hour'] <= 0:
                errors.append('employeeCreation_priceNotValid')

            if not errors:
                # Everything is OK, create the employee
                employee_user = create_employee_user(form)
                employee = create_employee(employee_user, admin, form)
                EmployeeLog.objects.create(
                    employee_id=employee,
                    event="A",
                    price_per_hour=employee.price_per_hour)
                send_register_email(form.cleaned_data["email"],
                                    form.cleaned_data["first_name"])

                return HttpResponseRedirect('/employee/view/' +
                                            form.cleaned_data["username"] +
                                            '/')

            else:
                # There are errors
                return render(request, 'employee/employee_register.html', {
                    'form': form,
                    'errors': errors
                })

        # Form is not valid
        else:
            return render(request, 'employee/employee_register.html', {
                'form': form,
                'errors': ['employeeCreation_formNotValid']
            })
    else:
        # Another request method
        raise PermissionDenied
Esempio n. 19
0
def edit(request, username):
    """
    url = employee/edit/<username>

    parameters/returns:
        form: formulario de edicion de datos de empleado

    errors:
        'employeeCreation_formNotValid': si el formulario no es válido

    template: employee_edit.html
    """

    # Check that the user is logged in and it's an administrator
    admin = get_admin_executive_or_403(request)
    employee = get_object_or_404(Employee, user__username=username)

    # Check that the admin has permission to view that employee
    same_company_or_403(admin, employee)

    if request.method == "GET":
        # Return a form filled with the employee's data
        form = EmployeeEditForm(
            initial={
                'first_name': employee.user.first_name,
                'last_name': employee.user.last_name,
                'email': employee.user.email,
                'identifier': employee.identifier,
                'phone': employee.phone,
                'price_per_hour': employee.price_per_hour
            })

        return render(
            request, 'employee/employee_edit.html', {
                'form': form,
                'picture': employee.picture,
                'username': username,
                'pass_form': EmployeePasswordForm(),
                'active': employee.user.is_active
            })

    elif request.method == "POST":
        # Process the received form

        form = EmployeeEditForm(request.POST, request.FILES)
        if form.is_valid():
            errors = []
            # Check that the price is OK
            if form.cleaned_data['price_per_hour'] <= 0:
                errors.append('employeeCreation_priceNotValid')

            # Check that the image is OK
            if not check_image(form, 'photo'):
                errors.append('employeeCreation_imageNotValid')

            # Check that the email is unique
            if not is_email_unique(
                    form.cleaned_data["email"]
            ) and employee.user.email != form.cleaned_data["email"]:
                errors.append('employeeCreation_emailNotUnique')

            if not errors:
                # Update employee data
                employee.identifier = form.cleaned_data["identifier"]
                employee.phone = form.cleaned_data["phone"]
                # New log if the salary has changed
                new_log = employee.price_per_hour != form.cleaned_data[
                    "price_per_hour"]

                employee.price_per_hour = form.cleaned_data["price_per_hour"]
                if form.cleaned_data["photo"]:
                    employee.picture = form.cleaned_data["photo"]

                # Update user data
                user = employee.user
                user.first_name = form.cleaned_data["first_name"]
                user.last_name = form.cleaned_data["last_name"]
                user.email = form.cleaned_data["email"]

                user.save()
                employee.save()

                # New log if the salary has changed
                if new_log:
                    EmployeeLog.objects.create(
                        employee_id=employee,
                        event="C",
                        price_per_hour=form.cleaned_data["price_per_hour"])
                return HttpResponseRedirect('/employee/view/' + username + '/')
            else:
                # There are errors
                return render(
                    request, 'employee/employee_edit.html', {
                        'form': form,
                        'errors': errors,
                        'picture': employee.picture,
                        'username': username,
                        'pass_form': EmployeePasswordForm(),
                        'active': employee.user.is_active
                    })

        else:
            # Form is not valid
            return render(
                request, 'employee/employee_edit.html', {
                    'form': form,
                    'picture': employee.picture,
                    'errors': ['employeeCreation_formNotValid'],
                    'username': username,
                    'pass_form': EmployeePasswordForm(),
                    'active': employee.user.is_active
                })
    else:
        raise PermissionDenied
Esempio n. 20
0
def display_info(request):
    get_admin_executive_or_403(request)
    return render(request, "role/role_info.html")
Esempio n. 21
0
def manage(request):
    """
    parameters:
        employee_id: id del empleado (si el formulario es nuevo)
        role_id: id del rol a editar (si se edita uno ya existente)
        Se devuelve error 400 si no se proporciona al menos uno de los dos

    returns:
        employee: datos del empleado que se está editando
        departments: lista de departamentos que puede usar el usuario/admin logueado
        projects: lista de proyectos que puede user el usuario/admin logueado
        roles: lista de roles del sistema (sólo se aceptarán si están por debajo para el dpto/proyecto)
        form: formulario RoleManagementForm con los valores iniciales adecuados

        errors: array de códigos de error si los hay

    template:
        rol_form.html

    códigos de error (todos empiezan por roleCreation_):
        formNotValid - el formulario enviado no es válido
        employeeDoesNotExist - el empleado indicado no existe en la compañía o no está activo
        departmentDoesNotExist - el departamento indicado no existe en la compañía o no está activo
        projectDoesNotExist - el proyecto indicado no existe en la compañía o no está activo
        roleDoesNotExist - el rol indicado no existe
        employeeRoleDoesNotExist - el ID de rol de empleado indicado no existe
        notAuthorizedProjectDepartment - el usuario no está autorizado para crear roles en ese departamento y proyecto
        notAuthorizedRole - el usuario está autorizado a crear roles pero el que intenta crear es igual o superior al suyo
        alreadyExists - ya existe un rol para ese usuario, departamento y proyecto (sólo aparece al crear roles, no al editar)
        editingHigherRole - el usuario está intentando editar un rol de otro usuario que está por encima de él
        cannotEditHighestRole - el usuario está intentando modificar su rol más alto y eso no pue sé
    """

    logged = get_admin_executive_or_403(request)

    if request.method == "GET":
        # Check that at least 'employee_id' or 'role_id' are provided as GET params, raise 400 otherwise
        if "employee_id" not in request.GET and "role_id" not in request.GET:
            raise SuspiciousOperation

        # Return the initial form
        return get_form(request, logged)

    elif request.method == "POST":

        form = RoleManagementForm(request.POST)
        if form.is_valid():

            result = process_post_form(logged, form)
            if result["ok"]:
                return HttpResponseRedirect(
                    '/employee/view/' + Employee.objects.get(
                        id=form.cleaned_data["employee_id"]).user.username +
                    '/')
            else:
                return return_invalid_form(request, form, logged,
                                           result["errors"])

        else:
            # The form is not valid
            return return_invalid_form(request, form, logged,
                                       ['roleCreation_formNotValid'])

    else:  # Other request method, not supported
        raise SuspiciousOperation