示例#1
0
class InteropArray(ServiceBase):
    @srpc(Array(Integer), _returns=Array(Integer))
    def echo_integer_array(ia):
        return ia

    @srpc(Array(String), _returns=Array(String))
    def echo_string_array(sa):
        return sa

    @srpc(Array(DateTime), _returns=Array(DateTime))
    def echo_date_time_array(dta):
        return dta

    @srpc(Array(Float), _returns=Array(Float))
    def echo_float_array(fa):
        return fa

    @srpc(Array(Double), _returns=Array(Double))
    def echo_double_array(da):
        return da

    @srpc(Array(Boolean), _returns=Array(Boolean))
    def echo_boolean_array(ba):
        return ba

    @srpc(Boolean(max_occurs="unbounded"),
          _returns=Boolean(max_occurs="unbounded"))
    def echo_simple_boolean_array(ba):
        return ba

    @srpc(Array(Boolean), _returns=Array(Array(Boolean)))
    def echo_array_in_array(baa):
        return baa
示例#2
0
class RequestExtras(ComplexModel):
    """
    Used in runMutalyzerLight
    """
    original = Boolean()
    mutated = Boolean()
    varDetails = Boolean()
示例#3
0
class Flight(ComplexModel):

    __namespace__ = 'testing'
    Index = Integer(min_occurs=0, max_occurs=1, nillable=True)
    flightNumber = Unicode(min_occurs=0, max_occurs=1, nillable=True)
    airline = Unicode(min_occurs=0, max_occurs=1, nillable=True)
    airlineIATA = Unicode(min_occurs=0, max_occurs=1, nillable=True)
    flightNumber = Unicode(min_occurs=0, max_occurs=1, nillable=True)
    nChild = Integer(min_occurs=0, max_occurs=1, nillable=True)
    nInfant = Integer(min_occurs=0, max_occurs=1, nillable=True)
    arrivalDateTime = DateTime(min_occurs=0, max_occurs=1, nillable=True)

    from_ = Unicode(min_occurs=0, max_occurs=1, nillable=False)
    to = Unicode(min_occurs=0, max_occurs=1, nillable=False)
    departureDatetime = DateTime(min_occurs=0, max_occurs=1, nillable=False)
    nAdult = Integer(min_occurs=0, max_occurs=1, nillable=False)
    AV = Array(AV.customize(nillable=True))
    LConnections = Array(Connection.customize(nillable=True))
    LFares = Array(Fare.customize(nillable=True))

    validReturns = Array(Unicode(min_occurs=0, max_occurs=1, nillable=False))
    type = Unicode(min_occurs=0, max_occurs=1, nillable=False)
    return_ = Boolean(min_occurs=0, max_occurs=1, nillable=False)
    schedule = Unicode(min_occurs=0, max_occurs=1, nillable=False)
    range = Unicode(min_occurs=0, max_occurs=1, nillable=False)
    info = Unicode(min_occurs=0, max_occurs=1, nillable=False)
示例#4
0
class Element(SchemaBase):
    name = XmlAttribute(Unicode)
    type = XmlAttribute(Unicode)
    ref = XmlAttribute(Unicode)
    # it can be "unbounded", so it should be of type Unicode
    max_occurs = XmlAttribute(Unicode(default="1", sub_name="maxOccurs"))
    # Also Unicode for consistency with max_occurs
    min_occurs = XmlAttribute(Unicode(default="1", sub_name="minOccurs"))
    nillable = XmlAttribute(Boolean(default=False))
示例#5
0
class Mandatory(object):
    """
    This is spyne.model.primitive.Mandatory, but without min_length=1 for
    the Unicode model.
    """
    Unicode = Unicode(type_name='mandatory_unicode', min_occurs=1, nillable=False)
    Integer = Integer(type_name='mandatory_integer', min_occurs=1, nillable=False)
    Boolean = Boolean(type_name='mandatory_boolean', min_occurs=1, nillable=False)
    DateTime = DateTime(type_name='mandatory_date_time', min_occurs=1, nillable=False)
    ByteArray = ByteArray(type_name='mandatory_byte_array', min_occurs=1, nillable=False)
