Example #1
0
def reschedule_job(job, schedule_event=None):
    """Regenerates the shifts associated with this job. If a schedule_event is passed then it will
    only regenerate overlapping shifts.
    """
    if schedule_event:
        schedule_events = [schedule_event]
    else:
        schedule_events = db.query(ScheduleEvent).filter(
            or_(ScheduleEvent.schedule.in_([x.id for x in job.schedules]),
                ScheduleEvent.id.in_([x.id
                                      for x in job.schedule_events]))).all()

    if not schedule_event:
        # Completely regenerate this schedule. Drop and recreate everything.
        existing = db.query(Shift).filter(Shift.job == job.id).all()
        new = create_shift_schedule(job, schedule_events)
        for shift in existing:
            remove_shift(db, shift)
        db.flush()
        for shift in new:
            add_shift(db, shift)
    if schedule_event:
        # Find adjacent schedule events
        adjacent = []
        starttime = schedule_event.starttime - datetime.timedelta(
            seconds=10)  # Treat times within 10 seconds as being adjacent
        endtime = schedule_event.starttime + datetime.timedelta(
            seconds=schedule_event.duration +
            10)  # Calculate the endtime, and add 10 seconds of margin
        for event in schedule_events:
            if not event in adjacent:
                eventstart = event.starttime
                eventend = event.starttime + datetime.timedelta(
                    seconds=event.duration)
                if eventstart <= starttime and eventend >= starttime:
                    adjacent.append(event)
                elif eventstart >= starttime and eventstart <= endtime:
                    adjacent.append(event)
        # Delete all adjacent schedule events
        for event in adjacent:
            shifts = db.query(Shift).filter(
                Shift.schedule_event == event.id).all()
            for shift in shifts:
                remove_shift(db, shift)
        db.flush()
        # Create new shifts for adjacent schedule events
        if request.method == "DELETE":
            adjacent.remove(schedule_event)
        new = create_shift_schedule(job, adjacent)
        for shift in new:
            add_shift(db, shift)
    shifts = db.query(Shift).filter(Shift.job == job.id).all()
    assignments = db.query(ShiftAssignment).all()
    return shifts
Example #2
0
def crud_single(model, event=None, department=None, id=None):
    perms = model_permissions(model.__tablename__.lower())
    if request.method == "GET":
        if READ_PERMS.intersection(
                perms['*']) or (id in perms
                                and READ_PERMS.intersection(perms[id])):
            full = request.args.get("full",
                                    False,
                                    type=lambda x: x.lower() == 'true')
            instance = db.query(model).filter(model.id == id).one_or_none()
            return jsonify(
                model.serialize(instance, serialize_relationships=full))
        raise PermissionDenied()
    elif request.method == "PATCH":
        if WRITE_PERMS.intersection(
                perms['*']) or (id in perms
                                and WRITE_PERMS.intersection(perms[id])):
            g.data['id'] = id
            g.data = {k: v for k, v in g.data.items() if hasattr(model, k)}
            instance = model.deserialize(g.data)
            db.add(instance)
            if hasattr(instance, 'onchange_cb'):
                db.flush()
                for cb in instance.onchange_cb:
                    cb(db, instance)
            db.commit()
            return jsonify(model.serialize(instance))
        raise PermissionDenied()
    elif request.method == "DELETE":
        if WRITE_PERMS.intersection(
                perms['*']) or (id in perms
                                and WRITE_PERMS.intersection(perms[id])):
            instance = db.query(model).filter(model.id == id).one_or_none()
            if not instance:
                return "", 404
            instance_data = None
            if hasattr(instance, 'onchange_cb'):
                instance_data = model.serialize(instance,
                                                serialize_relationships=True)
            db.delete(instance)
            if hasattr(instance, 'onchange_cb'):
                db.flush()
                for cb in instance.onchange_cb:
                    cb(db, instance, deleted=instance_data)
            db.commit()
            return "null"
        raise PermissionDenied()
    raise MethodNotAllowed()
