Skip to content

Commit

Permalink
Merge pull request #4651 from mikhailprivalov/WTS-currentBranc
Browse files Browse the repository at this point in the history
Wts current branc
  • Loading branch information
urchinpro authored Jan 22, 2025
2 parents a44dd2b + 5c66c19 commit fc11e87
Show file tree
Hide file tree
Showing 12 changed files with 834 additions and 8 deletions.
1 change: 1 addition & 0 deletions api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
path('construct/', include('api.construct.urls')),
path('cash-register/', include('api.cash_registers.urls')),
path('statement/', include('api.statement.urls')),
path('working-time/', include('api.working_time.urls')),
path('get-prices', views.get_prices),
path('get-price-data', views.get_price_data),
path('update-price', views.update_price),
Expand Down
Empty file added api/working_time/__init__.py
Empty file.
4 changes: 4 additions & 0 deletions api/working_time/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from django.urls import path
from api.working_time import views

urlpatterns = [path('get-departments', views.get_departments), path('get-work-time', views.get_work_time), path('update-time', views.update_time)]
34 changes: 34 additions & 0 deletions api/working_time/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import json

from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
from laboratory.decorators import group_required
from employees.models import Department, EmployeeWorkingHoursSchedule


@login_required()
@group_required('График рабочего времени')
def get_departments(request):
departments = Department.get_active()
return JsonResponse({"result": departments})


@login_required()
@group_required('График рабочего времени')
def get_work_time(request):
request_data = json.loads(request.body)
result = EmployeeWorkingHoursSchedule.get_work_time(request_data["year"], request_data["month"], request_data["departmentId"])
return JsonResponse({"result": result})


@login_required()
@group_required('График рабочего времени')
def update_time(request):
request_data = json.loads(request.body)
start_work = request_data["startWork"]
end_work = request_data["endWork"]
type_work = request_data["type"]
employee_position_id = request_data["employeePositionId"]
date = request_data["date"]
result = EmployeeWorkingHoursSchedule.update_time(start_work, end_work, type_work, employee_position_id, date)
return JsonResponse(result)
8 changes: 8 additions & 0 deletions context_processors/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,14 @@ def menu(request):
"Вызов врача",
],
},
{
"url": '/ui/working-time',
"title": "График рабочего времени",
"nt": False,
"access": [
"График рабочего времени",
],
},
{
"url": '/ui/some-links',
"title": "Ccылки",
Expand Down
105 changes: 98 additions & 7 deletions employees/models.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import calendar
import datetime

import pytz
from django.db import models
from django.core.paginator import Paginator

from employees.sql_func import get_employees_by_department, get_work_time_by_document
from hospitals.models import Hospitals
from laboratory.settings import TIME_ZONE
from laboratory.utils import strfdatetime
from slog.models import Log
from users.models import DoctorProfile
Expand Down Expand Up @@ -306,6 +312,13 @@ def validate_values(hospital_id, name, current_id=None):
if departments.exists():
raise ValueError('Отдел с таким названием уже существует')

@staticmethod
def get_active(hospital_id: int = None):
if not hospital_id:
hospital_id = Hospitals.objects.get(is_default=True)
departments = [{"id": department.pk, "label": department.name} for department in Department.objects.filter(is_active=True, hospital_id=hospital_id).order_by('name')]
return departments

class Meta:
verbose_name = 'Отдел'
verbose_name_plural = 'Отделы'
Expand Down Expand Up @@ -466,6 +479,17 @@ def create_time_tracking_document(data, docprofile):
department_id=department_pk,
).save()

@staticmethod
def get_time_tracking_document(date_str, department_id):
date = datetime.datetime.strptime(date_str, '%Y-%m-%d').date()
year = date.year
month = date.month
first_date_month = datetime.date(year, month, 1)
length_month = calendar.monthrange(year, month)[1]
last_date_month = datetime.date(year, month, length_month)
document = TimeTrackingDocument.objects.filter(month__gte=first_date_month, month__lte=last_date_month, department_id=department_id).last()
return document


