Example #1
0
def dispatch_job(start_day, end_day, team_code, dispatch_days):
    """Shows all available plugins"""

    print("Dispatch started...")
    from dispatch.team import service as team_service
    from sqlalchemy.orm import sessionmaker

    sl = sessionmaker(bind=engine)
    session = sl()
    team_obj = team_service.get_by_code(db_session=session, code=team_code)
    if not team_obj:
        print(f"Failed to find team by team_code = {team_code }, aborted.")
        return

    from dispatch.plugins.kandbox_planner.data_generator.veo_data_generator import (
        dispatch_jobs_batch_optimizer,
    )

    dispatch_jobs_batch_optimizer(
        {
            "service_url": "http://localhost:8000/api/v1",
            "start_day": start_day,
            "end_day": end_day,
            "dispatch_days": dispatch_days,
            "team_id": team_obj.id,
        }
    )
Example #2
0
def create(*, db_session, worker_in: WorkerCreate) -> Worker:
    """Creates an worker."""
    flag, msg = _check_business_hour(worker_in.business_hour)
    if flag:
        log.error(f"{worker_in.code} , {msg}")
        raise HTTPException(status_code=400,
                            detail=f"{worker_in.code} , {msg}")
    team = team_service.get_by_code(db_session=db_session,
                                    code=worker_in.team.code)
    if worker_in.location is not None:
        worker_in.location.org_id = worker_in.org_id
        location_obj = location_service.get_or_create_by_code(
            db_session=db_session, location_in=worker_in.location)
    else:
        location_obj = None

    if worker_in.dispatch_user:
        u = auth_service.get_by_email(db_session=db_session,
                                      email=worker_in.dispatch_user.email)
    else:
        u = None

    contact = Worker(**worker_in.dict(
        exclude={"flex_form_data", "team", "location", "dispatch_user"}),
                     team=team,
                     location=location_obj,
                     dispatch_user=u,
                     flex_form_data=worker_in.flex_form_data)
    db_session.add(contact)
    db_session.commit()
    return contact
Example #3
0
def update(
    *,
    db_session,
    worker: Worker,
    worker_in: WorkerUpdate,
) -> Worker:
    worker_data = jsonable_encoder(worker_in)

    update_data = worker_in.dict(
        skip_defaults=True,
        exclude={"flex_form_data", "team", "location"},
    )

    team = team_service.get_by_code(db_session=db_session,
                                    code=worker_in.team.code)

    location_obj = location_service.get_or_create_by_code(
        db_session=db_session, location_in=worker_in.location)

    for field in worker_data:
        if field in update_data:
            setattr(worker, field, update_data[field])

    worker.flex_form_data = worker_in.flex_form_data

    worker.team = team
    worker.location = location_obj
    db_session.add(worker)
    db_session.commit()
    return worker
Example #4
0
def create(*, db_session, worker_in: WorkerCreate) -> Worker:
    """Creates an worker."""
    team = team_service.get_by_code(db_session=db_session,
                                    code=worker_in.team.code)
    if worker_in.location is not None:
        location_obj = location_service.get_or_create_by_code(
            db_session=db_session, location_in=worker_in.location)
    else:
        location_obj = None

    contact = Worker(**worker_in.dict(
        exclude={"flex_form_data", "team", "location"}),
                     team=team,
                     location=location_obj,
                     flex_form_data=worker_in.flex_form_data)
    db_session.add(contact)
    db_session.commit()
    return contact
Example #5
0
def run_batch_optimizer_view(
    request_in: ResetPlanningWindowInput,
    team_code: str = Query("1", alias="team_code"),
    current_user: DispatchUser = Depends(get_current_user),
    db_session: Session = Depends(get_db),
):
    org_code = current_user.org_code
    team = team_service.get_by_code(db_session=db_session, code=request_in.team_code)
    if team is None:
        raise HTTPException(
            status_code=400, detail=f"The team code you requested is not in your organization.",
        )
    if team.org_id != current_user.org_id:
        raise HTTPException(
            status_code=400, detail=f"The team code you requested is not in your organization...",
        )
    result_info = run_batch_optimizer(
        org_code=org_code,
        team_id=team.id,)

    return JSONResponse(result_info)