示例#6
0
class PatientTicketsResponse(ComplexModel):
    __namespace__ = SOAP_NAMESPACE
    status = Boolean(doc=u'Результат поиска талончиков пациента')
    message = Unicode(doc=u'Сообщение об ошибке')
    tickets = TicketInfo.customize(
        max_occurs='unbounded', doc=u'Талончики, на которые записан пациент')

    def __init__(self):
        super(PatientTicketsResponse,
              self).__init__(doc=u'Результат запроса о записях на приём')
示例#7
0
class CancelResponse(ComplexModel):
    __namespace__ = SOAP_NAMESPACE

    success = Boolean(doc=u'Признак успешности выполнения операции')
    comment = Unicode(
        doc=u'Дополнительная информация о результатах выполнения операции')

    def __init__(self):
        super(
            CancelResponse,
            self).__init__(doc=u'Результат запроса об отмене записи на приём')
示例#8
0
class EnqueueResponse(ComplexModel):
    __namespace__ = SOAP_NAMESPACE

    result = Boolean(doc=u'Результат запроса о записи на приём')
    message = String(doc=u'Сообщение об ошибке')
    ticketUid = String(
        doc=u'Уникальный для МИС данного ЛПУ идентификатор принятой заявки')
    printableDocument = String(
        doc=
        u'Данныее электронного документа с печатной формой заявки на приём (талоном)'
    )

    def __init__(self):
        super(EnqueueResponse,
              self).__init__(doc=u'Данные запроса о записи на приём')