class TypeCheckTimeTrackingDocument(models.Model):
title = models.CharField(max_length=255, verbose_name='Наименование')
Expand Down Expand Up @@ -514,26 +538,93 @@ class TimeTrackingStatus(models.Model):
raw_data = models.TextField(blank=True, null=True, help_text="Данные документа")

class Meta:
verbose_name = "График-документ"
verbose_name_plural = "График-документы"
verbose_name = "График-документ-сохраненный"
verbose_name_plural = "График-документы-сохраненный"


class EmployeeWorkingHoursSchedule(models.Model):
time_tracking_document = models.ForeignKey(TimeTrackingDocument, null=True, blank=True, default=None, db_index=True, on_delete=models.SET_NULL)
employee_position = models.ForeignKey(EmployeePosition, null=True, blank=True, db_index=True, default=None, on_delete=models.SET_NULL)
start = models.DateTimeField(verbose_name='Начало рабочего времени', help_text='дата-время начала')
end = models.DateTimeField(verbose_name='Конец рабочего времени', help_text='дата-время окончания')
start = models.DateTimeField(verbose_name='Начало рабочего времени', help_text='дата-время начала', null=True, blank=True)
end = models.DateTimeField(verbose_name='Конец рабочего времени', help_text='дата-время окончания', null=True, blank=True)
day = models.DateField(verbose_name='Дата учета времени', null=True, blank=True, default=None, db_index=True, help_text='дата')
work_day_status = models.ForeignKey(WorkDayStatus, null=True, blank=True, default=None, db_index=True, on_delete=models.SET_NULL, verbose_name='Тип')
user_saved = models.ForeignKey('users.DoctorProfile', on_delete=models.SET_NULL, blank=True, null=True, verbose_name='Профиль пользователя сохранившего запись')

def __str__(self):
return f'{self.employee_position.employee.__str__()} {self.start} - {self.end}'

class Meta:
verbose_name = "Сотрудник - фактическое время за дату"
verbose_name_plural = "Сотрудники - фактическое время за дату"

def __str__(self):
return f'{self.employee_position.employee.__str__()} {self.start} - {self.end}'

@staticmethod
def get_employees_template(year: int, month: int, last_date_month: int, department_id: int) -> dict:
template_days = {datetime.date(year, month, day).strftime('%Y-%m-%d'): {"startWorkTime": "", "endWorkTime": "", "type": ""} for day in range(1, last_date_month + 1)}
employees = get_employees_by_department(department_id)
employees_template = {}
for employee in employees:
employees_template[employee.employee_position_id] = template_days.copy()
employees_template[employee.employee_position_id].update(
{
"employeePositionId": employee.employee_position_id,
"fio": f'{employee.family} {employee.name[0]}.{employee.patronymic[0] + "." if employee.patronymic else ""}',
"position": employee.position_name,
"bidType": 'осн',
"normMonth": '178',
"normDay": "8",
}
)
return employees_template

@staticmethod
def get_work_time(year: int, month: int, department_id: int):
first_date_month = datetime.date(year, month, 1)
length_month = calendar.monthrange(year, month)[1]
last_date_month = datetime.date(year, month, length_month)
template_employee = EmployeeWorkingHoursSchedule.get_employees_template(year, month, length_month, department_id)
document = TimeTrackingDocument.objects.filter(month__gte=first_date_month, month__lte=last_date_month, department_id=department_id).last()
if document:
employees_work_time = get_work_time_by_document(document.pk)
for work_day in employees_work_time:
work_time = template_employee[work_day.employee_position_id][work_day.start.strftime('%Y-%m-%d')].copy()
work_time["startWorkTime"] = work_day.start.astimezone(pytz.timezone(TIME_ZONE)).strftime('%H:%M')
work_time["endWorkTime"] = work_day.end.astimezone(pytz.timezone(TIME_ZONE)).strftime('%H:%M')
work_time["type"] = work_day.work_day_status_id
template_employee[work_day.employee_position_id][work_day.start.strftime('%Y-%m-%d')] = work_time
result = [value for value in template_employee.values()]
return result

@staticmethod
def update_time(start_work, end_work, type_work, employee_position_id, date):