Example #6
0
def update(
    *,
    db_session,
    worker: Worker,
    worker_in: WorkerUpdate,
) -> Worker:
    flag, msg = _check_business_hour(worker_in.business_hour)
    if flag:
        log.error(f"{worker_in.code} , {msg}")
        raise HTTPException(status_code=400,
                            detail=f"{worker_in.code} , {msg}")

    update_data = worker_in.dict(
        exclude={"flex_form_data", "team", "location", "dispatch_user"}, )
    if worker.team.code != worker_in.team.code:
        team = team_service.get_by_code(db_session=db_session,
                                        code=worker_in.team.code)
        worker.team = team

    if worker_in.location and (not worker.location
                               or worker_in.location.location_code !=
                               worker.location.location_code):
        location_obj = location_service.get_or_create_by_code(
            db_session=db_session, location_in=worker_in.location)
        worker.location = location_obj

    if worker_in.dispatch_user and (
        (worker.dispatch_user is None) or
        (worker.dispatch_user.email != worker_in.dispatch_user.email)):
        u = auth_service.get_by_email(db_session=db_session,
                                      email=worker_in.dispatch_user.email)
        worker.dispatch_user = u

    for field, field_value in update_data.items():
        setattr(worker, field, field_value)

    worker.flex_form_data = worker_in.flex_form_data
    db_session.add(worker)
    db_session.commit()
    return worker
Example #7
0
def create(*, db_session, location_in: LocationCreate) -> Location:
    location = location_in
    if type(location_in) != Location:
        if location_in.team is not None:
            team = get_by_code(db_session=db_session,
                               code=location_in.team.code)
        else:
            team = None

        if location_in.dispatch_user is not None:
            user = auth_service.get_by_email(
                db_session=db_session, email=location_in.dispatch_user.email)
        else:
            user = None

        location = Location(**location_in.dict(
            exclude={"team", "dispatch_user"}),
                            team=team,
                            dispatch_user=user)
    db_session.add(location)
    db_session.commit()
    return location
Example #8
0
def update(*, db_session, job: Job, job_in: JobUpdate, org_code: str) -> Job:
    tags = []
    for t in job_in.tags:
        tags.append(tag_service.get_or_create(db_session=db_session, tag_in=TagUpdate(**t)))

    scheduled_secondary_workers = []
    if job_in.scheduled_secondary_workers:
        for w in job_in.scheduled_secondary_workers:
            scheduled_secondary_workers.append(
                worker_service.get_by_code(db_session=db_session, code=w.code))
    if job_in.team and job_in.team.code != job.team.code:
        team_obj = team_service.get_by_code(db_session=db_session, code=job_in.team.code)
        job.team = team_obj
    if job_in.location and job_in.location.location_code and job_in.location.location_code != job.location.location_code:
        location_obj = location_service.get_or_create_by_code(
            db_session=db_session, location_in=job_in.location)
        job.location = location_obj
    update_data = job_in.dict(
        skip_defaults=True,
        exclude={
            "tags",
            "scheduled_secondary_workers",
            "requested_primary_worker",
            "scheduled_primary_worker",
            "team",
            "location",
        },
    )

    for field in update_data.keys():
        setattr(job, field, update_data[field])

    job.scheduled_secondary_workers = scheduled_secondary_workers
    job.tags = tags
    if job_in.scheduled_primary_worker is not None:
        job.scheduled_primary_worker = worker_service.get_by_code(
            db_session=db_session, code=job_in.scheduled_primary_worker.code)
    if job_in.requested_primary_worker is not None:
        job.requested_primary_worker = worker_service.get_by_code(
            db_session=db_session, code=job_in.requested_primary_worker.code)

    db_session.add(job)
    db_session.commit()
    event_service.log(
        db_session=db_session,
        source="Dispatch Core App",
        description=f"Job ({job_in.code}) is updated {job_in.flex_form_data}",
        job_id=job.id,
    )
    print(f"\033[37;46m\t1: job update succeed {job.code}\033[0m")
    post_job_to_kafka(job=job, message_type=KafkaMessageType.UPDATE_JOB,
                      db_session=db_session, org_code=org_code)

    print(f"\033[37;46m\t2: job psot kafka in succeed {job.code}\033[0m")
    # zulip send message
    if job.planning_status != JobPlanningStatus.UNPLANNED:
        zulip_dict = get_zulip_client_by_org_id(job.org_id)
        if zulip_dict:
            zulip_core = zulip_dict['client']
            zulip_core.update_job_send_message(
                job, [job.scheduled_primary_worker] + job.scheduled_secondary_workers)

    return job