示例#9
0
class WFMPortalService(DjangoServiceBase):
    """WEB API"""

    __in_header__ = AuthDataHeader
    """
    Создание заявки на аутсорсинг персонала
    """
    @rpc(Unicode(sub_name='guid', min_occurs=1, nillable=False),
         HeadquaterSoapModel.customize(min_occurs=0, nillable=False),
         Date(sub_name='start'),
         Date(sub_name='end'),
         OrganizationSoapModel,
         AgencySoapModel,
         Unicode(sub_name='state', min_occurs=1, nillable=False),
         Array(ShiftSoapModel),
         Unicode(sub_name='comments', min_occurs=0, nillable=False),
         Unicode(sub_name='user_name', min_occurs=0, nillable=False),
         Unicode(sub_name='email', min_occurs=0, nillable=False),
         _returns=Unicode,
         _throws=[AuthenticationError, AuthorizationError, CustomError])
    @soap_logger
    @check_auth_data
    def setOutsourcingRequest(ctx, guid, headquater, start, end, organization,
                              agency, state, shifts, comments, user_name,
                              email):

        auth_and_check_perms(ctx.in_header.login, ctx.in_header.password)

        # TODO remove
        if not headquater:
            db_headquarter = open_headquarter_by_code('mvideo')

        # Магазин, сформировавший запрос
        if headquater:
            db_headquarter = open_headquarter_by_code(headquater.code)
            db_organization = open_organization_by_code(
                organization.code, db_headquarter)
        else:
            db_organization = open_organization_by_code(
                organization.code, None)
            db_headquarter = db_organization.headquater
        if not db_headquarter:
            raise CustomError(
                f'REQUEST {guid}: no headquater with code {headquater.code}')
        if not db_organization:
            raise CustomError(
                f'REQUEST {guid}: no organiztion with code {organization.code}'
            )

        # Агентство, в котором запрашиваем аутсорсинг
        db_agency = open_agency_by_code(agency.code, None)
        if not db_agency:
            raise CustomError(
                f'REQUEST {guid}: no agency with code {agency.code}')

        # Принимаем запросы только в состоянии launched, повторно запросы и запросы без смен не обрабатываем
        if state != 'launched':
            raise CustomError(
                f'REQUEST {guid}: state {state} is differ then launched')
        out_req = OutsourcingRequest.objects.filter(guid=guid).first()
        if out_req or not shifts:
            return {'result': 'ok'}

        # Создаем объект запроса
        if not comments:
            comments = ''
        if not user_name:
            user_name = ''
        if not email:
            email = ''
        out_req = OutsourcingRequest.objects.create(
            guid=guid,
            headquater=db_headquarter,
            organization=db_organization,
            agency=db_agency,
            state='accepted',
            start=start,
            end=end,
            comments=comments,
            user_name=user_name,
            email=email)
        # Создаем связанные с запросом смены
        for s in shifts:
            try:
                job = Job.objects.get(code=s.job.code)
            except Job.DoesNotExist:
                raise CustomError(
                    f'REQUEST {guid}, SHIFT {s.guid}: no job with code {s.job.code}'
                )
            if s.start > s.end:
                raise CustomError(
                    f'REQUEST {guid}, SHIFT {s.guid}: start > end')
            if s.worktime < 0:
                raise CustomError(
                    f'REQUEST {guid}, SHIFT {s.guid}: worktime = {s.worktime} < 0'
                )
            OutsourcingShift.objects.create(guid=s.guid,
                                            headquater=db_headquarter,
                                            state=s.state,
                                            start=s.start,
                                            end=s.end,
                                            worktime=s.worktime,
                                            job=job,
                                            request=out_req,
                                            agency=db_agency,
                                            start_date=s.start)

        # Создаем и отправляем уведомления о новой заявке
        make_notify_data(out_req, 'agency', 'wait_req_template')
        return {'result': 'ok'}

    """
        Получение данных по запросам, чей статус был обновлен раньше определенного времени
    """

    @rpc(DateTime(sub_name='timestamp', min_occurs=1, nillable=False),
         HeadquaterSoapModel.customize(min_occurs=0, nillable=False),
         Integer(sub_name='amount', min_occurs=0, nillable=False),
         _returns=ComplexRequestsResponseSoapModel,
         _throws=[AuthenticationError, AuthorizationError, CustomError])
    @soap_logger
    @check_auth_data
    def getOutsourcingRequests(ctx, dt_change, headquater, amount):
        auth_and_check_perms(ctx.in_header.login, ctx.in_header.password)

        # TODO remove
        if not headquater:
            db_headquarter = open_headquarter_by_code('mvideo')
        else:
            # Клиент
            db_headquarter = open_headquarter_by_code(headquater.code)
        if not db_headquarter:
            raise CustomError(
                f'Headquater {headquater.code} is not registered')

        response = dict()
        response['requests_list'] = []

        # Ограничинваем максимальное количество запросов, возвращаемых за 1 раз
        if not amount or amount < 0:
            amount = 100

        # Поиск смен
        out_requests = OutsourcingRequest.objects.filter(
            headquater=db_headquarter, dt_ready__gt=dt_change, state='ready')
        out_requests = out_requests.order_by('dt_ready')[:amount]

        # Формируем результат
        if not out_requests:
            response['result'] = len(out_requests)
            response['timestamp'] = dt_change
        else:
            response['result'] = len(out_requests)
            response['timestamp'] = out_requests.aggregate(
                timestamp=Max('dt_ready'))['timestamp']
            response['requests_list'] = out_requests

        return response

    """
    Получение данных по запросу и связанным с ним сменам
    """

    @rpc(Unicode(sub_name='guid', min_occurs=1, nillable=False),
         HeadquaterSoapModel.customize(min_occurs=0, nillable=False),
         _returns=ComplexOutsourcingRequestSoapModel,
         _throws=[AuthenticationError, AuthorizationError, CustomError])
    @soap_logger
    @check_auth_data
    def getOutsourcingRequest(ctx, guid, headquater):
        auth_and_check_perms(ctx.in_header.login, ctx.in_header.password)

        # TODO remove
        if not headquater:
            db_headquarter = open_headquarter_by_code('mvideo')
        else:
            # Клиент
            db_headquarter = open_headquarter_by_code(headquater.code)
        if not db_headquarter:
            raise CustomError(
                f'Headquater {headquater.code} is not registered')

        try:
            out_request = OutsourcingRequest.objects.get(
                guid=guid, headquater=db_headquarter)
            shifts = OutsourcingShift.objects.filter(
                request=out_request,
                headquater=db_headquarter).select_related('job')
            out_request.shifts = shifts
            return out_request
        except:
            raise CustomError(
                f'REQUEST {guid}: no OutsourcingRequest is found')

    """
    Получение изменений по сменам на аутсорсинг
    """

    @rpc(DateTime(sub_name='timestamp', min_occurs=1, nillable=False),
         HeadquaterSoapModel.customize(min_occurs=0, nillable=False),
         Integer(sub_name='amount', min_occurs=0, nillable=False),
         _returns=ComplexShiftsResponseSoapModel,
         _throws=[AuthenticationError, AuthorizationError, CustomError])
    @soap_logger
    @check_auth_data
    def getOutsourcingShifts(ctx, dt_change, headquater, amount):
        auth_and_check_perms(ctx.in_header.login, ctx.in_header.password)

        # TODO remove
        if not headquater:
            db_headquarter = open_headquarter_by_code('mvideo')
        else:
            # Клиент
            db_headquarter = open_headquarter_by_code(headquater.code)
        if not db_headquarter:
            raise CustomError(
                f'Headquater {headquater.code} is not registered')

        response = dict()
        response['shifts_list'] = []

        # Ограничинваем максимальное количество смен, возвращаемых за 1 раз
        if not amount or amount < 0:
            amount = 100

        # Поиск смен
        out_shifts = OutsourcingShift.objects.filter(headquater=db_headquarter,
                                                     dt_change__gt=dt_change,
                                                     state='accept')
        out_shifts = out_shifts.order_by('dt_change').select_related(
            'agency_employee')[:amount]

        # Получение ТН сотрудника в организации на основе OrgHistory
        for shift in out_shifts:
            if shift.agency_employee:
                shift.agency_employee.oh_number = shift.get_employee_number_in_organization(
                )
        # Формируем результат
        if not out_shifts:
            response['result'] = len(out_shifts)
            response['timestamp'] = dt_change
        else:
            response['result'] = len(out_shifts)
            response['timestamp'] = out_shifts.aggregate(
                timestamp=Max('dt_change'))['timestamp']
            response['shifts_list'] = out_shifts

        return response

    """
    Получение смен промоутеров
    """

    @rpc(DateTime(sub_name='timestamp', min_occurs=1, nillable=False),
         HeadquaterSoapModel.customize(min_occurs=0, nillable=False),
         AgencySoapModel.customize(min_occurs=0, nillable=False),
         Integer(sub_name='amount', min_occurs=0, nillable=False),
         _returns=ComplexPromoShiftsResponseSoapModel,
         _throws=[AuthenticationError, AuthorizationError, CustomError])
    @soap_logger
    @check_auth_data
    def getPromoShifts(ctx, dt_change, headquater, agency, amount):
        return _calc_shifts(ctx,
                            dt_change,
                            headquater,
                            agency,
                            amount,
                            party='promo')

    """
    Получение смен брокеров
    """

    @rpc(DateTime(sub_name='timestamp', min_occurs=1, nillable=False),
         HeadquaterSoapModel.customize(min_occurs=0, nillable=False),
         AgencySoapModel.customize(min_occurs=0, nillable=False),
         Integer(sub_name='amount', min_occurs=0, nillable=False),
         _returns=ComplexPromoShiftsResponseSoapModel,
         _throws=[AuthenticationError, AuthorizationError, CustomError])
    @soap_logger
    @check_auth_data
    def getBrokerShifts(ctx, dt_change, headquater, agency, amount):
        return _calc_shifts(ctx,
                            dt_change,
                            headquater,
                            agency,
                            amount,
                            party='broker')

    """
    Удаление смены из заявки на аутсорсинг по решению управляюего магазином
    """

    @rpc(Array(ShiftDeleteSoapModel),
         HeadquaterSoapModel.customize(min_occurs=0, nillable=False),
         _returns=Unicode,
         _throws=[AuthenticationError, AuthorizationError, CustomError])
    @soap_logger
    @check_auth_data
    def deleteOutsourcingShifts(ctx, shifts, headquater):
        auth_and_check_perms(ctx.in_header.login, ctx.in_header.password)

        # TODO remove
        if not headquater:
            db_headquarter = open_headquarter_by_code('mvideo')
        else:
            # Клиент
            db_headquarter = open_headquarter_by_code(headquater.code)
        if not db_headquarter:
            raise CustomError(
                f'Headquater {headquater.code} is not registered')

        # Выходим, если массив смен не задан
        if not shifts:
            return {'result': 'ok'}

        # Помечаем смены как удаленные и формируем уведомления
        for shift in shifts:
            # ----------------------------------------------------------
            out_shift = OutsourcingShift.objects.filter(
                guid=shift.guid, headquater=db_headquarter).first()
            if not out_shift:
                continue
            # Создаем и отправляем уведомления об удаленной смене
            make_notify_data(out_shift, 'agency', 'delete_shift_template')

            # Меняем состояние на удалена
            out_shift.state = 'delete'
            out_shift.save(update_fields=['state'])
            # -----------------------------------------------------------
        return {'result': 'ok'}

    """
    Получение изменений в данных сотрудников
    """

    @rpc(DateTime(sub_name='timestamp', min_occurs=1, nillable=False),
         HeadquaterSoapModel.customize(min_occurs=0, nillable=False),
         Integer(sub_name='amount', min_occurs=1, nillable=False),
         _returns=ComplexEmployeeEventResponseSoapModel,
         _throws=[AuthenticationError, AuthorizationError, CustomError])
    @soap_logger
    @check_auth_data
    def getEmployeeEvents(ctx, timestamp, headquater, amount):
        auth_and_check_perms(ctx.in_header.login, ctx.in_header.password)

        # Ограничинваем максимальное количество событий, возвращаемых за 1 раз
        if amount <= 0:
            amount = 100

        # TODO remove
        if not headquater:
            db_headquarter = open_headquarter_by_code('mvideo')
        else:
            # Клиент
            db_headquarter = open_headquarter_by_code(headquater.code)
        if not db_headquarter:
            raise CustomError(
                f'Headquater {headquater.code} is not registered')

        # Поиск событий, начиная с заданного в запросе timestamp
        response = dict()
        response['events_list'] = []
        events = EmployeeEvent.objects.filter(dt_created__gt=timestamp, headquater=db_headquarter). \
                     select_related('agency_employee', 'agency').order_by('id')[:amount]
        # Обогощаем найденные события доп. полями
        for event in events:
            # Тип агентства
            event.agency.party = event.agency.headquater.party
            # Документы сотрудника
            event.agency_employee.documents = EmployeeDoc.objects.filter(
                agency_employee=event.agency_employee).order_by('-id')
            # Обнуляем лишние поля
            if event.kind != 'recruitment':
                event.recruitment_date = None
            if event.kind != 'dismissal':
                event.dismissal_reason = None
                event.dismissal_date = None
                event.blacklist = None
        # Добавляем возвращемые события в ответное сообщение
        response['result'] = len(events)
        if events:
            response['timestamp'] = events.aggregate(
                timestamp=Max('dt_created'))['timestamp']
            response['events_list'] = events
        return response

    """DEPRICATED"""

    @rpc(HeadquaterSoapModel.customize(min_occurs=1, nillable=False),
         OrganizationSoapModel.customize(min_occurs=1, nillable=False),
         AgencySoapModel.customize(min_occurs=1, nillable=False),
         EmployeeMinSoapModel,
         EventSoapModel.customize(sub_name='event'),
         Unicode(sub_name='kind', min_occurs=1, nillable=False),
         Unicode(sub_name='number', min_occurs=0, nillable=False),
         Date(sub_name='recruitment_date', min_occurs=0, nillable=False),
         Date(sub_name='recruitment_state', min_occurs=0, nillable=False),
         Date(sub_name='dismissal_date', min_occurs=0, nillable=False),
         Unicode(sub_name='reject_reason', min_occurs=0, nillable=False),
         Unicode(sub_name='dismissal_reason', min_occurs=0, nillable=False),
         _returns=Unicode,
         _throws=[AuthenticationError, AuthorizationError, CustomError])
    @soap_logger
    @check_auth_data
    def setEventHistory(ctx, headquater, organization, agency, employee,
                        employeeevent, kind, number, recruitment_date,
                        recruitment_state, dismissal_date, reject_reason,
                        dismissal_reason):
        raise CustomError('Method is deprocated')

        # TODO изменить проверку доступа с is_superuser

        auth_and_check_perms(ctx.in_header.login, ctx.in_header.password)

        headquater_id = get_headquater_id(headquater.code)

        org = Organization.objects.get(code=organization.code,
                                       headquater_id=headquater_id)
        if not org:
            raise CustomError('No organiztion')

        agn = Agency.objects.get(code=agency.code)
        if not agn:
            raise CustomError('No agency')

        emp = AgencyEmployee.objects.get(number=employee.number, agency=agn)
        if not emp:
            raise CustomError('No employee')

        event = EmployeeEvent.objects.get(guid=employeeevent.guid)

        user = User.objects.get(username=ctx.in_header.login)

        if kind not in dict(EVENT_HISTORY_KIND_CHOICES):
            raise CustomError('No kind')
        elif kind == 'accept_recruitment':

            if not recruitment_date:
                raise CustomError('No recruitment_date')

            if recruitment_state not in ['active', 'inactive']:
                raise CustomError('No recruitment_state')
            """Создаем объект внешнего события"""
            EmployeeHistory.objects.create(user=user,
                                           headquater_id=headquater_id,
                                           organization=org,
                                           event=event,
                                           agency_employee=emp,
                                           agency=agn,
                                           kind=kind,
                                           recruitment_date=recruitment_date,
                                           recruitment_state=recruitment_state)

            if recruitment_state == 'active':
                """Создаем объект назначения"""
                OrgHistory.objects.create(headquater_id=headquater_id,
                                          organization=org,
                                          agency_employee=emp,
                                          number=number,
                                          start=recruitment_date)
            """Устанавливаем EmployeeEvent флаг, что ответ на него получен"""
            event.answer_received = True
            event.save(update_fields=['answer_received'])
        elif kind == 'reject_recruitment':

            if not reject_reason:
                raise CustomError('No reject_reason')
            """Создаем объект внешнего события"""
            EmployeeHistory.objects.create(user=user,
                                           headquater_id=headquater_id,
                                           organization=org,
                                           event=event,
                                           agency_employee=emp,
                                           agency=agn,
                                           kind=kind,
                                           reject_reason=reject_reason)
            """Устанавливаем EmployeeEvent флаг, что ответ на него получен"""
            event.answer_received = True
            event.save(update_fields=['answer_received'])

        elif kind == 'dismissal':

            if not dismissal_date or not dismissal_reason:
                raise CustomError('No dismissal date or reason')
            """Ищем назначение и устанавливаем дату увольнения"""
            org_history = OrgHistory.objects.get(organization=org,
                                                 agency_employee=emp)
            if not org_history:
                raise CustomError('No OrgHistory')
            org_history.end = dismissal_date - timedelta(days=1)
            org_history.save(update_fields=['end'])
            """Ищем смены данного сотрудника после даты увольнения и снимаем назначение"""
            OutsourcingShift.objects.filter(
                agency_employee=emp,
                start_date__gt=dismissal_date - timedelta(days=1),
                headquater_id=headquater_id).update(agency_employee=None)
            """Создаем объект внешнего события"""
            EmployeeHistory.objects.create(user=user,
                                           headquater_id=headquater_id,
                                           organization=org,
                                           event=event,
                                           agency_employee=emp,
                                           agency=agn,
                                           kind=kind,
                                           dismissal_date=dismissal_date,
                                           dismissal_reason=dismissal_reason)
            """Устанавливаем EmployeeEvent флаг, что ответ на него получен"""
            event.answer_received = True
            event.save(update_fields=['answer_received'])
            """Устанавливаем сотруднику дату обновления данных по API"""
            event.agency_employee.last_external_update = timezone.now()
            event.agency_employee.save(update_fields=['last_external_update'])

        return "ok"

    """Подтверждение или отказ в приеме сотрудника из кадровой системы клиента"""

    @rpc(EventSoapModel2.customize(sub_name='event',
                                   min_occurs=1,
                                   nillable=False),
         Unicode(sub_name='status', min_occurs=1, nillable=False),
         Unicode(sub_name='recruitmentState',
                 min_occurs=0,
                 nillable=False,
                 default='active'),
         Date(sub_name='recruitmentDate', min_occurs=0, nillable=False),
         Unicode(sub_name='externalNumber', min_occurs=0, nillable=False),
         Unicode(sub_name='rejectReason', min_occurs=0, nillable=False),
         _returns=Unicode,
         _throws=[AuthenticationError, AuthorizationError, CustomError])
    @soap_logger
    @check_auth_data
    def setRecruitmentStatus(ctx, employeeevent, status, recruitmentState,
                             recruitmentDate, externalNumber, rejectReason):
        user = User.objects.get(username=ctx.in_header.login)
        auth_and_check_perms(ctx.in_header.login, ctx.in_header.password)

        # Проверка параметров
        event = EmployeeEvent.objects.get(guid=employeeevent.guid)
        if not event:
            raise CustomError(f'Event {employeeevent.guid} is undefined')
        if recruitmentState and recruitmentState not in ['active', 'inactive']:
            raise CustomError('No recruitmentState')
        if status not in ['accept', 'reject']:
            return

        # Подтверждение регистрации
        if status == 'accept':
            error = accept_employee_attach(user, event, recruitmentState,
                                           recruitmentDate, externalNumber)
        # Регистрация отклонена
        else:
            error = reject_employee_attach(user, event, rejectReason)
        # Обработчик ошибок
        if error:
            raise CustomError(error)

        # Устанавливаем сотруднику дату обновления данных по API
        event.agency_employee.last_external_update = timezone.now()
        event.agency_employee.save(update_fields=['last_external_update'])

        return

    """Открепление сотрудника от клиента по запросу из кадровой системы"""

    @rpc(HeadquaterSoapModel.customize(min_occurs=1, nillable=False),
         OrganizationSoapModel,
         AgencySoapModel.customize(min_occurs=1, nillable=False),
         Unicode(sub_name='externalNumber', min_occurs=1, nillable=False),
         Date(sub_name='dismissalDate', min_occurs=1, nillable=False),
         Unicode(sub_name='dismissalReason', min_occurs=1, nillable=False),
         Boolean(sub_name='blacklist', min_occurs=1, nillable=False),
         _returns=Unicode,
         _throws=[AuthenticationError, AuthorizationError, CustomError])
    @soap_logger
    @check_auth_data
    def dismissEmployee(ctx, headquater, organization, agency, ext_number,
                        dismissal_date, dismissal_reason, blacklist):
        user = User.objects.get(username=ctx.in_header.login)
        auth_and_check_perms(ctx.in_header.login, ctx.in_header.password)

        # Проверка параметров
        db_headquarter = open_headquarter_by_code(headquater.code)
        if not db_headquarter:
            raise CustomError(f'Headquater {headquater.code} is not found')
        if organization:
            db_organization = open_organization_by_code(
                organization.code, db_headquarter)
            if not db_organization:
                raise CustomError(
                    f'Organization {organization.code} is not found')
        else:
            db_organization = None
        db_agency = open_agency_by_code(agency.code, None)
        if not db_agency:
            raise CustomError(f'Agency {agency.code} is not found')

        # Определяем увольняемого сотрудника
        employees = employees_by_ext_number(db_headquarter, db_agency,
                                            ext_number)
        for employee in employees:
            dismiss_employee(user, employee, dismissal_date, dismissal_reason,
                             blacklist, db_headquarter, db_organization)
            # Устанавливаем сотруднику дату обновления данных по API
            employee.last_external_update = timezone.now()
            employee.save(update_fields=['last_external_update'])
        return

    ########
    @rpc(HeadquaterSoapModel.customize(min_occurs=1, nillable=False),
         Array(OrgunitSoapModel.customize(min_occurs=1, nillable=False)),
         Array(OrglinkSoapModel.customize(min_occurs=0, nillable=False)),
         _returns=Unicode,
         _throws=[AuthenticationError, AuthorizationError, CustomError])
    @soap_logger
    @check_auth_data
    def setOrgunits(ctx, headquater, orgunits, orglinks):
        """Set Orgunits. Синхронизитрует орг. структуру на основе данных из портала планирования"""

        auth_and_check_perms(ctx.in_header.login, ctx.in_header.password)

        # Headquarter
        headquater_id = get_headquater_id(headquater.code)

        # Organizations
        orgunits_received = 0
        orgunits_created = 0
        orgunits_errors = 0
        if orgunits:
            for orgunit in orgunits:
                orgunits_received += 1
                org, org_created = Organization.objects.get_or_create(
                    code=orgunit.code, headquater_id=headquater_id)
                if org_created:
                    orgunits_created += 1
                org.name = orgunit.name
                org.address = orgunit.address
                org.kind = 'store'
                if orgunit.parent and org_created:
                    parent_org = Organization.objects.filter(
                        code=orgunit.parent.code,
                        headquater_id=headquater_id).first()
                    if parent_org:
                        org.parent = parent_org
                    else:
                        default, default_created = Organization.objects.get_or_create(
                            code=headquater.code + '_city_undefined',
                            name='Город не определен',
                            headquater_id=headquater_id,
                            kind='city')
                        org.parent = default
                org.last_external_update = timezone.now()
                org.save()

        # OrgLinks
        orglinks_received = 0
        orglinks_created = 0
        orglinks_errors = 0
        if orglinks:
            for orglink_imp in orglinks:
                orglinks_received += 1
                organization = Organization.objects.filter(
                    code=orglink_imp.organization.code).first()
                if not organization:
                    orglinks_errors += 1
                    continue
                agency = Agency.objects.filter(
                    code=orglink_imp.agency.code).first()
                if not agency:
                    orglinks_errors += 1
                    continue
                _, orglink_created = OrgLink.objects.get_or_create(
                    agency=agency,
                    organization=organization,
                    headquater_id=headquater_id)
                if orglink_created:
                    orglinks_created += 1

        return {
            'result': 'ok',
            'orgunits_received': orgunits_received,
            'orgunits_created': orgunits_created,
            'orgunits_errors': orgunits_errors,
            'orglinks_received': orglinks_received,
            'orglinks_created': orglinks_created,
            'orglinks_errors': orglinks_errors,
        }

    @rpc(HeadquarterSoapModel.customize(min_occurs=1, nillable=False),
         UserExtSoapModel.customize(sub_name='user',
                                    min_occurs=1,
                                    nillable=False),
         Array(AccessProfileSoapModel,
               sub_name='accessProfiles').customize(min_occurs=1,
                                                    nillable=False),
         _throws=[
             AuthenticationError, AuthorizationError,
             error.ResourceNotFoundError
         ])
    @soap_logger
    @check_auth_data
    def setUser(ctx, headquarter, user, access_list):
        auth_and_check_perms(ctx.in_header.login, ctx.in_header.password)

        # Обновляем или создаем сотрудника
        user_defaults = {
            'first_name': user.first_name,
            'last_name': user.last_name,
            'email': user.email,
            'is_active': user.is_active
        }
        db_user, created = User.objects.update_or_create(
            username=user.username, defaults=user_defaults)
        db_headquarter = open_headquarter_by_code(headquarter.code)
        db_access_role = None

        # Установка прав доступа
        if access_list is None:
            access_list = []

        for access_profile in access_list:
            try:
                db_organization = open_organization_by_code(
                    access_profile.unit.code, db_headquarter)
            except error.ResourceNotFoundError:
                continue

            if access_profile.role is not None:
                db_access_role = open_role_by_code(access_profile.role.code)

            if db_access_role is None:
                raise error.ResourceNotFoundError('accessRole')

            profile, _ = AccessProfile.objects.update_or_create(
                user=db_user,
                unit_type=ContentType.objects.get_for_model(db_organization),
                unit_id=db_organization.id,
                role=db_access_role,
                headquater=db_headquarter)