def notify_before_shooting(): """Search for assignments scheduled and notify professional before shooting.""" query = Assignment.query().filter( and_( Assignment.state == 'scheduled', not_( Assignment.comments.any( Comment.content == BEFORE_SHOOTING_MSG)))) assignments = [] for item in query: now = timezone_now('UTC') delta = item.scheduled_datetime - now config_delta = timedelta(seconds=int(BEFORE_SHOOTING_SECONDS)) should_notify = delta.days >= 0 and delta <= config_delta if should_notify: assignments.append(item) msg = 'Total assignments professionals will be notified before shooting: {size}' logger.info(msg.format(size=len(assignments))) total_notified = 0 for assignment in assignments: status = _notify_before_shooting(assignment) total_notified += 1 if status else 0 msg = 'Total of assignments professionals were notified before shooting: {total}' logger.info(msg.format(total=total_notified))
def notify_late_submissions(): """Search for assignments with late submissions to be notified.""" query = Assignment.query().filter( and_( Assignment.state == 'awaiting_assets', not_( Assignment.comments.any( Comment.content == LATE_SUBMISSION_MSG)))) assignments = [] for item in query: now = timezone_now('UTC') delta = now - item.scheduled_datetime config_delta = timedelta(seconds=int(LATE_SUBMISSION_SECONDS)) should_notify = delta > config_delta and delta.days <= int( LATE_SUBMISSION_MAX_DAYS) if should_notify: assignments.append(item) msg = 'Total assignments professionals will be notified for late submissions: {size}' logger.info(msg.format(size=len(assignments))) total_notified = 0 for assignment in assignments: status = _notify_late_submissions(assignment) total_notified += 1 if status else 0 msg = 'Total of assignments professionals were notified for late submission: {total}' logger.info(msg.format(total=total_notified))
def move_orders_accepted(): """Move Orders from delivered to accepted.""" orders = Order.query().filter(Order.state == 'delivered').all() logger.info( 'Total orders in delivered state: {total}'.format(total=len(orders))) total_moved = 0 for order in orders: status = _move_order_accepted(order) total_moved += 1 if status else 0 logger.info('Total orders moved to accepted state: {total}'.format( total=total_moved))
def _move_order_accepted(order: Order) -> bool: """Move Order from delivered to accepted after a certain amount of working days. Task name: leica.task.order_accepted Task events: * leica.task.order_accepted.success * leica.task.order_accepted.failure :param order: Order to be processed. :return: Status of the transition """ task_name = 'leica.task.order_accepted' status = False state = order.state last_deliver_date = order.last_deliver_date if state == 'delivered' and last_deliver_date: now = datetime_utcnow() project = order.project approval_window = project.approval_window allowed_accept_date = workday(last_deliver_date, approval_window) wf = order.workflow wf.context = SystemUser if now >= allowed_accept_date: if not wf.can_accept: assignment_states = [a.state for a in order.assignments] msg = 'Approval window for Order {id} expired but it can not be completed. ' \ 'Assignment states: {states}' msg = msg.format(id=order.id, states=str(assignment_states)) else: wf.accept( message= 'Order automatic accepted after the end of the approval window.' ) msg = 'Order {id} moved to completed. Delivery date: {deliver_date}' msg = msg.format(id=order.id, deliver_date=last_deliver_date) status = True # Trigger task event cache_region.invalidate(order) for assignment in order.assignments: cache_region.invalidate(assignment) event = LeicaTaskEvent(task_name=task_name, success=status, obj=order) event() logger.info(msg) return status
def main(): """Initialize and execute the Leica Task Manager.""" sched = BlockingScheduler() db_configure(Session) @sched.scheduled_job('cron', hour=CRON_HOUR_JOB_TASKS, minute=CRON_MINUTE_JOB_TASKS) def run_tasks(): """Run all tasks.""" with transaction.manager: logger.info('Start: moving assignments to Pool.') move_assignments_to_pool() logger.info('End: moving assignments to Pool.') with transaction.manager: logger.info('Start: moving assignments to Awaiting Assets.') move_assignments_awaiting_assets() logger.info('End: moving assignments to Awaiting Assets.') with transaction.manager: if ENABLE_BEFORE_SHOOTING_NOTIFY: seconds = BEFORE_SHOOTING_SECONDS logger.info( f'Start: notifying assignments {seconds} seconds before shooting.' ) notify_before_shooting() logger.info( f'End: notifying assignments {seconds} seconds before shooting.' ) with transaction.manager: if ENABLE_LATE_SUBMISSION_NOTIFY: seconds = LATE_SUBMISSION_SECONDS logger.info(f'Start: notifying assignments not submitted ' f'{seconds} seconds after shooting.') notify_late_submissions() logger.info(f'End: notifying assignments not submitted ' f'{seconds} seconds after shooting.') with transaction.manager: logger.info('Start: moving orders to accepted.') move_orders_accepted() logger.info('End: moving orders to accepted.') logger.info('Starting Leica Task Manager.') sched.start()
def move_assignments_awaiting_assets(): """Move Assignments from scheduled to awaiting_assets.""" query = Assignment.query().filter(Assignment.state == 'scheduled').all() assignments = [] for item in query: now = timezone_now('UTC') if item.scheduled_datetime and item.scheduled_datetime < now: assignments.append(item) logger.info( 'Total assignments to be moved: {size}'.format(size=len(assignments))) total_moved = 0 for assignment in assignments: status = _move_assignment_awaiting_assets(assignment) total_moved += 1 if status else 0 cache_region.invalidate(assignment) cache_region.invalidate(assignment.order) logger.info('Total assignments moved to awaiting assets: {total}'.format( total=total_moved))
def _move_assignment_awaiting_assets(assignment: Assignment) -> bool: """Move Assignments from scheduled to awaiting_assets. Task name: leica.task.assignment_awaiting_assets Task events: * leica.task.assignment_awaiting_assets.success * leica.task.assignment_awaiting_assets.failure :param assignment: Assignment to be processed :return: Status of the transition """ task_name = 'leica.task.assignment_awaiting_assets' now = timezone_now('UTC') status = False if assignment.state == 'scheduled' and assignment.scheduled_datetime < now: wf = assignment.workflow wf.context = SystemUser try: wf.ready_for_upload() except WorkflowTransitionException as e: logger.exception( 'Assignment {id} not moved to awaiting_assets.'.format( id=assignment.id)) else: status = True logger.info( 'Assignment {id} moved to awaiting_assets. Shoot time: {shoot_time}' .format(id=assignment.id, shoot_time=assignment.scheduled_datetime)) cache_region.invalidate(assignment) event = LeicaTaskEvent(task_name=task_name, success=status, obj=assignment) event() return status
def run_tasks(): """Run all tasks.""" with transaction.manager: logger.info('Start: moving assignments to Pool.') move_assignments_to_pool() logger.info('End: moving assignments to Pool.') with transaction.manager: logger.info('Start: moving assignments to Awaiting Assets.') move_assignments_awaiting_assets() logger.info('End: moving assignments to Awaiting Assets.') with transaction.manager: if ENABLE_BEFORE_SHOOTING_NOTIFY: seconds = BEFORE_SHOOTING_SECONDS logger.info( f'Start: notifying assignments {seconds} seconds before shooting.' ) notify_before_shooting() logger.info( f'End: notifying assignments {seconds} seconds before shooting.' ) with transaction.manager: if ENABLE_LATE_SUBMISSION_NOTIFY: seconds = LATE_SUBMISSION_SECONDS logger.info(f'Start: notifying assignments not submitted ' f'{seconds} seconds after shooting.') notify_late_submissions() logger.info(f'End: notifying assignments not submitted ' f'{seconds} seconds after shooting.') with transaction.manager: logger.info('Start: moving orders to accepted.') move_orders_accepted() logger.info('End: moving orders to accepted.')