Example #9
0
def create(
    *,
    db_session,
    # job_priority: str = None,
    # job_type: str,
    code: str,
    job_type: str = "visit",
    org_id: str = None,
    org_code: str = None,
    name: str = None,
    planning_status: str,
    tags: List[dict] = [],
    description: str = None,
    team: TeamCreate,
    location: LocationCreate,
    flex_form_data: dict = None,
    requested_primary_worker: WorkerCreate = None,
    requested_start_datetime: datetime = None,
    requested_duration_minutes: float = None,
    scheduled_primary_worker: WorkerCreate = None,
    scheduled_secondary_workers: List[WorkerCreate] = [],
    scheduled_start_datetime: datetime = None,
    scheduled_duration_minutes: float = None,
    auto_planning: bool = True,
    requested_skills: List[str] = [],
    requested_items: List[str] = [],
    life_cycle_status: JobLifeCycleUpdate = None
) -> Job:
    """Creates a new job."""

    tag_objs = []
    for t in tags:
        tag_objs.append(tag_service.get_or_create(db_session=db_session, tag_in=TagCreate(**t)))

    team_obj = team_service.get_by_code(db_session=db_session, code=team["code"])

    location_obj = location_service.get_by_location_code(
        db_session=db_session,
        location_code=location["location_code"])
    if location_obj is None:
        loc_to_create = LocationCreate(**location)
        loc_to_create.org_id = org_id
        if loc_to_create.geo_address_text and not loc_to_create.geo_latitude:
            try:
                nid = SHORTUUID.random(length=9)
                location_config = {
                    "url": config.LOCATION_SERVICE_URL,
                    "token": config.LOCATION_SERVICE_TOKEN,
                    "request_method": config.LOCATION_SERVICE_REQUEST_METHOD,
                }
                payload = {"address_id": nid,
                           "input_address": loc_to_create.geo_address_text
                           }
                # get location service
                location_plug = service_plugin_service.get_by_service_id_and_type(
                    db_session=db_session,
                    service_id=team_obj.service_id,
                    service_plugin_type=KandboxPlannerPluginType.kandbox_location_service,
                ).all()
                if location_plug:
                    location_plugin = plugins.get(location_plug[0].plugin.slug)
                    location_adapter_service = location_plugin(config=location_config)
                    status, _location_ret, msg = location_adapter_service.get_pldt_location(payload)

                    if status:
                        if isinstance(_location_ret['latitude'], float):
                            if _check_location(_location_ret, team_obj.flex_form_data):
                                loc_to_create.geo_latitude = _location_ret['latitude']
                                loc_to_create.geo_longitude = _location_ret['longitude']
                                loc_to_create.id = _location_ret['location_id']
                                loc_to_create.location_code = _location_ret['location_code']
                            else:
                                logService.create(db_session=db_session, log_in=LogCreate(
                                    title='Location Response Data OutSide', category='Location', content=f"location outside,job code:{code},input_address:{payload['input_address']}, msg:{str(_location_ret)}", org_id=int(org_id), team_id=team_obj.id))
                                log.error(
                                    f"Location Response Data OutSide ,{msg} :{payload['input_address']}")
                        else:
                            logService.create(db_session=db_session, log_in=LogCreate(
                                title='Location Response Data NUll', category='Location', content=f"job code:{code},input_address:{payload['input_address']},msg:{str(_location_ret)}", org_id=int(org_id), team_id=team_obj.id))
                            log.error(
                                f"Location Response Data NUll ,{msg} :{payload['input_address']}")
                    else:
                        logService.create(db_session=db_session, log_in=LogCreate(
                            title=msg['type'], category='Location', content=f"job code:{code},input_address:{payload['input_address']},msg:{str(msg['msg'])}", org_id=int(org_id), team_id=team_obj.id))
                        log.error(
                            f"Location Response failed ,{msg} :{payload['input_address']}")
                else:
                    log.error(
                        f"not find location plug,service:{team_obj.service_id},{KandboxPlannerPluginType.kandbox_location_service}")
            except Exception as e:
                print(traceback.format_exc())
                log.error(f"address request error:{loc_to_create.geo_address_text},{ e} ")

        location_obj = location_service.get_or_create_by_code(
            db_session=db_session, location_in=loc_to_create)
        # if location_obj.geo_longitude < 1:
        #     location_obj.geo_longitude = loc_to_create.geo_longitude
        #     location_obj.geo_latitude = loc_to_create.geo_latitude
        db_session.add(location_obj)
    # location_obj = location_service.update(
    #     db_session=db_session, location=location_obj, location_in=LocationUpdate(**location)
    # )

    if requested_primary_worker:
        requested_primary_worker = worker_service.get_by_code(
            db_session=db_session, code=requested_primary_worker["code"])
    if scheduled_primary_worker:
        scheduled_primary_worker = worker_service.get_by_code(
            db_session=db_session, code=scheduled_primary_worker["code"])
    scheduled_secondary_workers_list = []
    if scheduled_secondary_workers is not None:
        for w in scheduled_secondary_workers:
            scheduled_secondary_workers_list.append(
                worker_service.get_by_code(db_session=db_session, code=w['code']))
    # We create the job
    if requested_skills:
        flex_form_data['requested_skills'] = requested_skills
    if requested_items:
        flex_form_data['requested_items'] = requested_items
    job = Job(
        code=code,
        name=name,
        org_id=org_id,
        job_type=job_type,
        description=description,
        planning_status=planning_status,
        tags=tag_objs,
        flex_form_data=flex_form_data,
        location=location_obj,
        team=team_obj,
        requested_start_datetime=requested_start_datetime,
        requested_duration_minutes=requested_duration_minutes,
        requested_primary_worker=requested_primary_worker,
        scheduled_start_datetime=scheduled_start_datetime,
        scheduled_duration_minutes=scheduled_duration_minutes,
        scheduled_primary_worker=scheduled_primary_worker,
        scheduled_secondary_workers=scheduled_secondary_workers_list,
        auto_planning=auto_planning,
        requested_skills=requested_skills,
        requested_items=requested_items,
    )
    db_session.add(job)

    if job.job_type == JobType.REPLENISH:
        depot_code = flex_form_data["depot_code"]
        depot = depot_service.get_by_code(db_session=db_session, code=depot_code)

        for item_str in flex_form_data["requested_items"]:
            item_list = parse_item_str(item_str)
            item = item_service.get_by_code(db_session=db_session, code=item_list[0])
            inv = inventory_service.get_by_item_depot(
                db_session=db_session,
                item_id=item.id,
                depot_id=depot.id,
                org_id=team_obj.org_id
            ).one_or_none()
            inv.curr_qty -= item_list[1]
            inv.allocated_qty += item_list[1]
            if inv.curr_qty < 0:
                log.error(
                    f" Not enough inventory for item: {item_list[0]}, depot: {depot_code}, org.id: {team_obj.org_id}")
                continue
            db_session.add(inv)
            inventory_event_service.log(
                db_session=db_session,
                source="Env_Replenish",
                description=f"Allocated {item_list[1]} {item_list[0]} from depot: {depot_code}",
                item_code=item_list[0],
                depot_code=depot_code,
                item_id=item.id,
                depot_id=depot.id
            )

    db_session.commit()

    print(f"\033[37;46m\t1:add job succeed,{code}\033[0m")
    log.info(f"1:add job succeed,{code}")
    event_service.log(
        db_session=db_session,
        source="Dispatch Core App",
        description=f"Job ({code}) is created, planning_status={planning_status}, requested_start_datetime={requested_start_datetime}",
        job_id=job.id,
    )

    post_job_to_kafka(job=job, message_type=KafkaMessageType.CREATE_JOB,
                      db_session=db_session, org_code=org_code)

    print(f"\033[37;46m\t2:job post kafka in succeed,{code}\033[0m")
    log.info(f"2:job post kafka in succeed,{code}")

    # zulip send message
    if job.planning_status != JobPlanningStatus.UNPLANNED:
        zulip_dict = get_zulip_client_by_org_id(job.org_id)
        if zulip_dict:
            zulip_core = zulip_dict['client']
            zulip_core.update_job_send_message(
                job, [job.scheduled_primary_worker] + job.scheduled_secondary_workers)

    return job