employee_position = EmployeePosition.objects.filter(pk=employee_position_id).first()
document = TimeTrackingDocument.get_time_tracking_document(date, employee_position.department_id)
current_hours: EmployeeWorkingHoursSchedule = EmployeeWorkingHoursSchedule.objects.filter(
time_tracking_document_id=document.pk, employee_position_id=employee_position_id, day=date
).first()
if current_hours:
if type_work:
current_hours.work_day_status = type_work
current_hours.start = None
current_hours.end = None
else:
current_hours.work_day_status = None
current_hours.start = start_work
current_hours.end = end_work
current_hours.save()
else:
if type_work:
current_hours = EmployeeWorkingHoursSchedule(
time_tracking_document_id=document.pk, employee_position_id=employee_position_id, day=date, start=None, end=None, work_day_status_id=type_work
)
else:
current_hours = EmployeeWorkingHoursSchedule(
time_tracking_document_id=document.pk, employee_position_id=employee_position_id, day=date, start=start_work, end=end_work, work_day_status_id=None
)
current_hours.save()
return {"ok": True, "message": ""}


class CashRegister(models.Model):
employee_position = models.ForeignKey(EmployeePosition, null=True, blank=True, db_index=True, default=None, on_delete=models.SET_NULL)
Expand Down
38 changes: 38 additions & 0 deletions employees/sql_func.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from django.db import connection

from utils.db import namedtuplefetchall


def get_work_time_by_document(document_id: int):
with connection.cursor() as cursor:
cursor.execute(
"""
SELECT employees_employee.family, employees_employee.name, employees_employee.patronymic, employees_position.name as position_name,
employees_employeeworkinghoursschedule.id as worktime_id, start, "end", day, work_day_status_id, employee_position_id FROM employees_employeeWorkingHoursSchedule
INNER JOIN employees_employeeposition ON employees_employeeWorkingHoursSchedule.employee_position_id = employees_employeeposition.id
INNER JOIN employees_employee ON employees_employeeposition.employee_id = employees_employee.id
INNER JOIN employees_position ON employees_employeeposition.position_id = employees_position.id
WHERE time_tracking_document_id = %(document_id)s
ORDER BY employee_position_id
""",
params={'document_id': document_id},
)
row = namedtuplefetchall(cursor)
return row


def get_employees_by_department(department_id: int):
with connection.cursor() as cursor:
cursor.execute(
"""
SELECT employees_employeeposition.id as employee_position_id, employees_position.name as position_name, family,
employees_employee.name, patronymic FROM employees_employeeposition
INNER JOIN employees_position ON employees_employeeposition.position_id = employees_position.id
INNER JOIN employees_employee ON employees_employeeposition.employee_id = employees_employee.id
WHERE department_id = %(department_id)s and employees_employeeposition.is_active = true
ORDER BY family
""",
params={'department_id': department_id},
)
row = namedtuplefetchall(cursor)
return row
6 changes: 5 additions & 1 deletion l2-frontend/src/fields/RadioFieldById.vue
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ export default {
required: false,
type: Boolean,
},
startNull: {
required: false,
type: Boolean,
},
},
data() {
return {
Expand Down Expand Up @@ -86,7 +90,7 @@ export default {
this.$emit('modified', newVal);
},
fixVal() {
if ((!this.val || !this.variants.find(v => v.id === this.val)) && this.variants.length > 0) {
if ((!this.val || !this.variants.find(v => v.id === this.val)) && this.variants.length > 0 && !this.startNull) {
// eslint-disable-next-line prefer-destructuring
this.val = this.variants[0].id;
this.changeValue(this.val);
Expand Down
10 changes: 10 additions & 0 deletions l2-frontend/src/mainWithRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,16 @@ const router = new Router({
groups: ['ДОУ: просмотр документов'],
},
},
{
path: '/ui/working-time',
name: 'WorkingTime',
component: () => import('@/pages/WorkingTime/WorkingTime.vue'),
meta: {
narrowLayout: false,
title: 'График рабочего времени',
groups: ['График рабочего времени'],
},
},
{
path: '/ui/construct/related-tube/:id',
name: 'construct-related-tube',
Expand Down
Loading

0 comments on commit fc11e87

Please sign in to comment.