Example #3
0
def add_shift(db, shift):
    signups = db.query(ShiftSignup).filter(
        ShiftSignup.job == shift.job, ShiftSignup.starttime == shift.starttime,
        ShiftSignup.duration == shift.duration,
        ShiftSignup.shift == None).order_by(ShiftSignup.signuptime).all()
    for signup in signups:
        if shift.slots > shift.filledslots:
            db.add(shift)
            db.flush()
            signup.shift = shift.id
            db.add(signup)
            assignment = ShiftAssignment(badge=signup.badge,
                                         shift=shift.id,
                                         event=shift.event)
            db.add(assignment)
            shift.filledslots += 1
    db.add(shift)
Example #4
0
def initial_setup():
    if User.query.first():
        return "Initial setup has already completed.", 403
    if request.json['username'] and request.json['email'] and request.json[
            'password']:
        user = User(username=request.json['username'],
                    email=request.json['email'],
                    password=sha256_crypt.hash(request.json['password']),
                    active=True)
        role = Role(name="Server Admin", description="Allowed to do anything.")
        db.add(user)
        db.add(role)
        db.flush()
        perm = Permission(operation="*.*.*", role=role.id)
        grant = Grant(user=user.id, role=role.id)
        db.add(perm)
        db.add(grant)
        db.commit()
        return "null", 200
    return "", 406
Example #5
0
def create_attendee(uber_model, event, hotel_eligible=True):
    staff_badge_type = db.query(BadgeType).filter(BadgeType.name == "Staff", BadgeType.event == event).one_or_none()
    if not staff_badge_type:
        staff_badge_type = BadgeType(name="Staff", description="Experienced Volunteers")
        db.flush()
    badge = Badge(
        event=event,
        badge_type=staff_badge_type.id,
        printed_number=uber_model['badge_num'],
        printed_name=uber_model['badge_printed_name'],
        public_name=uber_model['full_name'],
        search_name=uber_model['full_name'].lower(),
        first_name=uber_model['first_name'],
        last_name=uber_model['last_name'],
        legal_name_matches=(not uber_model['legal_name']),
        emergency_contact_name=uber_model['ec_name'],
        emergency_contact_phone=uber_model['ec_phone'],
        phone=uber_model['cellphone'],
        email=uber_model['email'],
        uber_id=uber_model['id']
    )
    db.add(badge)
    db.flush()
    if hotel_eligible:
        hotel_request = HotelRoomRequest(event=event, badge=badge.id)
        db.add(hotel_request)
        db.flush()
    return badge