Example #10
0
def create(
    *,
    db_session,
    # job_priority: str = None,
    # job_type: str,
    code: str,
    name: str = None,
    planning_status: str,
    tags: List[dict],
    description: str = None,
    team: TeamCreate,
    location: LocationCreate,
    flex_form_data: dict = None,
    requested_primary_worker: WorkerCreate = None,
    requested_start_datetime: datetime = None,
    requested_duration_minutes: float = None,
    scheduled_primary_worker: WorkerCreate = None,
    scheduled_secondary_workers: List[WorkerCreate],
    scheduled_start_datetime: datetime = None,
    scheduled_duration_minutes: float = None,
    auto_planning: bool = True,
) -> Job:
    """Creates a new job."""

    tag_objs = []
    for t in tags:
        tag_objs.append(
            tag_service.get_or_create(db_session=db_session,
                                      tag_in=TagCreate(**t)))

    team_obj = team_service.get_by_code(db_session=db_session,
                                        code=team["code"])
    loc_to_create = LocationCreate(**location)
    location_obj = location_service.get_or_create_by_code(
        db_session=db_session, location_in=loc_to_create)
    # if location_obj.geo_longitude < 1:
    #     location_obj.geo_longitude = loc_to_create.geo_longitude
    #     location_obj.geo_latitude = loc_to_create.geo_latitude
    db_session.add(location_obj)
    # location_obj = location_service.update(
    #     db_session=db_session, location=location_obj, location_in=LocationUpdate(**location)
    # )

    if requested_primary_worker:
        requested_primary_worker = worker_service.get_by_code(
            db_session=db_session, code=requested_primary_worker["code"])
    if scheduled_primary_worker:
        scheduled_primary_worker = worker_service.get_by_code(
            db_session=db_session, code=scheduled_primary_worker["code"])
    if scheduled_secondary_workers is None:
        scheduled_secondary_workers = []
    # We create the job
    job = Job(
        code=code,
        name=name,
        description=description,
        planning_status=planning_status,
        tags=tag_objs,
        flex_form_data=flex_form_data,
        location=location_obj,
        team=team_obj,
        requested_start_datetime=requested_start_datetime,
        requested_duration_minutes=requested_duration_minutes,
        requested_primary_worker=requested_primary_worker,
        scheduled_start_datetime=scheduled_start_datetime,
        scheduled_duration_minutes=scheduled_duration_minutes,
        scheduled_primary_worker=scheduled_primary_worker,
        scheduled_secondary_workers=scheduled_secondary_workers,
        auto_planning=auto_planning,
    )
    db_session.add(job)
    db_session.commit()

    event_service.log(
        db_session=db_session,
        source="Dispatch Core App",
        description=
        f"Job ({code}) is created, planning_status={planning_status}, scheduled_start_datetime={scheduled_start_datetime}",
        job_id=job.id,
    )

    post_job_to_kafka(job=job,
                      message_type=KafkaMessageType.CREATE_JOB,
                      db_session=db_session)

    return job
