adding adding adding adding stuff...
This commit is contained in:
parent
9ae8c30717
commit
c8f9107ead
BIN
db.sqlite3
BIN
db.sqlite3
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,85 +1,11 @@
|
||||
|
||||
|
||||
from django.conf import settings
|
||||
import pandas as pd
|
||||
from ..models import Employee, Plan
|
||||
import datetime
|
||||
|
||||
|
||||
def time_timedelta(time, timedelta):
|
||||
start = datetime.datetime(2020, 1, 1, time.hour, time.minute)
|
||||
end = start + timedelta
|
||||
return end.time()
|
||||
|
||||
def insert_into_plan(user, start_date, end_date, start_time, daily_hours, activity_type, timemodel):
|
||||
|
||||
start_date = datetime.datetime.strptime(start_date, '%Y-%m-%d')
|
||||
end_date = datetime.datetime.strptime(end_date, '%Y-%m-%d')
|
||||
start_time = datetime.datetime.strptime(start_time, '%H:%M').time()
|
||||
|
||||
username = Employee.objects.get(username=user)
|
||||
|
||||
daily_hours = int(daily_hours * 60)
|
||||
end_time = time_timedelta(start_time, datetime.timedelta(minutes=daily_hours))
|
||||
|
||||
timemodel_pattern = {0: timemodel['mon'],
|
||||
1: timemodel['tue'],
|
||||
2: timemodel['wed'],
|
||||
3: timemodel['thu'],
|
||||
4: timemodel['fri'],
|
||||
5: timemodel['sat'],
|
||||
6: timemodel['sun']}
|
||||
|
||||
days = (end_date - start_date).days
|
||||
log = []
|
||||
for day in range(days + 1):
|
||||
date_to_add = start_date + datetime.timedelta(days=day)
|
||||
overlap = check_conflicting_records(username, date_to_add, start_time, end_time)
|
||||
print(overlap)
|
||||
if timemodel_pattern[date_to_add.weekday()] and not overlap:
|
||||
print(date_to_add, start_time, end_time, overlap)
|
||||
plan = Plan(username=username,
|
||||
date=date_to_add,
|
||||
begin_time=start_time,
|
||||
end_time=end_time,
|
||||
activity_type=activity_type)
|
||||
plan.save()
|
||||
log.append({'username': username.pk,
|
||||
'date': date_to_add,
|
||||
'begin_time': start_time,
|
||||
'end_time': end_time,
|
||||
'activity_type': activity_type,
|
||||
'status': 'imported'})
|
||||
else:
|
||||
|
||||
log.append({'username': username.pk,
|
||||
'date': date_to_add,
|
||||
'begin_time': start_time,
|
||||
'end_time': end_time,
|
||||
'activity_type': activity_type,
|
||||
'status': 'failed due to conflicting overlap'})
|
||||
return log
|
||||
|
||||
|
||||
def check_conflicting_records(username, date, start_time, end_time):
|
||||
plan = Plan.objects.filter(username=username, date=date)
|
||||
|
||||
if len(plan) > 0:
|
||||
for day in plan:
|
||||
planned_time_start = day.begin_time
|
||||
planned_time_end = day.end_time
|
||||
|
||||
if planned_time_start <= end_time and planned_time_end >= start_time:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
|
||||
import datetime as dt
|
||||
|
||||
def create_planning_operation_report(dict_, current_user):
|
||||
df = pd.DataFrame(dict_)
|
||||
filename = current_user + '_' + datetime.datetime.now().isoformat() + '.xlsx'
|
||||
filename = current_user + '_' + dt.datetime.now().isoformat() + '.xlsx'
|
||||
path_temp = settings.IMPORT_REPORT_STORAGE + filename
|
||||
df.to_excel(path_temp, index=False)
|
||||
return filename
|
||||
return filename
|
||||
|
@ -17,4 +17,5 @@ urlpatterns = [
|
||||
path('show_employee_timelog_api', views.show_employee_timelog_api, name='show_employee_timelog_api'),
|
||||
path('show_employee_data', views.show_employee_data, name='show_employee_data'),
|
||||
path('show_employee_data_api', views.show_employee_data_api, name='show_employee_data_api'),
|
||||
|
||||
]
|
@ -44,7 +44,7 @@ def time_tracking(request):
|
||||
if not timelog_record:
|
||||
context = {'activity_in_progress': False, 'schedule': plan_records, 'work_started_at': None, }
|
||||
else:
|
||||
context = {'activity_in_progress': True, 'schedule': plan_records, 'work_started_at': timelog_record.begin_time }
|
||||
context = {'activity_in_progress': True, 'schedule': plan_records, 'work_started_at': timelog_record.begin_time}
|
||||
return render(request=request, context=context, template_name=template_name)
|
||||
|
||||
@login_required(login_url=login_url)
|
||||
|
BIN
hr_module/__pycache__/context_processors.cpython-38.pyc
Normal file
BIN
hr_module/__pycache__/context_processors.cpython-38.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
5
hr_module/context_processors.py
Normal file
5
hr_module/context_processors.py
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
def report_download_path(request):
|
||||
return {'IMPORT_REPORT_STORAGE': settings.IMPORT_REPORT_STORAGE}
|
Binary file not shown.
112
hr_module/handling_functions/insert_to_plan.py
Normal file
112
hr_module/handling_functions/insert_to_plan.py
Normal file
@ -0,0 +1,112 @@
|
||||
|
||||
import datetime as dt
|
||||
from hr_module.models import Plan, Employee
|
||||
from django.conf import settings
|
||||
import pandas as pd
|
||||
|
||||
class UpdatePlan:
|
||||
def __init__(self, json):
|
||||
self.target_username = json['username']
|
||||
self.start_date = dt.datetime.strptime(json['date_start'], '%Y-%m-%d')
|
||||
self.end_date = dt.datetime.strptime(json['date_end'], '%Y-%m-%d')
|
||||
self.start_time = dt.datetime.strptime(json['start_time'], '%H:%M').time()
|
||||
self.daily_hours = int(json['daily_hours']) * 60
|
||||
self.activity_type = json['activity_type']
|
||||
self.time_model = self.get_timemodel(json['timemodel_pattern'])
|
||||
self.end_time = self.get_end_time()
|
||||
self.n_days = (self.end_date - self.start_date).days
|
||||
self.log = None
|
||||
|
||||
def run_inserting(self):
|
||||
log = []
|
||||
for day in range(self.n_days + 1):
|
||||
date_to_add = self.start_date + dt.timedelta(days=day)
|
||||
overlap = self.check_conflicting_records(date_to_add)
|
||||
|
||||
if self.time_model[date_to_add.weekday()] and not overlap:
|
||||
self.insert_into_plan(date_to_add)
|
||||
status = 'imported'
|
||||
else:
|
||||
status = 'failed due to conflicting overlap'
|
||||
|
||||
log.append({'username': self.target_username,
|
||||
'date': date_to_add,
|
||||
'begin_time': self.start_time,
|
||||
'end_time': self.end_time,
|
||||
'activity_type': self.activity_type,
|
||||
'status': status})
|
||||
return log
|
||||
|
||||
|
||||
|
||||
def insert_into_plan(self, date_to_add):
|
||||
employee = Employee.objects.get(pk=self.target_username)
|
||||
if not self.check_overnight_shift():
|
||||
plan = Plan(username=employee,
|
||||
date=date_to_add,
|
||||
begin_time=self.start_time,
|
||||
end_time=self.end_time,
|
||||
activity_type=self.activity_type)
|
||||
plan.save()
|
||||
else:
|
||||
plan = Plan(username=employee,
|
||||
date=date_to_add,
|
||||
begin_time=self.start_time,
|
||||
end_time=dt.time(23, 59, 59),
|
||||
activity_type=self.activity_type)
|
||||
plan.save()
|
||||
plan = Plan(username=employee,
|
||||
date=date_to_add + dt.timedelta(days=1),
|
||||
begin_time=dt.time(0, 0, 0),
|
||||
end_time=self.end_time,
|
||||
activity_type=self.activity_type)
|
||||
plan.save()
|
||||
|
||||
|
||||
|
||||
|
||||
def check_conflicting_records(self, checked_date):
|
||||
plan = Plan.objects.filter(username=self.target_username, date=checked_date)
|
||||
if len(plan) > 0:
|
||||
for day in plan:
|
||||
planned_time_start = dt.datetime.combine(day.date, day.begin_time)
|
||||
planned_time_end = dt.datetime.combine(day.date, day.end_time)
|
||||
|
||||
date_of_finish = checked_date + dt.timedelta(days=1) if self.check_overnight_shift() == True else checked_date
|
||||
unplanned_time_start = dt.datetime.combine(checked_date, self.start_time)
|
||||
unplanned_time_end = dt.datetime.combine(date_of_finish, self.end_time)
|
||||
print(planned_time_start, unplanned_time_start, planned_time_end, unplanned_time_end, date_of_finish, self.check_overnight_shift())
|
||||
if planned_time_start <= unplanned_time_start and planned_time_end >= unplanned_time_end:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def check_overnight_shift(self):
|
||||
start = dt.datetime(2020, 1, 1, self.start_time.hour, self.start_time.minute, self.start_time.second)
|
||||
end = start + dt.timedelta(minutes=self.daily_hours)
|
||||
if (end.date() - start.date()).days > 0:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def get_end_time(self):
|
||||
start = dt.datetime(2020, 1, 1, self.start_time.hour, self.start_time.minute, self.start_time.second)
|
||||
end = start + dt.timedelta(minutes=self.daily_hours)
|
||||
return end.time()
|
||||
|
||||
|
||||
def get_timemodel(self, time_model):
|
||||
time_model_pattern = {0: time_model['mon'],
|
||||
1: time_model['tue'],
|
||||
2: time_model['wed'],
|
||||
3: time_model['thu'],
|
||||
4: time_model['fri'],
|
||||
5: time_model['sat'],
|
||||
6: time_model['sun']}
|
||||
return time_model_pattern
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Generated by Django 3.1.3 on 2020-12-22 19:18
|
||||
# Generated by Django 3.1.3 on 2021-01-08 18:14
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
@ -43,7 +43,7 @@ class Migration(migrations.Migration):
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('date', models.DateField()),
|
||||
('begin_time', models.TimeField()),
|
||||
('end_time', models.TimeField()),
|
||||
('end_time', models.TimeField(null=True)),
|
||||
('activity_type', models.CharField(max_length=100)),
|
||||
('username', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='hr_module.employee')),
|
||||
],
|
||||
|
@ -1,18 +0,0 @@
|
||||
# Generated by Django 3.1.3 on 2021-01-05 18:58
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('hr_module', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='plan',
|
||||
name='end_time',
|
||||
field=models.TimeField(null=True),
|
||||
),
|
||||
]
|
@ -1,24 +0,0 @@
|
||||
# Generated by Django 3.1.3 on 2021-01-05 18:59
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('hr_module', '0002_auto_20210105_1858'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='plan',
|
||||
name='end_time',
|
||||
field=models.TimeField(default='09:00:00'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='timelog',
|
||||
name='end_time',
|
||||
field=models.TimeField(null=True),
|
||||
),
|
||||
]
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -2,7 +2,6 @@
|
||||
const csrftoken = getCookie('csrftoken');
|
||||
|
||||
|
||||
|
||||
window.addEventListener('load', function(){
|
||||
var parent = document.getElementById('calendar_box')
|
||||
parent.appendChild(addCalendar(monthsAhead=3))
|
||||
@ -27,7 +26,7 @@ window.addEventListener('load', function(){
|
||||
|
||||
function fetchDays(){
|
||||
var host = 'http://' + window.location.host;
|
||||
var fetch_url = host + '/hr_module/show_employee_plan_api'
|
||||
var fetch_url = host + '/hr_module/show_employee_timelog_api'
|
||||
|
||||
var range = searchedDateRange()
|
||||
var startDate = range['min']
|
||||
@ -82,11 +81,6 @@ function createDetailedCalendarRecords(data){
|
||||
for (var i = 0; i < data.length; i++){
|
||||
var index = data[i]['id']
|
||||
var username = data[i]['username_id']
|
||||
var processedDate = data[i]['date']
|
||||
var processedActivityType = data[i]['activity_type']
|
||||
var processedBeginTime = data[i]['begin_time']
|
||||
var processedEndTime = data[i]['end_time']
|
||||
|
||||
var row = table.insertRow(-1)
|
||||
row.id = 'database_id_' + index.toString()
|
||||
row.setAttribute('database_username', username)
|
||||
@ -192,7 +186,7 @@ function getCheckedRecords(event){
|
||||
|
||||
function updateCheckedRecords(recordsArray, action){
|
||||
var host = 'http://' + window.location.host;
|
||||
var fetch_url = host + '/hr_module/update_plan_api'
|
||||
var fetch_url = host + '/hr_module/update_timelog_api'
|
||||
|
||||
fetch(fetch_url,
|
||||
{
|
||||
|
369
hr_module/static/js/hr_module_show_timelog.js
Normal file
369
hr_module/static/js/hr_module_show_timelog.js
Normal file
@ -0,0 +1,369 @@
|
||||
|
||||
const csrftoken = getCookie('csrftoken');
|
||||
|
||||
|
||||
|
||||
window.addEventListener('load', function(){
|
||||
var parent = document.getElementById('calendar_box')
|
||||
parent.appendChild(addCalendar(monthsAhead=3))
|
||||
appendLegend()
|
||||
formatCalendarContainerSize(document.getElementById('calendar_container'))
|
||||
formatCalendarSize()
|
||||
document.getElementById('load_schedule_button').addEventListener('click', function(){
|
||||
fetchDays()
|
||||
})
|
||||
document.getElementById('calendar_button_back').addEventListener('click', function(){
|
||||
fetchDays()
|
||||
})
|
||||
document.getElementById('calendar_button_forwards').addEventListener('click', function(){
|
||||
fetchDays()
|
||||
})
|
||||
document.getElementById('button_load_selected_months').addEventListener('click', function(){
|
||||
fetchDays()
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
function fetchDays(){
|
||||
var host = 'http://' + window.location.host;
|
||||
var fetch_url = host + '/hr_module/show_employee_plan_api'
|
||||
|
||||
var range = searchedDateRange()
|
||||
var startDate = range['min']
|
||||
var endDate = range['max']
|
||||
var username = document.getElementById('username_input').value
|
||||
|
||||
fetch(fetch_url,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRFToken': csrftoken
|
||||
},
|
||||
body: JSON.stringify({
|
||||
"username": username,
|
||||
"start_date": startDate,
|
||||
"end_date" : endDate
|
||||
}),
|
||||
}).then((response) => {
|
||||
return response.json();
|
||||
}).then((data) => {
|
||||
console.log(data);
|
||||
addClassToWorkingDays(data);
|
||||
|
||||
var parent = document.getElementById('hr_module_main_container')
|
||||
|
||||
var listContainer = document.getElementById('list_container')
|
||||
if (listContainer == null){
|
||||
var listContainer = document.createElement('div')
|
||||
listContainer.id = 'list_container'
|
||||
} else {
|
||||
listContainer.innerHTML = ''
|
||||
}
|
||||
listContainer.appendChild(createDetailedCalendarRecords(data))
|
||||
parent.appendChild(listContainer)
|
||||
formatTableSize()
|
||||
});
|
||||
}
|
||||
|
||||
function addClassToWorkingDays(data){
|
||||
for (var i = 0; i < data.length; i++){
|
||||
var processedDate = data[i]['date']
|
||||
var processedActivityType = data[i]['activity_type']
|
||||
var nodeToChange = document.getElementById('date_' + processedDate)
|
||||
nodeToChange.classList.add('days_of_month_' + processedActivityType)
|
||||
}
|
||||
}
|
||||
|
||||
function createDetailedCalendarRecords(data){
|
||||
var table = createDetailedHeaders()
|
||||
|
||||
for (var i = 0; i < data.length; i++){
|
||||
var index = data[i]['id']
|
||||
var username = data[i]['username_id']
|
||||
var row = table.insertRow(-1)
|
||||
row.id = 'database_id_' + index.toString()
|
||||
row.setAttribute('database_username', username)
|
||||
|
||||
appendCell(row, 'div', 'date', data[i]['date'], 0)
|
||||
appendCell(row, 'div', 'begin_time', data[i]['begin_time'], 1)
|
||||
appendCell(row, 'div', 'end_time', data[i]['end_time'], 2)
|
||||
appendCell(row, 'div', 'activity_type', data[i]['activity_type'], 3)
|
||||
|
||||
var cell = row.insertCell(4)
|
||||
var buttonContainer = document.createElement('div')
|
||||
buttonContainer.className = 'buttons_cell'
|
||||
var button = document.createElement('button')
|
||||
button.innerText = 'Edit'
|
||||
button.value = index
|
||||
button.addEventListener('click', unlockRecordsForEditing)
|
||||
buttonContainer.appendChild(button)
|
||||
cell.appendChild(buttonContainer)
|
||||
|
||||
var cell = row.insertCell(5)
|
||||
var checkboxContainer = document.createElement('checkbox')
|
||||
checkboxContainer.className = 'copy_over_checkbox_cell'
|
||||
checkboxContainer.style.display = 'none'
|
||||
var checkbox = document.createElement('input')
|
||||
checkbox.type = 'checkbox'
|
||||
checkbox.checked = false
|
||||
checkboxContainer.appendChild(checkbox)
|
||||
cell.appendChild(checkboxContainer)
|
||||
}
|
||||
return table
|
||||
}
|
||||
|
||||
function appendCell(tableRow, tag, tagName, tagText, cellIndex){
|
||||
var cell = tableRow.insertCell(cellIndex)
|
||||
var textInput = document.createElement(tag)
|
||||
textInput.innerText = tagText
|
||||
textInput.name = tagName
|
||||
cell.appendChild(textInput)
|
||||
}
|
||||
|
||||
function unlockRecordsForEditing(event){
|
||||
var databaseId = event.target.value
|
||||
var parent = event.target.parentElement
|
||||
var row = document.getElementById('database_id_' + databaseId.toString())
|
||||
var children = row.getElementsByTagName('div')
|
||||
for (var i = 0; i < children.length; i++){
|
||||
console.log(children[i].className )
|
||||
if (['begin_time', 'end_time'].includes(children[i].className)) {
|
||||
var value = children[i].innerText
|
||||
var name = children[i].className
|
||||
var input = document.createElement('input')
|
||||
input.name = name
|
||||
input.value = value
|
||||
input.type = 'time'
|
||||
children[i].innerHTML = ''
|
||||
children[i].appendChild(input)
|
||||
}
|
||||
}
|
||||
|
||||
removeEditButtons(databaseId)
|
||||
|
||||
parent.appendChild(addSaveButton(databaseId))
|
||||
parent.appendChild(addDeleteButton(databaseId))
|
||||
parent.appendChild(addCancelButton(databaseId))
|
||||
|
||||
unhideCheckboxes(databaseId)
|
||||
}
|
||||
|
||||
function getCheckedRecords(event){
|
||||
|
||||
var id = event.target.value
|
||||
var row = document.getElementById('database_id_' + id)
|
||||
var username = row.getAttribute('database_username')
|
||||
var children = row.getElementsByTagName('input')
|
||||
|
||||
var copyValues = {'username': username}
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
var fieldName = children[i].name
|
||||
var fieldvalue = children[i].value
|
||||
if (fieldName != '') {
|
||||
copyValues[fieldName] = fieldvalue
|
||||
}
|
||||
}
|
||||
|
||||
var checkboxes = document.getElementsByClassName('copy_over_checkbox_cell')
|
||||
var outputArray = []
|
||||
for (var i = 0; i < checkboxes.length; i++) {
|
||||
if (checkboxes[i].firstChild.checked == true) {
|
||||
console.log('checked', i)
|
||||
var jsonChecked = {}
|
||||
var row = checkboxes[i].parentNode.parentNode
|
||||
var id = row.id.split('_')
|
||||
id = id[id.length-1]
|
||||
jsonChecked['id'] = parseInt(id)
|
||||
var jsonConcat = Object.assign(jsonChecked, copyValues)
|
||||
outputArray.push(jsonConcat)
|
||||
}
|
||||
}
|
||||
console.log(outputArray)
|
||||
return outputArray
|
||||
}
|
||||
|
||||
|
||||
function updateCheckedRecords(recordsArray, action){
|
||||
var host = 'http://' + window.location.host;
|
||||
var fetch_url = host + '/hr_module/update_plan_api'
|
||||
|
||||
fetch(fetch_url,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRFToken': csrftoken
|
||||
},
|
||||
body: JSON.stringify({
|
||||
'action': action,
|
||||
'records': recordsArray,
|
||||
}),
|
||||
}).then((response) => {
|
||||
return response.json();
|
||||
}).then((data) => {
|
||||
console.log(data);
|
||||
parent.innerHTML = ''
|
||||
parent.appendChild(addCalendar(3))
|
||||
formatCalendarContainerSize(document.getElementById('calendar_container'))
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
function unhideCheckboxes(databaseId){
|
||||
var checkboxes = document.getElementsByClassName('copy_over_checkbox_cell')
|
||||
for (var i = 0; i < checkboxes.length; i++){
|
||||
checkboxes[i].style.display = 'initial'
|
||||
if (checkboxes[i].parentNode.parentNode.id == 'database_id_' + databaseId.toString()){
|
||||
checkboxes[i].firstChild.checked = 'true'
|
||||
}
|
||||
}
|
||||
var header_copy_over = document.getElementById('header_copy_over')
|
||||
header_copy_over.style.display = 'table-cell'
|
||||
}
|
||||
|
||||
function removeEditButtons(id){
|
||||
var elements = document.getElementsByClassName('buttons_cell')
|
||||
for (var i = 0; i < elements.length; i++){
|
||||
elements[i].innerHTML = ''
|
||||
}
|
||||
}
|
||||
|
||||
function addSaveButton(databaseId){
|
||||
var button = document.createElement('button')
|
||||
button.innerHTML = 'Save'
|
||||
button.name = 'save'
|
||||
button.value = databaseId
|
||||
button.addEventListener('click', function(event){
|
||||
var checkedRecords = getCheckedRecords(event)
|
||||
updateCheckedRecords(checkedRecords, 'update')
|
||||
fetchDays()
|
||||
})
|
||||
return button
|
||||
}
|
||||
|
||||
function addDeleteButton(databaseId){
|
||||
var button = document.createElement('button')
|
||||
button.innerHTML = 'Delete'
|
||||
button.name = 'delete'
|
||||
button.value = databaseId
|
||||
button.addEventListener('click', function(event){
|
||||
var checkedRecords = getCheckedRecords(event)
|
||||
updateCheckedRecords(checkedRecords, 'delete')
|
||||
fetchDays()
|
||||
})
|
||||
|
||||
return button
|
||||
}
|
||||
|
||||
function addCancelButton(databaseId){
|
||||
var button = document.createElement('button')
|
||||
button.innerHTML = 'Cancel'
|
||||
button.name = 'cancel'
|
||||
button.value = databaseId
|
||||
button.addEventListener('click', fetchDays)
|
||||
return button
|
||||
}
|
||||
|
||||
function createDetailedHeaders(){
|
||||
var table = document.createElement('table')
|
||||
let headerRow = document.createElement('tr')
|
||||
let columns = ['Date', 'Start time', 'End time', 'Activity type', 'Action', 'Copy over']
|
||||
for (let i = 0; i < columns.length; i++){
|
||||
var headerCell = document.createElement('th')
|
||||
var headerText = document.createElement('div')
|
||||
headerText.innerText = columns[i]
|
||||
headerCell.appendChild(headerText)
|
||||
if (i == columns.length -1){
|
||||
headerCell.style.display = 'none'
|
||||
headerCell.id = 'header_copy_over'
|
||||
}
|
||||
|
||||
headerRow.appendChild(headerCell)
|
||||
|
||||
}
|
||||
table.appendChild(headerRow)
|
||||
table.id = 'detailed_plan_records'
|
||||
return table
|
||||
}
|
||||
|
||||
function formatCalendarContainerSize(calendarContainer){
|
||||
|
||||
var monthsBlock = calendarContainer.querySelector('#months_block')
|
||||
var calendarButton = calendarContainer.querySelector('#calendar_button_back')
|
||||
var dateSelector = calendarContainer.querySelector('#date_selector')
|
||||
var legendSelector = calendarContainer.querySelector('#legend_container')
|
||||
|
||||
var widthMonths = monthsBlock.offsetWidth
|
||||
var heightMonths = monthsBlock.offsetHeight
|
||||
var heightDateSelector = dateSelector.offsetHeight
|
||||
var heightLegend = legendSelector.offsetHeight
|
||||
var widthCalendarButton = calendarButton.offsetWidth * 2
|
||||
|
||||
var widthTotal = widthMonths + widthCalendarButton
|
||||
var heightTotal = heightMonths + heightDateSelector + heightLegend
|
||||
|
||||
calendarContainer.setAttribute('style','height:' + heightTotal +'px; width:' + widthTotal + 'px');
|
||||
}
|
||||
|
||||
function formatTableSize(){
|
||||
var calendar = document.getElementById('calendar_container')
|
||||
var tableDiv = document.getElementById('list_container')
|
||||
var width = calendar.offsetWidth
|
||||
|
||||
tableDiv.setAttribute('style', 'width:' + width + 'px')
|
||||
}
|
||||
|
||||
function formatCalendarSize(){
|
||||
var calendarBox = document.getElementById('calendar_box')
|
||||
var calendar = document.getElementById('calendar_container')
|
||||
calendarBox.setAttribute('style', 'width:' + calendar.offsetWidth + 'px')
|
||||
}
|
||||
|
||||
function searchedDateRange(){
|
||||
var dates = document.getElementsByClassName('days_of_month_current')
|
||||
|
||||
var datesArray = []
|
||||
for (var i = 0; i < dates.length; i++){
|
||||
var dateAttr = new Date(dates[i].getAttribute('date'))
|
||||
datesArray.push(dateAttr)
|
||||
}
|
||||
var minDate = new Date(Math.min.apply(null, datesArray))
|
||||
var maxDate = new Date(Math.max.apply(null, datesArray))
|
||||
var out = {'min' : minDate,
|
||||
'max': maxDate}
|
||||
console.log(out)
|
||||
return out
|
||||
}
|
||||
|
||||
function getCookie(name) {
|
||||
let cookieValue = null;
|
||||
if (document.cookie && document.cookie !== '') {
|
||||
let cookies = document.cookie.split(';');
|
||||
for (let i = 0; i < cookies.length; i++) {
|
||||
let cookie = cookies[i].trim();
|
||||
|
||||
if (cookie.substring(0, name.length + 1) === (name + '=')) {
|
||||
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cookieValue;
|
||||
}
|
||||
|
||||
function appendLegend(){
|
||||
var calendar = document.getElementById('calendar_container')
|
||||
var container = document.createElement('div')
|
||||
container.id = 'legend_container'
|
||||
var activityTypes = ['work', 'vacation', 'sickness', 'parental_leave']
|
||||
for(var i = 0; i < activityTypes.length; i++){
|
||||
var legendDiv = document.createElement('div')
|
||||
legendDiv.classList.add('legend_cube')
|
||||
legendDiv.classList.add('days_of_month_' + activityTypes[i])
|
||||
container.appendChild(legendDiv)
|
||||
}
|
||||
calendar.appendChild(container)
|
||||
}
|
@ -17,31 +17,47 @@
|
||||
</div>
|
||||
</a>
|
||||
|
||||
|
||||
<a href="{% url 'hr_module:create_schedule' %}">
|
||||
<div class="sidebar_item">Create schedule
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a href="{% url 'hr_module:plan_creation_log' %}">
|
||||
<div class="sidebar_item">Schedule creating logs
|
||||
</div>
|
||||
</a>
|
||||
|
||||
|
||||
<a href="{% url 'hr_module:manage_schedule' %}">
|
||||
<div class="sidebar_item">Manage employee schedule
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a href="{% url 'hr_module:manage_timelog' %}">
|
||||
<div class="sidebar_item">Manage employee timelog
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a href="{% url 'hr_module:change_employee_data' %}">
|
||||
<div class="sidebar_item">Manage employee data
|
||||
</div>
|
||||
</a>
|
||||
|
||||
{% if request.user.is_superuser %}
|
||||
<a href="{% url 'hr_module:create_employees' %}">
|
||||
<div class="sidebar_item">Create new employees
|
||||
</div>
|
||||
</a>
|
||||
|
||||
|
||||
<a href="{% url 'hr_module:create_schedule' %}">
|
||||
<div class="sidebar_item">Export Data
|
||||
</div>
|
||||
</a>
|
||||
|
||||
{% endif %}
|
||||
|
||||
<a href="{% url 'employee_module:homepage' %}">
|
||||
<div class="sidebar_item">Go to employee section
|
||||
</div>
|
||||
|
17
hr_module/templates/hr_module_creation_log.html
Normal file
17
hr_module/templates/hr_module_creation_log.html
Normal file
@ -0,0 +1,17 @@
|
||||
{% extends 'hr_module_base.html' %}
|
||||
|
||||
{% load static %}
|
||||
|
||||
{% block action_panel %}
|
||||
|
||||
{% if creation_log.count > 0 %}
|
||||
<div class="link_to_report_download">Links with scheduling import are below: </div>
|
||||
{% for item in creation_log %}
|
||||
<a href="{{ MEDIA_URL }}import_reports/{{ item.report_location }}">
|
||||
<div class="link_to_report_download">{{ item.report_location }}</div>
|
||||
</a>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<div class="link_to_report_download">You have not created schedule for anyone yet</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
21
hr_module/templates/hr_module_show_timelog.html
Normal file
21
hr_module/templates/hr_module_show_timelog.html
Normal file
@ -0,0 +1,21 @@
|
||||
{% extends 'hr_module_base.html' %}
|
||||
|
||||
{% load static %}
|
||||
|
||||
{% block action_panel %}
|
||||
<link rel="stylesheet" href="{% static '/css/calendar.css' %}">
|
||||
<link rel="stylesheet" href="{% static '/css/calendar_local.css' %}">
|
||||
<link rel="stylesheet" href="{% static '/css/hr_module_show_schedule.css' %}">
|
||||
|
||||
<div>
|
||||
<label for="username_input">Person username: </label>
|
||||
<input id="username_input" type="text" value="kowalskija">
|
||||
<button type="button" id="load_schedule_button">Load Schedule</button>
|
||||
</div>
|
||||
<div id="calendar_box"></div>
|
||||
|
||||
<script src="{% static '/js/calendar.js' %}"></script>
|
||||
<script src="{% static '/js/hr_module_show_timelog.js' %}"></script>
|
||||
|
||||
|
||||
{% endblock %}
|
@ -18,6 +18,10 @@ urlpatterns = [
|
||||
path('manage_schedule', views.manage_schedule, name='manage_schedule'),
|
||||
path('show_employee_plan_api', views.show_employee_plan_api, name='show_employee_plan_api'),
|
||||
path('update_plan_api', views.update_plan_api, name='update_plan_api'),
|
||||
path('manage_timelog', views.manage_timelog, name='manage_timelog'),
|
||||
path('show_employee_timelog_api', views.show_employee_timelog_api, name='show_employee_timelog_api'),
|
||||
path('update_timelog_api', views.update_timelog_api, name='update_timelog_api'),
|
||||
path('change_employee_data', views.change_employee_data, name='change_employee_data'),
|
||||
path('change_employee_data_api', views.change_employee_data_api, name='change_employee_data_api'),
|
||||
path('plan_creation_log', views.plan_creation_log, name='plan_creation_log'),
|
||||
]
|
@ -2,16 +2,18 @@ from django.shortcuts import render, redirect
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from .forms import UploadFileForm, NewUserForm
|
||||
from hr_module.handling_functions.data_import_functions import read_and_parse_excel, insert_excel
|
||||
from hr_module.handling_functions.monthly_planning_functions import insert_into_plan, create_planning_operation_report
|
||||
from hr_module.handling_functions.misc import dictfetchall
|
||||
from hr_module.handling_functions.insert_to_plan import UpdatePlan
|
||||
from hr_module.handling_functions.monthly_planning_functions import create_planning_operation_report
|
||||
import pandas as pd
|
||||
import json
|
||||
from .models import Employee, PlanCreationLog, Plan
|
||||
from .models import Employee, PlanCreationLog, Plan, TimeLog
|
||||
from django.contrib.auth.models import User
|
||||
from django.http import HttpResponse, JsonResponse, Http404, HttpResponseRedirect
|
||||
from django.db import connection
|
||||
import datetime
|
||||
from django.urls import reverse
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
login_url = '/hr_module/login'
|
||||
@ -90,7 +92,6 @@ def change_employee_data_api(request):
|
||||
|
||||
@login_required(login_url=login_url)
|
||||
def create_employees(request):
|
||||
session_user = User.objects.select_related('employee').get(username=request.user.username)
|
||||
if not request.user.is_superuser:
|
||||
return HttpResponseRedirect(reverse('hr_module:homepage'))
|
||||
|
||||
@ -222,18 +223,17 @@ def load_employees_api(request):
|
||||
|
||||
def new_plan_api(request):
|
||||
if request.method == 'POST':
|
||||
user = request.user.username
|
||||
body = json.loads(request.body)['json']
|
||||
log = []
|
||||
for item in body:
|
||||
insert_result = insert_into_plan(item['username'], item['date_start'], item['date_end'], item['start_time'], item['daily_hours'], item['activity_type'], item['timemodel_pattern'])
|
||||
update_object = UpdatePlan(item)
|
||||
insert_result = update_object.run_inserting()
|
||||
log = log + insert_result
|
||||
|
||||
report_location = create_planning_operation_report(log, user)
|
||||
print(user)
|
||||
user_obj = Employee.objects.get(pk=user)
|
||||
# plan_creation_log = PlanCreationLog(username=user_obj, report_location=report_location)
|
||||
# plan_creation_log.save()
|
||||
report_location = create_planning_operation_report(log, request.user.username)
|
||||
user_obj = Employee.objects.get(pk=request.user)
|
||||
plan_creation_log = PlanCreationLog(username=user_obj, report_location=report_location)
|
||||
plan_creation_log.save()
|
||||
return JsonResponse(log, safe=False)
|
||||
|
||||
@login_required(login_url=login_url)
|
||||
@ -256,8 +256,6 @@ def show_employee_plan_api(request):
|
||||
start_date = datetime.datetime.strptime(start_date, '%Y-%m-%d')
|
||||
end_date = datetime.datetime.strptime(end_date, '%Y-%m-%d')
|
||||
|
||||
print(username, start_date, end_date)
|
||||
|
||||
user_obj = Employee.objects.get(pk=username)
|
||||
|
||||
query_result = Plan.objects.filter(username=user_obj, date__range= [start_date, end_date])
|
||||
@ -285,4 +283,69 @@ def update_plan_api(request):
|
||||
record.save()
|
||||
|
||||
response = {'true': 'true'}
|
||||
return JsonResponse(response, safe=False)
|
||||
return JsonResponse(response, safe=False)
|
||||
|
||||
|
||||
@login_required(login_url=login_url)
|
||||
def manage_timelog(request):
|
||||
session_user = User.objects.select_related('employee').get(username=request.user.username)
|
||||
if not session_user.employee.manager_flag and not request.user.is_superuser:
|
||||
return HttpResponseRedirect(reverse('employee_module:homepage'))
|
||||
|
||||
template = 'hr_module_show_timelog.html'
|
||||
return render(request, template)
|
||||
|
||||
def show_employee_timelog_api(request):
|
||||
if request.method == 'POST':
|
||||
body = json.loads(request.body)
|
||||
username = body['username']
|
||||
start_date = body['start_date'].split('T')[0]
|
||||
end_date = body['end_date'].split('T')[0]
|
||||
|
||||
start_date = datetime.datetime.strptime(start_date, '%Y-%m-%d')
|
||||
end_date = datetime.datetime.strptime(end_date, '%Y-%m-%d')
|
||||
|
||||
user_obj = Employee.objects.get(pk=username)
|
||||
|
||||
query_result = TimeLog.objects.filter(username=user_obj, date__range= [start_date, end_date])
|
||||
response = list(query_result.values())
|
||||
return JsonResponse(response, safe=False)
|
||||
|
||||
|
||||
def update_timelog_api(request):
|
||||
if request.method == 'POST':
|
||||
body = json.loads(request.body)
|
||||
print(body)
|
||||
if body['action'] == 'delete':
|
||||
for i in body['records']:
|
||||
record_id = i['id']
|
||||
TimeLog.objects.filter(id=record_id).delete()
|
||||
|
||||
if body['action'] == 'update':
|
||||
for i in body['records']:
|
||||
record_id = i['id']
|
||||
record_start_time = i['begin_time']
|
||||
record_end_time = i['end_time']
|
||||
record = TimeLog.objects.get(pk=record_id)
|
||||
record.begin_time = record_start_time
|
||||
record.end_time = record_end_time
|
||||
record.save()
|
||||
|
||||
response = {'true': 'true'}
|
||||
return JsonResponse(response, safe=False)
|
||||
|
||||
|
||||
@login_required(login_url=login_url)
|
||||
def plan_creation_log(request):
|
||||
session_user = User.objects.select_related('employee').get(username=request.user.username)
|
||||
session_user_manager_flag = session_user.employee.manager_flag
|
||||
if request.user.is_superuser:
|
||||
creation_log = PlanCreationLog.objects.all().order_by('-creation_date')
|
||||
elif session_user_manager_flag:
|
||||
creation_log = PlanCreationLog.objects.filter(report_location__contains=request.user.username).order_by('-creation_date')
|
||||
|
||||
context = {'creation_log': creation_log,
|
||||
'path': settings.IMPORT_REPORT_STORAGE}
|
||||
|
||||
template_name = 'hr_module_creation_log.html'
|
||||
return render(request, context=context, template_name=template_name)
|
BIN
media/import_reports/admin_2021-01-08T18:20:58.628482.xlsx
Normal file
BIN
media/import_reports/admin_2021-01-08T18:20:58.628482.xlsx
Normal file
Binary file not shown.
BIN
media/import_reports/admin_2021-01-08T18:28:00.784191.xlsx
Normal file
BIN
media/import_reports/admin_2021-01-08T18:28:00.784191.xlsx
Normal file
Binary file not shown.
BIN
media/import_reports/hitlerad_2021-01-08T15:50:18.109111.xlsx
Normal file
BIN
media/import_reports/hitlerad_2021-01-08T15:50:18.109111.xlsx
Normal file
Binary file not shown.
BIN
media/import_reports/hitlerad_2021-01-08T15:50:19.623406.xlsx
Normal file
BIN
media/import_reports/hitlerad_2021-01-08T15:50:19.623406.xlsx
Normal file
Binary file not shown.
BIN
media/import_reports/hitlerad_2021-01-08T15:50:34.968166.xlsx
Normal file
BIN
media/import_reports/hitlerad_2021-01-08T15:50:34.968166.xlsx
Normal file
Binary file not shown.
BIN
media/import_reports/hitlerad_2021-01-08T15:51:47.956514.xlsx
Normal file
BIN
media/import_reports/hitlerad_2021-01-08T15:51:47.956514.xlsx
Normal file
Binary file not shown.
BIN
media/import_reports/hitlerad_2021-01-08T15:52:12.207359.xlsx
Normal file
BIN
media/import_reports/hitlerad_2021-01-08T15:52:12.207359.xlsx
Normal file
Binary file not shown.
BIN
media/import_reports/hitlerad_2021-01-08T15:57:00.124542.xlsx
Normal file
BIN
media/import_reports/hitlerad_2021-01-08T15:57:00.124542.xlsx
Normal file
Binary file not shown.
BIN
media/import_reports/hitlerad_2021-01-08T15:58:37.353387.xlsx
Normal file
BIN
media/import_reports/hitlerad_2021-01-08T15:58:37.353387.xlsx
Normal file
Binary file not shown.
BIN
media/import_reports/hitlerad_2021-01-08T15:58:47.446569.xlsx
Normal file
BIN
media/import_reports/hitlerad_2021-01-08T15:58:47.446569.xlsx
Normal file
Binary file not shown.
BIN
media/import_reports/hitlerad_2021-01-08T15:59:32.551891.xlsx
Normal file
BIN
media/import_reports/hitlerad_2021-01-08T15:59:32.551891.xlsx
Normal file
Binary file not shown.
BIN
media/import_reports/hitlerad_2021-01-08T15:59:55.135525.xlsx
Normal file
BIN
media/import_reports/hitlerad_2021-01-08T15:59:55.135525.xlsx
Normal file
Binary file not shown.
BIN
media/import_reports/hitlerad_2021-01-08T16:12:49.390236.xlsx
Normal file
BIN
media/import_reports/hitlerad_2021-01-08T16:12:49.390236.xlsx
Normal file
Binary file not shown.
BIN
media/import_reports/hitlerad_2021-01-08T16:36:47.512626.xlsx
Normal file
BIN
media/import_reports/hitlerad_2021-01-08T16:36:47.512626.xlsx
Normal file
Binary file not shown.
BIN
media/import_reports/hitlerad_2021-01-08T16:39:16.993419.xlsx
Normal file
BIN
media/import_reports/hitlerad_2021-01-08T16:39:16.993419.xlsx
Normal file
Binary file not shown.
BIN
media/import_reports/hitlerad_2021-01-08T16:44:53.681112.xlsx
Normal file
BIN
media/import_reports/hitlerad_2021-01-08T16:44:53.681112.xlsx
Normal file
Binary file not shown.
BIN
media/import_reports/hitlerad_2021-01-08T16:48:34.073374.xlsx
Normal file
BIN
media/import_reports/hitlerad_2021-01-08T16:48:34.073374.xlsx
Normal file
Binary file not shown.
BIN
media/import_reports/hitlerad_2021-01-08T16:49:41.790338.xlsx
Normal file
BIN
media/import_reports/hitlerad_2021-01-08T16:49:41.790338.xlsx
Normal file
Binary file not shown.
BIN
media/import_reports/hitlerad_2021-01-08T16:50:24.991185.xlsx
Normal file
BIN
media/import_reports/hitlerad_2021-01-08T16:50:24.991185.xlsx
Normal file
Binary file not shown.
BIN
media/import_reports/hitlerad_2021-01-08T16:50:58.290789.xlsx
Normal file
BIN
media/import_reports/hitlerad_2021-01-08T16:50:58.290789.xlsx
Normal file
Binary file not shown.
BIN
media/import_reports/hitlerad_2021-01-08T16:51:15.303037.xlsx
Normal file
BIN
media/import_reports/hitlerad_2021-01-08T16:51:15.303037.xlsx
Normal file
Binary file not shown.
BIN
media/import_reports/hitlerad_2021-01-08T16:52:13.818740.xlsx
Normal file
BIN
media/import_reports/hitlerad_2021-01-08T16:52:13.818740.xlsx
Normal file
Binary file not shown.
BIN
media/import_reports/hitlerad_2021-01-08T16:52:30.491847.xlsx
Normal file
BIN
media/import_reports/hitlerad_2021-01-08T16:52:30.491847.xlsx
Normal file
Binary file not shown.
Binary file not shown.
@ -1,6 +0,0 @@
|
||||
,first_name,last_name,username,email,is_staff,is_active,is_superuser,department,manager_username,time_model_id,manager_flag
|
||||
0,Jan,Kowalski,kowalskija,kowalskija@company.com,0,1,0,test department,hitlerad,1,0
|
||||
1,Janina,Kowalska,kowalskaja,kowalskaja@company.com,0,1,0,test department,test department0,1,0
|
||||
2,Tadeusz,Tadeuszowicz,tadeuszowiczta,tadeuszowiczta@company.com,0,1,0,dfdfdv,dfdfdv0,1,0
|
||||
3,Aleksander,Lukaszenko,lukaszenkoal,lukaszenkoal@company.com,0,1,0,fsdfgfg,hitlerad,1,0
|
||||
4,Adolf,Hitler,hitlerad,hitlerad@company.com,0,1,0,fg,hitlerad,1,0
|
|
Binary file not shown.
Binary file not shown.
@ -34,6 +34,7 @@ ALLOWED_HOSTS = ['192.168.101.128',
|
||||
# Application definition
|
||||
|
||||
INSTALLED_APPS = [
|
||||
'django_extensions',
|
||||
'hr_module.apps.HrModuleConfig',
|
||||
'employee_module.apps.EmployeeModuleConfig',
|
||||
'django.contrib.admin',
|
||||
@ -65,6 +66,8 @@ TEMPLATES = [
|
||||
'APP_DIRS': True,
|
||||
'OPTIONS': {
|
||||
'context_processors': [
|
||||
'hr_module.context_processors.report_download_path',
|
||||
'django.template.context_processors.media',
|
||||
'django.template.context_processors.debug',
|
||||
'django.template.context_processors.request',
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
@ -133,9 +136,13 @@ STATICFILES_DIRS = [
|
||||
]
|
||||
|
||||
|
||||
TMP_FILE_STORAGE = os.path.join(BASE_DIR, 'temp/')
|
||||
IMPORT_REPORT_STORAGE = os.path.join(BASE_DIR, 'import_reports/')
|
||||
|
||||
|
||||
LOGOUT_REDIRECT_URL = '/hr_module/login'
|
||||
LOGIN_REDIRECT_URL = '/hr_module/home'
|
||||
|
||||
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
|
||||
MEDIA_URL = '/media/'
|
||||
|
||||
TMP_FILE_STORAGE = os.path.join(MEDIA_URL, 'temp/')
|
||||
IMPORT_REPORT_STORAGE = os.path.join(BASE_DIR, 'import_reports')
|
||||
|
@ -15,9 +15,15 @@ Including another URLconf
|
||||
"""
|
||||
from django.contrib import admin
|
||||
from django.urls import path, include
|
||||
from django.conf import settings
|
||||
from django.conf.urls.static import static
|
||||
|
||||
urlpatterns = [
|
||||
path('admin/', admin.site.urls),
|
||||
path('hr_module/', include('hr_module.urls')),
|
||||
path('employee_module/', include('employee_module.urls')),
|
||||
]
|
||||
|
||||
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user