Example #6
0
def run_staff_import(email, password, url, event):
    session = requests.Session()
    db.post(url + "/accounts/login",
            data={
                "email": email,
                "password": password,
                "original_location": "homepage"
            })
    attendees = get_uber_csv(session, "Attendee", url)
    num_staff = 0
    print("Retrieved export")

    role = db.query(Role).filter(Role.name == "Default Staff").one_or_none()
    if not role:
        role = Role(name="Default Staff",
                    description="Automatically assigned to staff.",
                    event=event)
        db.add(role)
        db.flush()
        for perm in [
                'staff.search_names', 'hotel_request.create', 'event.read'
        ]:
            permission = Permission(operation=perm, role=role.id)
            db.add(permission)

    dh_role = db.query(Role).filter(
        Role.name == "Department Head").one_or_none()
    if not dh_role:
        dh_role = Role(
            name="Department Head",
            description="Automatically assigned to department heads.",
            event=event)
        db.add(dh_role)
        db.flush()
        for perm in ['department.write', 'hotel_request.approve']:
            permission = Permission(operation=perm, role=dh_role.id)
            db.add(permission)

    print("Adding attendees...")
    for attendee in attendees:
        if attendee['hotel_eligible'].lower() == "true":
            num_staff += 1
            user = db.query(User).filter(
                User.password == attendee['id']).one_or_none()
            if not user:
                user = User(username=attendee['id'],
                            email=attendee['id'],
                            password=attendee['id'],
                            active=False)
                db.add(user)
                db.flush()
            grant = db.query(Grant).filter(
                Grant.user == user.id, Grant.role == role.id).one_or_none()
            if not grant:
                grant = Grant(user=user.id, role=role.id)
                db.add(grant)
            badge = db.query(Badge).filter(
                Badge.event == event,
                Badge.uber_id == attendee['id']).one_or_none()
            if badge:
                badge.printed_number = attendee['badge_num']
                badge.printed_name = attendee['badge_printed_name']
                badge.search_name = "{} {}".format(
                    attendee['first_name'].lower(),
                    attendee['last_name'].lower())
                badge.first_name = attendee['first_name']
                badge.last_name = attendee['last_name']
                badge.legal_name = attendee['legal_name']
                badge.legal_name_matches = bool(attendee['legal_name'])
                badge.email = attendee['email']
                badge.phone = attendee['cellphone']
                db.add(badge)
            if not badge:
                badge = Badge(uber_id=attendee['id'],
                              event=event,
                              printed_number=attendee['badge_num'],
                              printed_name=attendee['badge_printed_name'],
                              search_name="{} {}".format(
                                  attendee['first_name'].lower(),
                                  attendee['last_name'].lower()),
                              first_name=attendee['first_name'],
                              last_name=attendee['last_name'],
                              legal_name=attendee['legal_name'],
                              legal_name_matches=bool(attendee['legal_name']),
                              email=attendee['email'],
                              phone=attendee['cellphone'],
                              user_id=user.id)
                db.add(badge)

    print("Adding departments...")
    departments = get_uber_csv(session, "Department", url)
    for department in departments:
        current = db.query(Department).filter(
            Department.event == event,
            Department.uber_id == department['id']).one_or_none()
        if not current:
            dept = Department(uber_id=department['id'],
                              name=department['name'],
                              description=department['description'],
                              event=event)
            db.add(dept)

    print("Adding staffers to departments...")
    deptmembers = get_uber_csv(session, "DeptMembership", url)
    for dm in deptmembers:
        badge = db.query(Badge).filter(
            Badge.event == event,
            Badge.uber_id == dm['attendee_id']).one_or_none()
        if not badge:
            print("Could not find badge {} to place in department {}.".format(
                dm['attendee_id'], dm['department_id']))
            continue
        department = db.query(Department).filter(
            Department.event == event,
            Department.uber_id == dm['department_id']).one_or_none()
        if not department:
            print("Could not find department {} for attendee {}.".format(
                dm['department_id'], dm['attendee_id']))
            continue
        existing = db.query(BadgeToDepartment).filter(
            BadgeToDepartment.badge == badge.id,
            BadgeToDepartment.department == department.id).one_or_none()
        if not existing:
            department_member = BadgeToDepartment(badge=badge.id,
                                                  department=department.id)
            db.add(department_member)
        grant = db.query(Grant).filter(
            Grant.user == badge.user_id, Grant.role == dh_role.id,
            Grant.department == department.id).one_or_none()
        if (dm['is_dept_head'].lower()
                == "true") or (dm['is_checklist_admin'].lower() == "true"):
            if not grant:
                grant = Grant(user=badge.user_id,
                              role=dh_role.id,
                              department=department.id)
                db.add(grant)
        elif grant:
            db.delete(grant)
    print("Committing changes...")
    db.commit()
    print("Done.")