Example #11
0
def create_worker(*,
                  db_session: Session = Depends(get_db),
                  worker_in: WorkerCreate,
                  current_user: DispatchUser = Depends(get_current_user)):
    """
    Create a new worker contact.
    """
    # limit max
    org_data = orgService.get(db_session=db_session,
                              org_code=current_user.org_code)
    if not org_data:
        raise HTTPException(status_code=400, detail="org not exists")
    max_nbr_worker = org_data.max_nbr_workers

    if worker_in.skills:
        worker_in.flex_form_data['skills'] = worker_in.skills
    if worker_in.loaded_items:
        worker_in.flex_form_data['loaded_items'] = worker_in.loaded_items
    job_all_count = get_by_org_id_count(db_session=db_session,
                                        org_id=current_user.org_id)
    if job_all_count >= max_nbr_worker:
        raise HTTPException(status_code=400,
                            detail="Worker Reached the upper limit")
    worker_in.org_id = current_user.org_id
    worker = get_by_code_org_id(db_session=db_session,
                                code=worker_in.code,
                                org_id=current_user.org_id)

    team = team_service.get_by_code(db_session=db_session,
                                    code=worker_in.team.code)

    # use zulip
    zulip_user_id = worker_in.flex_form_data.get("zulip_user_id", None)
    result = None
    zulip_dict = get_zulip_client_by_org_id(current_user.org_id)
    if zulip_dict and zulip_user_id and worker_in.team.flex_form_data.get(
            'use_zulip', False):
        flag, worker_code = check_zulip_user_id(db_session=db_session,
                                                zulip_user_id=zulip_user_id,
                                                team_id=team.id)
        if not flag:
            raise HTTPException(
                status_code=400,
                detail=
                f"The worker zulip_user_id already exists in {worker_code}")
        zulip_core = zulip_dict['client']
        result = zulip_core.update_add_subscribe_user_group(
            worker_in,
            org_code=current_user.org_code,
            team_code=team.code,
            flag=True)
    if result and result['result'] != 'success':
        raise HTTPException(status_code=400, detail=f"{result['msg']}")
    # add worker
    if worker:
        raise HTTPException(status_code=400,
                            detail="The worker with this code already exists.")
    worker = create(db_session=db_session, worker_in=worker_in)

    # change to env
    if current_user.org_code and team.id:
        message_dict = transfrom_worker_data(worker, team)
        post_worker_to_env(message_dict, current_user.org_code, team.id, False)

    return worker
