def METHOD_NAME(
    appointer: Participant,
    room: Room,
    start: datetime, finish: datetime,
    usage: str,
    students: Iterable[Participant] | None = None,
    announce: str = '',
    outer_num: int = 0,
    *,
    type: Appoint.Type = Appoint.Type.NORMAL,
    notify: bool = True,
) -> tuple[Appoint, Literal['']]:
    '''创建预约
    创建预约并设置所有可以独立执行的功能，如状态切换等，无需额外调用。
    预约信息必须逻辑上正确，且满足预约的通用条件，如房间可用、时间有序、人数合法等。
    发起者必须有足够的信用分，否则无法创建预约。
    Args:
        appointer(Participant): 发起人
        room(Room): 预约房间
        start(datetime): 预约开始时间
        finish(datetime): 预约结束时间
        usage(str): 预约用途
        students(Iterable[Participant], optional): 预约参与人，发起人默认参与
        announce(str, optional): 预约内部公告
        outer_num(int, optional): 预约外部人数
    Keyword Args
        type(Appoint.Type): 预约类型，默认为普通预约
        notify(bool): 是否发送通知，默认为发送
    Returns:
        tuple[Appoint, Literal['']]: 预约对象和空错误信息
        tuple[None, str]: 错误信息
    '''
    _check_room_valid(room)
    _check_appoint_time(start, finish)
    if students is None:
        students = []
    students = list(students)
    if appointer not in students:
        students.append(appointer)
    inner_num = len(students)
    _check_create_num(room, type, inner_num, outer_num)
    _check_num_constraint(room, type, inner_num, outer_num)
    _check_credit(appointer)
    appoint = Appoint(
        major_student=appointer, Room=room,
        Astart=start, Afinish=finish,
        Ausage=usage, Aannouncement=announce,
        Anon_yp_num=outer_num, Ayp_num=inner_num,
        Aneed_num=_attend_require_num(room, type, start, finish),
        Atype=type,
    )
    _check_conflict(appoint)
    appoint.save()
    appoint.students_manager.set(students)
    set_scheduler(appoint)
    if notify:
        _notify_create(appoint)
    set_appoint_reminder(appoint)
    get_user_logger(appointer).info(f"发起预约，预约号{appoint.pk}")
    # 如果预约者是个人，解锁成就-完成地下室预约 该部分尚未测试
    user = appointer.Sid
    if user.is_person():
        unlock_achievement(user, '完成地下室预约')
    return _success(appoint)