Example #7
0
def import_mock():
    if not 'event' in request.json:
        return "Event is a required parament.", 406
    event = db.query(Event).filter(
        Event.id == request.json['event']).one_or_none()
    if not event:
        return "Could not locate event {}".format(escape(
            request.json['event'])), 404
    badges = db.query(Badge).filter(Badge.event == event.id).all()
    if badges:
        return "You cannot generate mock data if there are already badges. Please delete the badges first if you really want junk data.", 412
    staff_badge_type = db.query(BadgeType).filter(
        BadgeType.name == "Staff").one_or_none()
    if not staff_badge_type:
        staff_badge_type = BadgeType(name="Staff",
                                     description="Helps run the show")
        db.add(staff_badge_type)
    attendee_badge_type = db.query(BadgeType).filter(
        BadgeType.name == "Attendee").one_or_none()
    if not attendee_badge_type:
        attendee_badge_type = BadgeType(name="Attendee",
                                        description="Come to see the show")
        db.add(attendee_badge_type)
    db.flush()
    if 'attendees' in request.json:
        print("Generating {} attendees".format(request.json['attendees']))
        for i in range(request.json['attendees']):
            if i % 1000 == 0:
                print("  ...{}/{}".format(i, request.json['attendees']))
            first_name = names.get_first_name()
            last_name = names.get_last_name()
            legal_name = "{} {}".format(first_name, last_name)
            full_name = legal_name
            legal_name_matches = True
            printed_name = legal_name
            if random.random() > 0.95:
                legal_name = names.get_full_name()
                legal_name_matches = False
            if random.random() > 0.75:
                printed_name = names.get_last_name()
            provider = random.choice(
                ["verizon", "gmail", "yahoo", "aol", "magfest"])
            site = random.choice(["net", "com", "org", "co.uk"])
            email = "{}.{}@{}.{}".format(first_name, last_name, provider, site)
            badge = Badge(
                event=event.id,
                badge_type=attendee_badge_type.id,
                printed_number=(((i + request.json['staffers']) // 1000 + 1) *
                                1000) if 'staffers' in request.json else i,
                printed_name=printed_name,
                search_name=printed_name.lower(),
                first_name=first_name,
                last_name=last_name,
                legal_name=legal_name,
                legal_name_matches=legal_name_matches,
                email=email)
            db.add(badge)

    departments = []
    if 'departments' in request.json:
        print("Generating {} departments...".format(
            request.json['departments']))
        dept_names = {}
        while len(dept_names.keys()) < request.json['departments']:
            name = random.choice([
                "Tech", "Staff", "Arcade", "Game", "Medical", "Hotel", "Cat",
                "Concert", "Music", "Security", "Food", "Rescue", "Warehouse",
                "Logistics", "Truck", "Management"
            ])
            name += random.choice([
                " Ops", " Management", " Wranglers", " Herders", "",
                " Chasers", " Fixers", " Breakers", " Managers", " Destroyers",
                " Cleaners"
            ])
            name = ''.join(
                [x.upper() if random.random() < 0.05 else x for x in name])
            dept_names[name] = None
        for name in dept_names.keys():
            description = "The {} department.".format(name)
            department = Department(name=name,
                                    description=description,
                                    event=event.id)
            db.add(department)
            departments.append(department)

    staffers = []
    if 'staffers' in request.json:
        print("Generating {} staffers...".format(request.json['staffers']))
        for i in range(request.json['staffers']):
            if i % 1000 == 0:
                print("  ...{}/{}".format(i, request.json['staffers']))
            first_name = names.get_first_name()
            last_name = names.get_last_name()
            legal_name = "{} {}".format(first_name, last_name)
            full_name = legal_name
            legal_name_matches = True
            printed_name = legal_name
            if random.random() > 0.95:
                legal_name = names.get_full_name()
                legal_name_matches = False
            if random.random() > 0.75:
                printed_name = names.get_last_name()
            provider = random.choice(
                ["verizon", "gmail", "yahoo", "aol", "magfest"])
            site = random.choice(["net", "com", "org", "co.uk"])
            email = "{}.{}@{}.{}".format(first_name, last_name, provider, site)
            badge = Badge(event=event.id,
                          badge_type=staff_badge_type.id,
                          printed_number=i,
                          printed_name=printed_name,
                          search_name=printed_name.lower(),
                          first_name=first_name,
                          last_name=last_name,
                          legal_name=legal_name,
                          legal_name_matches=legal_name_matches,
                          email=email)
            db.add(badge)
            staffers.append(badge)
        print("Flushing database...")
        db.flush()

        print("Adding hotel information...")
        room_block = HotelRoomBlock(event=event.id,
                                    name="The staff block",
                                    description="")
        db.add(room_block)
        hotel_location = HotelLocation(name="The Really Big Hotel",
                                       address="123 Waterfront",
                                       event=event.id)
        db.add(hotel_location)
        room_nights = []
        for i in ["Wednesday", "Thursday"]:
            room_night = HotelRoomNight(name=i,
                                        event=event.id,
                                        restricted=True,
                                        restriction_type="Setup",
                                        hidden=False)
            db.add(room_night)
            room_nights.append(room_night)
        for i in ["Friday", "Saturday", "Sunday"]:
            room_night = HotelRoomNight(name=i,
                                        event=event.id,
                                        restricted=False,
                                        restriction_type="Setup",
                                        hidden=False)
            db.add(room_night)
            room_nights.append(room_night)
        print("Flushing database...")
        db.flush()

        print("Adding staffers to departments...")
        requested_room = []
        for staffer in staffers:
            staffer_depts = list(departments)
            hotel_requested = False
            declined = False

            preferred_department = None
            for i in range(int(random.random() / 0.3)):
                staffer_dept = random.choice(staffer_depts)
                staffer_depts.remove(staffer_dept)
                assignment = BadgeToDepartment(badge=staffer.id,
                                               department=staffer_dept.id)
                db.add(assignment)
                preferred_department = staffer_dept.id

            if random.random() > 0.3:
                hotel_requested = True
                if random.random() > 0.1:
                    declined = True
                else:
                    requested_room.append(staffer)
                hotel_request = HotelRoomRequest(
                    badge=staffer.id,
                    declined=declined,
                    prefer_department=random.random() > 0.1,
                    preferred_department=preferred_department,
                    notes="Please give room.",
                    prefer_single_gender=random.random() > 0.3,
                    preferred_gender=random.choice(['male', 'female',
                                                    'other']),
                    noise_level=random.choice([
                        'Quiet - I am quiet, and prefer quiet.',
                        "Moderate - I don't make a lot of noise.",
                        "Loud - I'm ok if someone snores or I snore.",
                    ]),
                    smoke_sensitive=random.choice([True, False]),
                    sleep_time=random.choice(
                        ['2am-4am', '4am-6am', '6am-8am', '8am-10am']),
                )
                db.add(hotel_request)

        print("Requesting Roommates...")
        requested_roommates = []
        for staffer in requested_room:
            for i in room_nights:
                if random.random() > 0.2:
                    req = RoomNightRequest(badge=staffer.id,
                                           requested=True,
                                           room_night=i.id)
                    db.add(req)
            for i in range(random.randrange(0, 3)):
                other = random.choice(requested_room)
                if other == staffer:
                    continue
                if random.random() > 0.2:
                    if not (staffer.id, other.id) in requested_roommates:
                        req = HotelRoommateRequest(requester=staffer.id,
                                                   requested=other.id)
                        requested_roommates.append((staffer.id, other.id))
                        db.add(req)
                    if random.random() > 0.6:
                        if not (other.id, staffer.id) in requested_roommates:
                            req = HotelRoommateRequest(requester=other.id,
                                                       requested=staffer.id)
                            requested_roommates.append((other.id, staffer.id))
                            db.add(req)
                else:
                    if not (staffer.id, other.id) in requested_roommates:
                        req = HotelAntiRoommateRequest(requester=staffer.id,
                                                       requested=other.id)
                        requested_roommates.append((staffer.id, other.id))
                        db.add(req)
                if random.random() > 0.9:
                    if not (other.id, staffer.id) in requested_roommates:
                        req = HotelAntiRoommateRequest(requester=other.id,
                                                       requested=staffer.id)
                        requested_roommates.append((other.id, staffer.id))
                        db.add(req)
        print("Flushing db...")
        db.flush()

    print("Committing...")
    db.commit()
    print("Done!")
    return "null", 200
Example #8
0
def staffer_auth():
    if not User.query.first():
        return "You must set up this server before using this method to log in.", 403
    event = config.uber_event
    req = {
        "method": "attendee.search",
        "params": [
            request.json['token'],
            "full"
        ]
    }
    results = requests.post(config.uber_api_url, headers=headers, json=req).json()['result']
    if len(results) == 0:
        return "no result", 403
    result = results[0]
    if not 'id' in result:
        return "no id", 403
    uber_id = result['id']
    if uber_id != request.json['token']:
        return "wrong token", 403
    if result['badge_status_label'] == "Deferred":
        return "Badge is deferred", 403

    badge = db.query(Badge).filter(Badge.uber_id == uber_id).one_or_none()
    hotel_request = None
    if badge:
        hotel_request = db.query(HotelRoomRequest).filter(HotelRoomRequest.badge == badge.id).one_or_none()
    if not hotel_request or not badge:
        req = {"method": "hotel.eligible_attendees"}
        eligible = requests.post(config.uber_api_url, headers=headers, json=req).json()['result']
        if len(eligible) == 0:
            return "Failed to load eligible attendees", 403
        if not uber_id in eligible:
            return "You are not eligible", 403
    if not badge:
        staff_badge_type = db.query(BadgeType).filter(BadgeType.event == event, BadgeType.name == "Staff").one_or_none()
        if not staff_badge_type:
            staff_badge_type = BadgeType(name="Staff", description="Experienced Volunteers", event=event)
            db.flush()
        badge = Badge(
            event=event,
            badge_type=staff_badge_type.id,
            printed_number=result['badge_num'],
            printed_name=result['badge_printed_name'],
            public_name=result['full_name'],
            search_name=result['full_name'].lower(),
            first_name=result['first_name'],
            last_name=result['last_name'],
            legal_name_matches=(not result['legal_name']),
            emergency_contact_name=result['ec_name'],
            emergency_contact_phone=result['ec_phone'],
            phone=result['cellphone'],
            email=result['email'],
            uber_id=result['id']
        )

        req = {
            "method": "dept.list",
            "params": []
        }
        uber_depts = requests.post(config.uber_api_url, headers=headers, json=req).json()['result']
        uber_depts_names = {}
        for dept_id in uber_depts:
            uber_depts_names[uber_depts[dept_id]] = dept_id

        departments = db.query(Department).filter(Department.event == event).all()
        dept_names = {}
        for dept in departments:
            dept_names[dept.name] = dept

        for dept_name in result['assigned_depts_labels']:
            if not dept_name in dept_names and dept_name in uber_depts_names:
                new_dept = Department(uber_id=uber_depts_names[dept_name], event=event, name=dept_name)
                db.add(new_dept)
                badge.departments.append(new_dept)
            elif dept_name in dept_names:
                badge.departments.append(dept_names[dept_name])
        db.add(badge)
        db.flush()
    if not hotel_request:
        hotel_request = HotelRoomRequest(event=event, badge=badge.id)
        db.add(hotel_request)
        db.flush()

    permissions = {
        "event": {
            str(event): [
                "rooming.*.request",
                "badge.*.searchname",
                f"hotel_room_request.{hotel_request.id}.write",
                "hotel_room_block.*.read",
                "hotel_location.*.read",
                "hotel_room_night.*.read",
            ],
            "*": [
                "event.*.read",
                f"badge.{badge.id}.read",
                "department.*.read"
            ]
        },
        "department": {}
    }

    for department in badge.departments:
        req = {
            "method": "dept.members",
            "params": {
                "department_id": department.uber_id
            }
        }
        result = requests.post(config.uber_api_url, headers=headers, json=req).json()
        if 'error' in result:
            print(f"Could not locate {department.name} ({department.uber_id})")
            continue
        uber_dept_members = result['result']
        for attendee in uber_dept_members['checklist_admins']:
            if attendee['id'] == badge.uber_id:
                if not str(event) in permissions["department"]:
                    permissions["department"][str(event)] = {}
                permissions["department"][str(event)][str(department.id)] = [
                    f"department.*.checklist_admin",
                    "hotel_request.*.approve"
                ]

    session = Session(badge=badge.id, secret=str(uuid.uuid4()), permissions=json.dumps(permissions), last_active=datetime.datetime.now())
    db.add(session)
    db.commit()
    response = jsonify(session.secret)
    response.set_cookie('session', session.secret)
    return response
Example #9
0
def crud_group(model, event=None, department=None):
    start = time.time()
    if request.method == "GET":
        count = request.args.get("count",
                                 False,
                                 type=lambda x: x.lower() == 'true')
        sort = request.args.get("sort", "")
        order = request.args.get("order", "asc")
        limit = request.args.get("limit", 0, type=int)
        offset = request.args.get("offset", 0, type=int)
        page = request.args.get("page", 0, type=int)
        search = request.args.get("search", "", type=str)
        search_field = request.args.get("search_field", "", type=str)
        search_mode = request.args.get("search_mode", "contains", type=str)
        search_case_sensitive = request.args.get(
            "search_case_sensitive", False, type=lambda x: x.lower() == 'true')
        full = request.args.get("full",
                                False,
                                type=lambda x: x.lower() == 'true')
        deep = request.args.get("deep",
                                False,
                                type=lambda x: x.lower() == 'true')
        if page:
            offset = page * 10
            if limit:
                offset = page * limit
        filters = []
        perms = model_permissions(model.__tablename__.lower())
        if not READ_PERMS.intersection(perms['*']):
            ids = [
                int(x) for x in perms.keys()
                if READ_PERMS.intersection(perms[x])
            ]
            if not ids:
                raise PermissionDenied(
                    f"User is not able to read any values in {model.__tablename__}"
                )
            filters.append(model.id.in_(ids))
        if event:
            filters.append(model.event == event)
        if department:
            filters.append(model.department == department)
        if search_field:
            if hasattr(model, search_field):
                columns, relationships = model.get_fields()
                relationships = {x.key: x for x in relationships}
                if search_field in relationships:
                    search_model = getattr(model, search_field)
                    model.get_modelclasses()
                    rel_model = model.modelclasses[
                        relationships[search_field].target.name]
                    search = [int(x) for x in search.split(",")]
                    filters.append(search_model.any(rel_model.id.in_(search)))
                else:
                    if search_case_sensitive:
                        search_model = getattr(model, search_field)
                    else:
                        search_model = func.lower(getattr(model, search_field))
                        search = search.lower()
                    if search_mode == "contains":
                        filters.append(
                            search_model.contains(search, autoescape=True))
                    elif search_mode == "startswith":
                        filters.append(
                            search_model.startswith(search, autoescape=True))
                    elif search_mode == "endswith":
                        filters.append(
                            search_model.endswith(search, autoescape=True))
                    elif search_mode == "equals":
                        filters.append(search_model == search)
                    elif search_mode == "notEquals":
                        filters.append(search_model != search)
        for key, val in request.args.items():
            if hasattr(model, key):
                filters.append(getattr(model, key) == val)
        rows = db.query(model).filter(*filters)
        if full:
            columns, relationships = model.get_fields()
            for relation in relationships:
                rows = rows.options(joinedload(relation.key))
        if count:
            return json.dumps(rows.count()), 200
        if hasattr(model, sort):
            if order == "asc":
                rows = rows.order_by(getattr(model, sort))
            else:
                rows = rows.order_by(getattr(model, sort).desc())
        if limit:
            rows = rows.offset(offset).limit(limit)
        elif offset:
            rows = rows.offset(offset).limit(10)
        rows = rows.all()
        now = time.time()
        print(f"{request.path} Load time {now - start}s")
        data = model.serialize(rows, serialize_relationships=full, deep=deep)
        print(f"{request.path} Serialize time {time.time() - now}s")
        return jsonify(data)
    elif request.method == "POST":
        if event:
            g.data['event'] = event
        if department:
            g.data['department'] = department
        instance = model.deserialize(g.data)
        db.add(instance)
        if hasattr(instance, 'onchange_cb'):
            db.flush()
            for cb in instance.onchange_cb:
                cb(db, instance)
        db.commit()
        return jsonify(model.serialize(instance))
    raise MethodNotAllowed()