def create_slots(request): data = data_parse( request.body, { 'slots': list, 'sources': list, 'duration': int, 'date': str, 'resource': int }) slots: List[str] = data[0] sources: List[str] = data[1] duration: int = data[2] date: str = data[3] resource: int = data[4] date_start = f"{date} 00:00:00" date_end = f"{date} 23:59:59" has_rights = can_edit_resource(request, resource) if not has_rights: return status_response(False, 'У вас недостаточно прав') date_slots = get_date_slots(date_start, date_end, resource) remove_element = [] for s in slots: start_end = s.split(" — ") a1 = try_strptime(f"{date} {start_end[0]}", formats=('%Y-%m-%d %H:%M', )) a2 = try_strptime(f"{date} {start_end[1]}", formats=('%Y-%m-%d %H:%M', )) for ds in date_slots: b1 = try_strptime(f"{date} {ds.start_slot}", formats=('%Y-%m-%d %H:%M', )) b2 = try_strptime(f"{date} {ds.end_slot}", formats=('%Y-%m-%d %H:%M', )) # проерка на не пересечение if not (a1 >= b2 or a2 <= b1): remove_element.append(s) for r in remove_element: slots.remove(r) with transaction.atomic(): for s in slots: time = s.split(' ')[0] datetime_str = f"{date} {time}" dt = try_strptime(datetime_str, formats=('%Y-%m-%d %H:%M', )) end_date = dt + relativedelta(minutes=duration) SlotPlan.objects.create( resource_id=resource, datetime=dt, datetime_end=end_date, duration_minutes=duration, available_systems=sources, ) return status_response(True)
def get_available_slots_of_dates(research_pk, date_start, date_end, allow_cito=False): d1 = try_strptime(f"{date_start}", formats=('%Y-%m-%d', )) d2 = try_strptime(f"{date_end}", formats=('%Y-%m-%d', )) current_date = try_strptime(current_time().strftime("%Y-%m-%d"), formats=('%Y-%m-%d', )) start_date = datetime.datetime.combine(d1, datetime.time.min) end_date = datetime.datetime.combine(d2, datetime.time.max) if end_date < datetime.datetime.combine(current_date, datetime.time.max): return {} if start_date < datetime.datetime.combine(current_date, datetime.time.min): start_date = datetime.datetime.combine( current_date, datetime.time.min) + datetime.timedelta(days=1) if allow_cito: data = {} date_i = start_date - datetime.timedelta( days=1) # ЦИТО можно записать на сегодня while date_i < end_date: date_s = date_i.strftime("%Y-%m-%d") data[date_s] = True date_i += datetime.timedelta(days=1) return data resource_hosp = get_hospital_resource_by_research(research_pk) structure_resource = { rh.scheduleresource_id: rh.resource_title for rh in resource_hosp } resource_tuple = tuple(structure_resource.keys()) slot_plans = get_date_slots_for_many_resource(start_date, end_date, resource_tuple) slot_plan_pks = tuple([slplan.slot_id for slplan in slot_plans]) slot_plan_busy_slot_fact = get_slot_fact(slot_plan_pks) slot_plan_busy_slot_fact = [i.plan_id for i in slot_plan_busy_slot_fact] data = {} for slotplan in slot_plans: if slotplan.slot_id in slot_plan_busy_slot_fact or slotplan.date_char in data: continue data[slotplan.date_char] = True return data
def check_available_hospital_slot_before_save(research_pk, resource_id, date): if not research_pk or not date: return False d = try_strptime(f"{date}", formats=('%Y-%m-%d', )) start_date = datetime.datetime.combine(d, datetime.time.min) end_date = datetime.datetime.combine(d, datetime.time.max) if resource_id is None: resource_id = tuple( ScheduleResource.objects.filter( service__in=[research_pk]).values_list('pk', flat=True)) elif isinstance(resource_id, tuple): resource_id = resource_id elif isinstance(resource_id, list): resource_id = tuple(resource_id) else: resource_id = tuple([resource_id]) if not resource_id: return False result_slot = get_slot_plan_by_hosp_resource(start_date, end_date, resource_id) date_slots = [i.hhmm_char for i in result_slot] current_plan_count = PlanHospitalization.objects.filter( exec_at__range=(start_date, end_date), work_status=0, action=0, research_id=research_pk).order_by("exec_at").count() return len(date_slots) > current_plan_count
def save(request): data = data_parse( request.body, { 'id': int, 'cardId': int, 'status': str, 'planId': int, 'serviceId': int, 'date': str, 'resource': str }, { 'planId': None, 'cardId': None, 'serviceId': None, 'status': 'reserved', 'date': None, 'resource': None }, ) pk: int = data[0] card_pk: int = data[1] status: str = data[2] plan_id: int = data[3] service_id: int = data[4] date: str = data[5] resource: int = data[6] if not card_pk: return status_response(False, 'Пациен не выбран') is_cito = False if has_group( request.user, 'Цито-запись в расписании') and pk == -10 and date and resource: d = try_strptime(f"{date}", formats=('%Y-%m-%d', )) start_date = datetime.datetime.combine(d, datetime.time.min) end_date = datetime.datetime.combine(d, datetime.time.max) slots = SlotPlan.objects.filter(datetime__range=(start_date, end_date)) free_slot: SlotPlan = slots.filter( slotfact__isnull=True).order_by('datetime').first() if not free_slot: last_any_slot: SlotPlan = slots.order_by('-datetime').first() if last_any_slot: next_time = last_any_slot.datetime + datetime.timedelta( minutes=last_any_slot.duration_minutes) duration = last_any_slot.duration_minutes else: next_time = try_strptime(f"{date} 08:00", formats=('%Y-%m-%d %H:%M', )) duration = 3 end_time = next_time + datetime.timedelta(minutes=duration) new_slot_plan = SlotPlan.objects.create( resource_id=resource, datetime=next_time, datetime_end=end_time, duration_minutes=duration, available_systems=[SlotPlan.LOCAL], disabled=False, is_cito=True, ) pk = new_slot_plan.pk else: pk = free_slot.pk is_cito = True s: SlotPlan = SlotPlan.objects.filter(pk=pk).first() if s: status = { 'reserved': 0, 'cancelled': 1, 'success': 2, }.get(status, 0) slot_fact: SlotFact = SlotFact.objects.filter( plan=s).order_by('-pk').first() if not slot_fact: slot_fact = SlotFact.objects.create(plan=s, status=status) slot_fact.patient_id = card_pk slot_fact.status = status slot_fact.service_id = service_id slot_fact.is_cito = is_cito slot_fact.save() if plan_id: ph: PlanHospitalization = PlanHospitalization.objects.get( pk=plan_id) ph.slot_fact = slot_fact ph.work_status = 3 ph.exec_at = s.datetime ph.save() return status_response(True) return status_response(False, 'Слот не найден')
def get_available_hospital_plans(research_pk, resource_id=None, date_start=None, date_end=None): if date_start and date_end: d1 = try_strptime(f"{date_start}", formats=('%Y-%m-%d', )) d2 = try_strptime(f"{date_end}", formats=('%Y-%m-%d', )) else: d1 = current_time(only_date=True) + relativedelta(days=1) d2 = d1 + relativedelta(days=FORWARD_DAYS_SCHEDULE) if resource_id is None: resource_id = tuple( ScheduleResource.objects.filter( service__in=[research_pk]).values_list('pk', flat=True)) elif isinstance(resource_id, tuple): resource_id = resource_id elif isinstance(resource_id, list): resource_id = tuple(resource_id) else: resource_id = tuple([resource_id]) if not resource_id: return {}, {} counts = {} start_date = datetime.datetime.combine(d1, datetime.time.min) end_date = datetime.datetime.combine(d2, datetime.time.max) result_slot = get_slot_plan_by_hosp_resource(start_date, end_date, resource_id) date_slots = {} for rslots in result_slot: if not date_slots.get(rslots.date_char, None): date_slots[rslots.date_char] = [rslots.datetime] else: temp_date_slots = date_slots.get(rslots.date_char, None) temp_date_slots.append(rslots.datetime) date_slots[rslots.date_char] = temp_date_slots.copy() date_available_status = {} date_i = start_date - datetime.timedelta( days=1) # ЦИТО можно записать на сегодня while date_i < end_date: date_s = date_i.strftime("%Y-%m-%d") date_available_status[date_s] = False date_i += datetime.timedelta(days=1) for current_date, slots_in_date in date_slots.items(): d1 = try_strptime(current_date, formats=('%Y-%m-%d', )) start_date = datetime.datetime.combine(d1, datetime.time.min) end_date = datetime.datetime.combine(d1, datetime.time.max) current_plan_count = (PlanHospitalization.objects.filter( exec_at__range=(start_date, end_date), work_status__in=[0, 1, 3], action=0, research_id=research_pk).order_by("exec_at").count()) counts[current_date] = { "available": len(slots_in_date), "used": current_plan_count, } date_available_status[current_date] = counts[current_date][ "available"] > counts[current_date]["used"] return date_available_status, counts
def get_available_hospital_resource_slot(research_pk, date_start, date_end, allow_cito=False): d1 = try_strptime(f"{date_start}", formats=('%Y-%m-%d', )) d2 = try_strptime(f"{date_end}", formats=('%Y-%m-%d', )) start_date = datetime.datetime.combine(d1, datetime.time.min) end_date = datetime.datetime.combine(d2, datetime.time.max) result = {"dates": {}} if end_date < datetime.datetime.combine( try_strptime(current_time().strftime("%Y-%m-%d"), formats=('%Y-%m-%d', )), datetime.time.max): return result resource_hosp = get_hospital_resource_by_research(research_pk) structure_resource = { rh.scheduleresource_id: rh.resource_title for rh in resource_hosp } resource_tuple = tuple(structure_resource.keys()) slot_plans = get_date_slots_for_many_resource(start_date, end_date, resource_tuple) slot_plan_pks = tuple([slplan.slot_id for slplan in slot_plans]) slot_plan_busy_slot_fact = get_slot_fact(slot_plan_pks) slot_plan_busy_slot_fact = [i.plan_id for i in slot_plan_busy_slot_fact] data = result["dates"] dates = set([slotplan.date_char for slotplan in slot_plans]) for d in dates: data[d] = [] temp_data_slot_resource = {} for slotplan in slot_plans: if slotplan.slot_id in slot_plan_busy_slot_fact: continue if not temp_data_slot_resource.get(slotplan.resource_id): temp_data_slot_resource[slotplan.resource_id] = { slotplan.date_char: [{ "pk": slotplan.slot_id, "title": f"{slotplan.start_slot} - {slotplan.end_slot}" }] } else: temp_slot_resource_date = temp_data_slot_resource.get( slotplan.resource_id, None) if not temp_slot_resource_date.get(slotplan.date_char): temp_slot_resource_date[slotplan.date_char] = [{ "pk": slotplan.slot_id, "title": f"{slotplan.start_slot} - {slotplan.end_slot}" }] else: temp_slot_resource_data = temp_slot_resource_date.get( slotplan.date_char) temp_slot_resource_data.append({ "pk": slotplan.slot_id, "title": f"{slotplan.start_slot} - {slotplan.end_slot}" }) temp_slot_resource_date[ slotplan.date_char] = temp_slot_resource_data.copy() temp_data_slot_resource[ slotplan.resource_id] = temp_slot_resource_date.copy() for k, v in temp_data_slot_resource.items(): for date, slots in v.items(): temp_data = data.get(date) temp_data.append({ "resourcePk": k, "resourceTitle": structure_resource.get(k, ""), "slots": slots }) data[date] = temp_data.copy() if allow_cito: dates = [] date_i = start_date while date_i < end_date: date = date_i.strftime("%Y-%m-%d") if date not in data: data[date] = [] has_resources = {x['resourcePk']: x for x in data[date]} for rpk in resource_tuple: if rpk in has_resources: has_resources[rpk]['slots'].append({ "pk": -10, "title": "CITO" }) continue temp_data = { "resourcePk": rpk, "resourceTitle": structure_resource.get(rpk, ""), "slots": [{ "pk": -10, "title": "CITO" }] } data[date].append(temp_data) date_i += datetime.timedelta(days=1) return result