Example #12
0
def update_worker_by_code(
    *,
    db_session: Session = Depends(get_db),
    worker_code: str,
    worker_in: WorkerUpdate,
    current_user: DispatchUser = Depends(get_current_user)):
    """
    Update a worker contact.
    """
    worker_in.org_id = current_user.org_id
    worker = get_by_code(db_session=db_session, code=worker_code)
    code_change = False
    if worker_in.code != worker.code:
        code_change = True
    change_active = False
    if worker_in.is_active != worker.is_active:
        change_active = True
        count = get_count_by_active(db_session=db_session, is_active=True)
        if count < 2 and not worker_in.is_active:
            raise HTTPException(status_code=404,
                                detail="There must be a normal worker.")

    if not worker:
        raise HTTPException(status_code=404,
                            detail="The worker with this id does not exist.")
    if worker_in.requested_skills:
        worker_in.flex_form_data[
            'requested_skills'] = worker_in.requested_skills

    team = team_service.get_by_code(db_session=db_session,
                                    code=worker_in.team.code)
    # use zulip
    zulip_user_id = worker_in.flex_form_data.get("zulip_user_id", None)
    old_user_id = worker.flex_form_data.get("zulip_user_id", None)
    result = None

    zulip_dict = get_zulip_client_by_org_id(current_user.org_id)
    if zulip_dict and zulip_user_id and zulip_user_id != old_user_id and worker_in.team.flex_form_data.get(
            'use_zulip', False):
        flag, worker_code = check_zulip_user_id(db_session=db_session,
                                                zulip_user_id=zulip_user_id,
                                                team_id=team.id)
        if not flag:
            raise HTTPException(
                status_code=400,
                detail=
                f"The worker zulip_user_id already exists in {worker_code}")
        zulip_core = zulip_dict['client']
        result = zulip_core.update_add_subscribe_user_group(
            worker_in,
            org_code=current_user.org_code,
            team_code=team.code,
            flag=True)

    if result and result['result'] != 'success':
        raise HTTPException(status_code=400, detail=f"{result['msg']}")
    worker = update(
        db_session=db_session,
        worker=worker,
        worker_in=worker_in,
    )
    if current_user.org_code and team.id:
        message_dict = transfrom_worker_data(worker, team)
        post_worker_to_env(message_dict, current_user.org_code, team.id,
                           any([code_change, change_active]))
    return worker