Exemple #1
0
    def _test_commit(my):

        from pyasm.biz import Project
        database_type = Project.get_by_code("unittest").get_database_type()
        if database_type == "MySQL":
            print
            print "WARNING: !!!!!!!"
            print "_test_commit is disabled"
            print "WARNING: !!!!!!!"
            print
            return

        person_s = Search('unittest/person')
        person_s.add_filter('name_first', 'pete')

        person = person_s.get_sobject()
        from pyasm.biz import Note
        Note.create(person,
                    "3 slashes \\\\\\",
                    context="unittest_commit",
                    process="unittest_commit")
        search = Search('sthpw/note')
        search.add_filter('process', 'unittest_commit')
        search.set_limit(1)
        note = search.get_sobject()
        my.assertEquals(note.get_value('note'), "3 slashes \\\\\\")
Exemple #2
0
    def add_publish_note(my):
        # DISABLING because this is too overbearing.  There are way
        # too many notes created
        return

        description = my.snapshot.get_value("description")
        process = my.snapshot.get_value("process")
        context = my.snapshot.get_value("context")
        version = my.snapshot.get_value("version")

        from pyasm.biz import Note
        if description:
            description = "Check-in [v%0.3d]: %s" % (version, description)

            Note.create(my.sobject, description, context=context, process=process)
Exemple #3
0
    def add_publish_note(self):
        # DISABLING because this is too overbearing.  There are way
        # too many notes created
        return

        description = self.snapshot.get_value("description")
        process = self.snapshot.get_value("process")
        context = self.snapshot.get_value("context")
        version = self.snapshot.get_value("version")

        from pyasm.biz import Note
        if description:
            description = "Check-in [v%0.3d]: %s" % (version, description)

            Note.create(self.sobject,
                        description,
                        context=context,
                        process=process)
Exemple #4
0
    def _test_commit(self):
       
        from pyasm.biz import Project
        database_type = Project.get_by_code("unittest").get_database_type()
        if database_type == "MySQL":
            print
            print "WARNING: !!!!!!!"
            print "_test_commit is disabled"
            print "WARNING: !!!!!!!"
            print
            return

        person_s = Search('unittest/person')
        person_s.add_filter('name_first','pete')

        person = person_s.get_sobject()
        from pyasm.biz import Note
        Note.create(person, "3 slashes \\\\\\", context="unittest_commit", process="unittest_commit")
        search = Search('sthpw/note')
        search.add_filter('process','unittest_commit')
        search.set_limit(1)
        note = search.get_sobject()
        self.assertEquals(note.get_value('note'), "3 slashes \\\\\\")
def main(server=None, input=None):
    """
    The main function of the custom script. The entire script was copied
    and pasted into the body of the try statement in order to add some
    error handling. It's all legacy code, so edit with caution.

    :param server: the TacticServerStub object
    :param input: a dict with data like like search_key, search_type, sobject, and update_data
    :return: None
    """
    if not input:
        input = {}

    try:
        # CUSTOM_SCRIPT00019
        #
        # Created by Matthew Misenhimer
        #
        def make_timestamp():
            #Makes a Timestamp for postgres
            import datetime
            now = datetime.datetime.now()
            return now.strftime("%Y-%m-%d %H:%M:%S")
        
        def are_no_hackpipes_preceding(sob, ignore_code):
            #Checks to see if there are any manually inserted/non-pipeline Projects or Work Orders that lead in to the sob that are not completed yet
            #If there are incompleted hackpipe work orders or projs that precede the sob, then this will return false.
            #Ignore code is usually the code of the task just completed. We don't care about looking at it's status in determining this. 
            boolio = True
            matcher = '' #This is the type of sob (PROJ or WORK_ORDER) that we care about looking at
            if 'PROJ' in sob.get('code'):
                matcher = 'PROJ'
            elif 'WORK_ORDER' in sob.get('code'):
                matcher = 'WORK_ORDER'
            pre_hacks_expr = "@SOBJECT(twog/hackpipe_out['out_to','%s'])" % sob.get('code') #See what hackpipes lead in to this sob
            pre_hacks = server.eval(pre_hacks_expr)
            for ph in pre_hacks:
                if matcher in ph.get('lookup_code') and ignore_code not in ph.get('lookup_code'): #If it's the type we care about and it isn't the main sob
                    ph_task = server.eval("@SOBJECT(sthpw/task['lookup_code','%s'])" % ph.get('lookup_code'))
                    if ph_task:
                        ph_task = ph_task[0]
                        if ph_task.get('status') != 'Completed': #If it hasn't been completed, then there is an incomplete hackpipe preceding sob, so return false
                            boolio = False
            return boolio
        
        def block_manual_status_adjust_for_inactive_hackup(sob, task):
            #This was created because people used to be able to change the status of inactive work orders
            #I think this is prevented in other ways now, but I am keeping it in just in case it is still needed.
            from pyasm.common import TacticException
            good = True
            if sob.get('creation_type') == 'hackup':
                if task.get('active') not in [True,'true','t',1,'1']:
                    raise TacticException('This needs to be active in order to change the status')
            return good
        
        from pyasm.common import TacticException, Environment
        # input and server are assumed variables
        # define some contants here
        #print "\n\nIN KICKOFF"
        COMPLETE = 'Completed'
        READY = 'Ready'
        PENDING = 'Pending'
        sobj = input.get('sobject')
        this_process = sobj.get('process')
        this_lookup = sobj.get('lookup_code')
        sk = input.get('search_key')
        task_code = sobj.get('code')
        update_data = input.get('update_data') #These are the new values
        prev_data = {}
        old_status = ''
        if 'prev_data' in input.keys():
            prev_data = input.get('prev_data') #These are the old values
            if 'status' in prev_data.keys():
                old_status = prev_data.get('status')
        new_status = update_data.get('status')
        login = Environment.get_login()
        user_name = login.get_login()
        assigned_login_group = sobj.get('assigned_login_group')
        parent_obj = None
        title = None
        order = None
        if 'PROJ' in this_lookup:
            parent_obj = server.eval("@SOBJECT(twog/proj['code','%s'])" % this_lookup)[0] #Parent Obj is the Proj attached to the task
            proj = parent_obj
            title = server.eval("@SOBJECT(twog/title['code','%s'])" % parent_obj.get('title_code'))[0]
            order = server.eval("@SOBJECT(twog/order['code','%s'])" % title.get('order_code'))[0] 
        elif 'WORK_ORDER' in this_lookup:
            parent_obj = server.eval("@SOBJECT(twog/work_order['code','%s'])" % this_lookup)[0] #Parent Obj is the Work Order attached to the task
            work_order = parent_obj
            proj = server.eval("@SOBJECT(twog/proj['code','%s'])" % work_order.get('proj_code'))[0]
            title = server.eval("@SOBJECT(twog/proj['code','%s'].twog/title)" % parent_obj.get('proj_code'))[0] 
            order = server.eval("@SOBJECT(twog/order['code','%s'])" % title.get('order_code'))[0] 
        
        if 'PROJ' in this_lookup and title.get('priority_triggers') != 'No':
            #If the new status for this Proj is ready, then grab the priority attached to he proj and give it to the Title
            #This is to control priority order per department
            if new_status == 'Ready':
                server.update(title.get('__search_key__'), {'priority': parent_obj.get('priority')}, triggers=False)
        elif 'WORK_ORDER' in this_lookup:
            t_wo_completed = title.get('wo_completed') #This is for the completion ratio on title
            o_wo_completed = order.get('wo_completed') #This is for the completion ratio on order
            if new_status == COMPLETE:
                title_str = title.get('title') #This is for a potential alert/exception
                if title.get('episode') not in [None,'']:
                    title_str = '%s: %s' % (title_str, title.get('episode'))
                #Block QC and Edel from completing their work orders if the TRT or TRT w/Textless are not filled in
                if 'qc' in assigned_login_group or 'edeliveries' in assigned_login_group:
                    total_program_runtime = title.get('total_program_runtime')
                    total_runtime_w_textless = title.get('total_runtime_w_textless')
                    say_str = ''
                    say_str2 = ''
                    if total_program_runtime in [None,''] or total_runtime_w_textless in [None,'']:
                        if total_program_runtime in [None,'']:
                            say_str = 'Total Program Runtime has' 
                        if total_runtime_w_textless in [None,'']:
                            if say_str == '': 
                                say_str = 'Total Runtime With Textless has'
                            else:
                                say_str = '%s and Total Runtime With Textless have' % (say_str[:-4])  
                        say_str2 = "%s (%s)'s %s not been filled. You must enter this data before trying to complete this work order." % (title_str, title.get('code'), say_str)
                    if 'qc' in assigned_login_group:
                        if total_program_runtime in [None,''] or total_runtime_w_textless in [None,'']:
                            raise TacticException(say_str2)
                        else:
                            #They were filled in, so finish completing the task and send a note
                            from pyasm.biz import Note
                            from pyasm.search import Search
                            title_obj2 = Search.get_by_search_key(title.get('__search_key__')) #This is the type of object required for Note creation
                            note_text = '%s (%s) has been Passed and Completed by %s in QC' % (sobj.get('process'), this_lookup, user_name)
                            note = Note.create(title_obj2, note_text, context='QC Completed', process='QC Completed')
                    elif 'edeliveries' in assigned_login_group and (total_program_runtime in [None,''] or total_runtime_w_textless in [None,'']):
                        raise TacticException(say_str2)
                #This section is turned off due to logistical problems with it. 
                #It intended to block machine room, edit, and compression from completing a work order unless the pulled_blacks had been filled out.
                #if 'machine_room' in assigned_login_group or 'edit' in assigned_login_group or 'compression' in assigned_login_group:
                #    pulled_blacks = title.get('pulled_blacks')
                #    if pulled_blacks in [None,'','0']:
                #        raise TacticException("%s (%s)'s pulled_blacks has not been filled, or is still '0'." % (title_str, title.get('code'))) 
                t_wo_completed = t_wo_completed + 1
                o_wo_completed = o_wo_completed + 1
                #Update the completion ratios attached, since there were no blocking exceptions 
                server.update(title.get('__search_key__'), {'wo_completed': t_wo_completed})
                server.update(order.get('__search_key__'), {'wo_completed': o_wo_completed})
            elif old_status == COMPLETE:
                t_wo_completed = t_wo_completed - 1
                o_wo_completed = o_wo_completed - 1
                #Reduce the completion ratio, since it was completed but has now been taken off that status
                server.update(title.get('__search_key__'), {'wo_completed': t_wo_completed})
                server.update(order.get('__search_key__'), {'wo_completed': o_wo_completed})
        #Still doing this, but don't know if it's neccessary anymore        
        mmkay = block_manual_status_adjust_for_inactive_hackup(parent_obj, sobj)
        if new_status == COMPLETE and 'PROJ' not in this_lookup:
            #Make sure they have set the assigned person to the work order.
            if sobj.get('assigned') in [None,'']:
                task_assigned_expr = "@GET(sthpw/task['code','%s'].assigned)" % sobj.get('code') #MTM: Do I need to retrieve the task again, or can I just use the sobj's "assigned"? 
                task_assigned = server.eval(task_assigned_expr)
                if task_assigned:
                    task_assigned = task_assigned[0]
                if task_assigned in [None,'']:
                    raise TacticException('Before completing a work order, someone must be assigned to it.')
            #Make sure they have added work hours. If not, error out.
            whs_expr = "@SOBJECT(sthpw/work_hour['task_code','%s'])" % task_code
            whs = server.eval(whs_expr)
            sum = 0
            for wh in whs:
                straight_time = wh.get('straight_time')
                if straight_time in [None,'']:
                    straight_time = 0
                else:
                    straight_time = float(straight_time)
                sum = float(sum) + straight_time
                sum = str(sum)
            if sum in ['0','',0,0.0]:
                raise TacticException('You need to save the hours you worked on this before you can set the status to "Completed".')
        
        now_timestamp = make_timestamp() 
        #Since there have been no blocking exceptions, record the status change
        server.insert('twog/status_log', {'login': user_name, 'timestamp': now_timestamp, 'from_status': old_status, 'status': new_status, 'task_code': task_code, 'lookup_code': this_lookup, 'order_code': sobj.get('order_code'), 'title_code': sobj.get('title_code'), 'process': this_process})
        if new_status == COMPLETE:
            #Record the completion date on the work order, and take it off the BigBoard
            import datetime
            now = datetime.datetime.now()
            timestamp_str = '%s-%s-%s %s:%s:%s' % (now.year, now.month, now.day, now.hour, now.minute, now.second)
            updict = {'actual_end_date': timestamp_str}
            if 'WORK_ORDER' in this_lookup:
                updict['bigboard'] = False
            server.update(sk, updict)
        elif new_status not in ['Pending','Ready','Completed'] and 'WORK_ORDER' in this_lookup:
            server.update(server.build_search_key('sthpw/task', proj.get('task_code')), {'status': new_status})        #NEW
        if 'PROJ' in sobj.get('lookup_code'):
            #MTM: This annoying section is for passing Proj's their task's status.
            #I don't know if this is needed at all anymore. Will have to check other triggers and reports.
            #The "tripwire" stuff was just to keep it from infinitely passing statuses from proj to task, task to proj
            do_it = True
            if 'tripwire' in update_data.keys():
                if update_data.get('tripwire') == 'No Send Back': #?
                    do_it = False
                    server.update(input.get('search_key'), {'tripwire': ''}, triggers=False) #Empty the tripwire and do nothing
                    server.update(proj.get('__search_key__'), {'tripwire': '', 'status': sobj.get('status')}, triggers=False) #?
            if do_it:
                if proj:
                    server.update(proj.get('__search_key__'), {'status': new_status})
        if title.get('priority_triggers') != 'No':
            #Update Title Priority for On Hold Status, or having that status removed -- BEGIN
            if sobj.get('status') in ['On_Hold','On Hold']:
                title_priority = title.get('priority')
                server.update(title.get('__search_key__'), {'saved_priority': title_priority, 'priority': 200}, triggers=False)    
            else:
                if old_status in ['On_Hold','On Hold']:
                    saved_priority = title.get('saved_priority')
                    server.update(title.get('__search_key__'), {'priority': saved_priority}, triggers=False)    
            #Update Title Priority for On Hold Status, or having that status removed -- END
        
            #Update Title Priority for Client Response Status, or having that status removed -- BEGIN
            if sobj.get('status') == 'Client Response':
                title_priority = title.get('priority')
                crc = title.get('client_response_count')
                crc_num = 0
                if crc not in [None,'']:
                    crc_num = int(crc)
                crc_num = crc_num + 1        
                server.update(title.get('__search_key__'), {'saved_priority': title_priority, 'priority': 300, 'client_response_count': crc_num}, triggers=False)    
            else:
                if old_status == 'Client Response':
                    saved_priority = title.get('saved_priority')
                    crc = title.get('client_response_count')
                    crc_num = 0
                    if crc not in [None,'']:
                        crc_num = int(crc)
                    if crc_num > 0:
                        crc_num = crc_num - 1        
                    server.update(title.get('__search_key__'), {'priority': saved_priority, 'client_response_count': crc_num}, triggers=False)    
            #Update Title Priority for Client Response Status, or having that status removed -- END
                 
        if sobj.get('status') in ['In_Progress','In Progress','DR In_Progress','DR In Progress', 'Amberfin01_In_Progress', 'Amberfin01 In Progress', 'Amberfin02_In_Progress', 'Amberfin02 In Progress','BATON In_Progress','BATON In Progress','Export In_Progress','Export In Progress','Buddy Check In_Progress','Buddy Check In Progress','Need Buddy Check','Completed'] and old_status not in ['In_Progress','DR In_Progress','DR In Progress','Amberfin01_In_Progress','Amberfin01 In Progress', 'Amberfin02_In_Progress','Amberfin02 In Progress','BATON In_Progress','BATON In Progress','Export In_Progress','Export In Progress','Buddy Check In_Progress','Buddy Check In Progress','Need Buddy Check','In Progress']:
            #Update the actual start date if they just set the status to 'In Progress'
            if sobj.get('actual_start_date') in ['',None]:
                now_timestamp = make_timestamp() 
                server.update(sk, {'actual_start_date': now_timestamp})
        if sobj.get('status') in ['Ready','In_Progress','In Progress'] and 'WORK_ORDER' in sobj.get('lookup_code'):
            if title.get('client_status') != 'In Production':
                server.update(title.get('__search_key__'), {'client_status': 'In Production', 'status': 'In Production'})
        elif sobj.get('status') in ['Rejected','Fix Needed'] and 'WORK_ORDER' in sobj.get('lookup_code'):
            from pyasm.biz import Note
            from pyasm.search import Search
            server.insert('twog/production_error', {'error_type': sobj.get('status'), 'process': sobj.get('process'), 'work_order_code': sobj.get('lookup_code'), 'title': title.get('title'), 'episode': title.get('episode'), 'title_code': title.get('code'), 'order_code': order.get('code'), 'order_name': order.get('name'), 'po_number': order.get('po_number'), 'proj_code': proj.get('code'), 'scheduler_login': sobj.get('creator_login'), 'operator_login': user_name, 'login': user_name}) 
            if sobj.get('status') == 'Rejected':
                server.update(title.get('__search_key__'), {'client_status': 'QC Rejected'})
                if title.get('priority_triggers') != 'No':
                    server.update(title.get('__search_key__'), {'priority': 90}, triggers=False)
                title_obj2 = Search.get_by_search_key(title.get('__search_key__'))   #This is the type of object required for Note creation
                note_text = '%s (%s) has been Rejected, as marked by %s' % (sobj.get('process'), this_lookup, user_name)
                note = Note.create(title_obj2, note_text, context='QC Rejected', process='QC Rejected')
        
        if sobj.get('status') == COMPLETE and title.get('status_triggers') != 'No':
            # Now we need to set the next task(s) statuses to 'Ready'
            parent = server.get_parent(sk)
            # Get all process information from the pipeline regarding processes linked to this process in the normal pipeline
            info = server.get_pipeline_processes_info(parent.get('__search_key__'), related_process=this_process)
            input_processes = info.get('input_processes')
            output_processes = info.get('output_processes')
            # this combines all other input_processes and this process
            # including this_process in case this process has more than 1 task
            ready = False
            if input_processes:
                input_processes.append(this_process)
                ready = True
                input_tasks = server.query('sthpw/task', filters = [('search_type', sobj.get('search_type')), ('search_id', sobj.get('search_id')), ('process', input_processes), ('title_code',sobj.get('title_code'))])
                for task in input_tasks:
                    if task.get('status') != COMPLETE:
                        ready = False
            else:
                ready = True
            #Now we need to check the manually entered work orders and projs 
            #This section may be replaced with the are_no_hackpipes_preceding function, but for the sake of stability, I won't do it until I test it again
            hack_outs_expr = "@SOBJECT(twog/hackpipe_out['out_to','%s'])" % sobj.get('lookup_code')
            hack_outs = server.eval(hack_outs_expr)
            stype = ''
            stype_st = ''
            if 'PROJ' in sobj.get('lookup_code'):
                stype = 'PROJ'
                stype_st = 'twog/proj'
            elif 'WORK_ORDER' in sobj.get('lookup_code'):
                stype = 'WORK_ORDER'
                stype_st = 'twog/work_order'
            for ho in hack_outs:
                lookup_code = ho.get('lookup_code')
                if stype in lookup_code:
                    hacktasks = server.eval("@SOBJECT(sthpw/task['lookup_code','%s'])" % lookup_code)
                    for hacktask in hacktasks:
                        if hacktask.get('status') != COMPLETE:
                            ready = False
               
            # make the next process ready
            if ready == True:
                output_tasks = server.query('sthpw/task', filters = [('search_type', sobj.get('search_type')), ('search_id', sobj.get('search_id')), ('process', output_processes), ('title_code',sobj.get('title_code'))])
                update_data = {}
           
                for task in output_tasks:
                    if task.get('lookup_code') not in [None,'']:
                        if task.get('status') == 'Pending':
                            #Need to make sure other tasks leading into this one (an output task for the triggered task) are also complete - both ways, with pipeline and hackpipe - before allowing this status update 
                            
                            out_info = server.get_pipeline_processes_info(parent.get('__search_key__'), related_process=task.get('process'))
                            input_to_out = out_info.get('input_processes') 
                            if this_process in input_to_out:
                               prc_idx = input_to_out.index(this_process)
                               input_to_out.pop(prc_idx)
                            ready2 = False
                            if input_to_out:
                                #input_to_out.append(task.get('process'))
                                ts_st = ''
                                if 'PROJ' in task.get('lookup_code'):
                                    ts_st = 'twog/proj'
                                elif 'WORK_ORDER' in task.get('lookup_code'):
                                    ts_st = 'twog/work_order'
                                tsob = server.eval("@SOBJECT(%s['code','%s'])" % (ts_st, task.get('lookup_code')))[0] 
                                ready2 = are_no_hackpipes_preceding(tsob, sobj.get('lookup_code'))
                                into_out_tasks = server.query('sthpw/task', filters = [('search_type', task.get('search_type')), ('search_id', task.get('search_id')), ('process', input_to_out)])
                                for iotask in into_out_tasks:
                                    # If preceding tasks have not yet been set to 'Completed', do not change the next task's status
                                    if iotask.get('status') != COMPLETE:
                                        ready2 = False
                            else:
                                ready2 = True
                            hacks_expr = "@SOBJECT(twog/hackpipe_out['out_to','%s'])" % task.get('lookup_code')
                            hacks = server.eval(hacks_expr)
                            for hack in hacks:
                                lu_code = hack.get('lookup_code') 
                                hacktasks = server.eval("@SOBJECT(sthpw/task['lookup_code','%s'])" % lu_code)
                                for hacktask in hacktasks:
                                    if hacktask.get('status') != COMPLETE:
                                        ready2 = False
                            if ready2 == True:
                                update_data[task.get('__search_key__')] = { 'status': READY }
                                if 'PROJ' in task.get('lookup_code'):
                                    get_proj_expr = "@SOBJECT(twog/proj['code','%s'])" % task.get('lookup_code')
                                    proj = server.eval(get_proj_expr)[0]
                                    # FIND ALL NON HACK WOS
                                    wos = server.eval("@SOBJECT(twog/work_order['proj_code','%s'])" % proj.get('code'))
                                    for wo in wos: 
                                        if wo.get('creation_type') not in ['hackpipe','hackup']:
                                            this_processer = wo.get('process')
                                            info2 = server.get_pipeline_processes_info(proj.get('__search_key__'), related_process=this_processer)
                                            input_processes2 = info2.get('input_processes')
                                            okayed = are_no_hackpipes_preceding(wo, sobj.get('lookup_code'))
                                            len_proc = 0
                                            if input_processes2 not in ['',{},[],None]:
                                                len_proc = len(input_processes2)
                                            if len_proc < 1 and okayed:
                                                task2 = server.eval("@SOBJECT(sthpw/task['code','%s'])" % wo.get('task_code')) 
                                                if task2:
                                                    task2 = task2[0]
                                                    if task2.get('status') == 'Pending':
                                                        server.update(task2.get('__search_key__'), {'status': READY}) #?
                                    # FIND ALL HACK WOS HERE.........
                                    hack_dudes = server.eval("@SOBJECT(twog/hackpipe_out['lookup_code','%s'])" % proj.get('code'))
                                    for ho in hack_dudes:
                                        ready3 = True
                                        out_to = ho.get('out_to')
                                        label = ''
                                        if 'PROJ' in out_to:
                                            label = 'twog/proj'
                                        elif 'WORK_ORDER' in out_to:
                                            label = 'twog/work_order'
                                        sob_guy = server.eval("@SOBJECT(%s['code','%s'])" % (label, out_to))
                                        for sobby in sob_guy:
                                            ready3 = are_no_hackpipes_preceding(sobby, sobj.get('lookup_code'))
                                        if ready3:
                                            htask = server.eval("@SOBJECT(sthpw/task['lookup_code','%s'])" % out_to)
                                            if htask:
                                                htask = htask[0]
                                                if htask.get('status') == 'Pending':
                                                    server.update(htask.get('__search_key__'), {'status': READY})
                                    
                hackers = server.eval("@SOBJECT(twog/hackpipe_out['lookup_code','%s'])" % sobj.get('lookup_code'))
                for hack in hackers:
                    if stype in hack.get('out_to'):
                        out_to = hack.get('out_to')
                        out_sob = server.eval("@SOBJECT(%s['code','%s'])" % (stype_st, out_to))
                        if out_sob:
                            out_sob = out_sob[0] 
                            ready4 = are_no_hackpipes_preceding(out_sob, sobj.get('lookup_code'))
                            if ready4:
                                tasker = server.eval("@SOBJECT(sthpw/task['code','%s'])" % out_sob.get('task_code'))
                                if tasker:
                                    tasker = tasker[0]
                                    if tasker.get('status') == 'Pending':
                                        server.update(tasker.get('__search_key__'), {'status': READY})
                                        if stype == 'PROJ':
                                            # Need to do the same thing here, looking at pipeline and hackpipe
                                            hack_wos = server.eval("@SOBJECT(twog/hackpipe_out['lookup_code','%s'])" % out_to)
                                            for hos in hack_wos:
                                                if 'PROJ' not in hos.get('out_to'):
                                                    ho_wo = server.eval("@SOBJECT(twog/work_order['code','%s'])" % hos.get('out_to'))
                                                    if ho_wo:
                                                        ho_wo = ho_wo[0]
                                                        ready5 = are_no_hackpipes_preceding(ho_wo, out_sob.get('code'))
                                                        if ready5:
                                                            ho_wo_task_sk = server.build_search_key('sthpw/task', ho_wo.get('task_code'))
                                                            #7/10/2014 --- WAIT. WTF. THERE IS NO STATUS ON WOS, JUST THE TASK..... MTMMTMMTM!!!
                                                            if ho_wo.get('status') == 'Pending':
                                                                server.update(ho_wo_task_sk, {'status': READY})
                                            # NEED TO LOOK AT PROJ PIPELINE NOW
                                            proj_sk = server.build_search_key('twog/proj', out_to)
                                            pipe_wos = server.eval("@SOBJECT(twog/work_order['proj_code','%s'])" % out_to)
                                            for pwos in pipe_wos:
                                                if pwos.get('creation_type') not in ['hackpipe','hackup']:
                                                    info2 = server.get_pipeline_processes_info(proj_sk, related_process=pwos.get('process'))
                                                    if 'input_processes' in info2.keys():
                                                        input_processes2 = info2.get('input_processes')
                                                        whack_says = are_no_hackpipes_preceding(pwos, out_to)
                                                        # If there are no input processes, it must be a work order that should also be set to ready - as long as hackpipe says it's ok
                                                        len_proc2 = 0
                                                        if input_processes2 not in ['',{},[],None]:
                                                            len_proc2 = len(input_processes2)
                                                        if len_proc2 < 1 and whack_says:
                                                            wtask_code = pwos.get('task_code')
                                                            # Get the task sobject associated with this work order
                                                            wtask = server.eval("@SOBJECT(sthpw/task['code','%s'])" % wtask_code)
                                                            if wtask:
                                                                wtask = wtask[0]
                                                                # If the task's status has not been touched yet ('Pending') and active is set to true, update the status with 'Ready'
                                                                if wtask.get('status') == 'Pending':
                                                                    wdata = {}
                                                                    wdata['status'] = 'Ready'
                                                                    if wtask.get('status') == 'Pending':
                                                                        server.update(wtask.get('__search_key__'), wdata)
                                                
                            
                          
                #
                # HERE NEED TO FIND ANY OTHER TASKS THIS GOES 'OUT_TO' and make sure they don't also depend on another task's status (if so, make sure it is completed)
                #
                        
                # this is optional, for simplicity, turn off triggers for these updates
                if update_data != {} and title.get('priority_triggers') != 'No':
                    #make title priority the proj priority, if proj is becoming "Ready"
                    for tkey in update_data.keys():
                        record = update_data.get(tkey)
                        tkcode = tkey.split('code=')[1]
                        if 'status' in record.keys():
                            if record.get('status') == 'Ready':
                                ttt = server.eval("@GET(sthpw/task['code','%s'].lookup_code)" % tkcode)[0]
                                if 'PROJ' in ttt:
                                    pjj = server.eval("@SOBJECT(twog/proj['code','%s'])" % ttt)[0]
                                    proj_title_code = pjj.get('title_code')
                                    proj_prio = pjj.get('priority')
                                    server.update(server.build_search_key('twog/title',proj_title_code), {'priority': proj_prio}, triggers=False)
                    server.update_multiple(update_data, triggers=False) #? Should triggers=False?
            
        
        # Now see if all wos under proj or all projs under title are completed. If so, make their parent's status completed
        all_wos_completed = False
        all_wos_pending = False
        prj = None
        if new_status in [COMPLETE,PENDING]: 
            if 'WORK_ORDER' in this_lookup:
                wo = server.eval("@SOBJECT(twog/work_order['code','%s'])" % sobj.get('lookup_code'))
                wo = wo[0]
                other_wotasks_expr = "@SOBJECT(twog/proj['code','%s'].twog/work_order.WT:sthpw/task)" % wo.get('proj_code')
                other_wo_tasks = server.eval(other_wotasks_expr)
                all_wos_completed = True
                all_wos_pending = True
                if new_status == PENDING:
                    all_wos_completed = False
                else:
                    all_wos_pending = False
                for owt in other_wo_tasks:
                    if owt.get('lookup_code') != wo.get('code'):
                        if owt.get('status') != COMPLETE:
                            all_wos_completed = False
                        if owt.get('status') != PENDING:
                            all_wos_pending = False
                prj = server.eval("@SOBJECT(twog/proj['code','%s'])" % wo.get('proj_code'))
                if len(prj) > 0:
                    prj = prj[0]
                else:
                    prj = None
                if (all_wos_completed or all_wos_pending) and prj not in [None,'']:
                    if title.get('status_triggers') != 'No' or all_wos_pending == True:
                        prj_task = server.eval("@SOBJECT(sthpw/task['lookup_code','%s'])" % prj.get('code'))
                        if prj_task:
                            prj_task = prj_task[0]
                            server.update(prj_task.get('__search_key__'), {'status': new_status})
            elif 'PROJ' in this_lookup:
                prj = server.eval("@SOBJECT(twog/proj['code','%s'])" % this_lookup)
                if prj:
                    prj = prj[0]
                else:
                    prj = None
        
            all_projs_completed = True
            all_projs_pending = True
            all_titles_completed = False
            all_titles_pending = False
            if prj not in [None,'']:
                title_proj_tasks = server.eval("@SOBJECT(twog/title['code','%s'].twog/proj.PT:sthpw/task)" % prj.get('title_code'))
                for tpt in title_proj_tasks:
                    if tpt.get('status') != COMPLETE:
                        all_projs_completed = False
                    if tpt.get('status') != PENDING:
                        all_projs_pending = False
                title_updated = False
                if all_projs_completed:
                    title_sk = server.build_search_key('twog/title', prj.get('title_code'))
                    if title.get('priority_triggers') != 'No' and title.get('status_triggers') != 'No':
                        server.update(title_sk, {'status': COMPLETE, 'bigboard': False, 'priority': 5000})
                        titles_completed = order.get('titles_completed')
                        title_codes_completed = order.get('title_codes_completed')
                        if title.get('code') not in title_codes_completed:
                            if titles_completed in [None,'']:
                                titles_completed = 0
                            else:
                                titles_completed = int(titles_completed)
                            titles_completed = titles_completed + 1
                            if title_codes_completed == '':
                                title_codes_completed = title.get('code')
                            else:
                                title_codes_completed = '%s,%s' % (title_codes_completed, title.get('code'))
                            server.update(order.get('__search_key__'), {'titles_completed': titles_completed, 'title_codes_completed': title_codes_completed}) 
                        title_updated = True
                    all_titles_completed = True
                    title = server.eval("@SOBJECT(twog/title['code','%s'])" % prj.get('title_code'))
                    if title and title_updated:
                        title = title[0]
                        other_titles = server.eval("@SOBJECT(twog/order['code','%s'].twog/title)" % title.get('order_code'))
                        for ot in other_titles:
                            if title.get('code') != ot.get('code'):
                                if ot.get('status') != COMPLETE:
                                    all_titles_completed = False
                    else:
                        all_titles_completed = False
                if all_projs_pending:
                    title_sk = server.build_search_key('twog/title', prj.get('title_code'))
                    if title.get('priority_triggers') != 'No' and title.get('status_triggers') != 'No':
                        server.update(title_sk, {'status': '', 'bigboard': False})
                        title_codes_completed = order.get('title_codes_completed')
                        if title.get('code') in title_codes_completed:
                            title_codes_completed = title_codes_completed.replace(',%s'  % title.get('code'),'').replace('%s,'  % title.get('code'),'').replace('%s'  % title.get('code'),'')
                            titles_completed = order.get('titles_completed')
                            if titles_completed in [None,'']:
                                titles_completed = 0
                            else:
                                titles_completed = int(titles_completed) - 1
                            server.update(order.get('__search_key__'), {'titles_completed': titles_completed, 'title_codes_completed': title_codes_completed})
                        title_updated = True
                    all_titles_pending = True
                    title = server.eval("@SOBJECT(twog/title['code','%s'])" % prj.get('title_code'))
                    if title and title_updated:
                        title = title[0]
                        other_titles = server.eval("@SOBJECT(twog/order['code','%s'].twog/title)" % title.get('order_code'))
                        for ot in other_titles:
                            if title.get('code') != ot.get('code'):
                                if ot.get('status') != '':
                                    all_titles_pending = False
                    else:
                        all_titles_pending = False
            if all_titles_pending:
                server.update(server.build_search_key('twog/order', title.get('order_code')), {'needs_completion_review': False}) 
            if all_titles_completed:
                server.update(server.build_search_key('twog/order', title.get('order_code')), {'needs_completion_review': True}) 
                    
        #print "LEAVING KICKOFF"
    except AttributeError as e:
        traceback.print_exc()
        print str(e) + '\nMost likely the server object does not exist.'
        raise e
    except KeyError as e:
        traceback.print_exc()
        print str(e) + '\nMost likely the input dictionary does not exist.'
        raise e
    except Exception as e:
        traceback.print_exc()
        print str(e)
        raise e
    def get_message(my):
        search_type_obj = my.parent.get_search_type_obj()
        title = search_type_obj.get_title()
        subject = my.get_subject()
        notification_message = my.notification.get_value("message")

        message = "%s %s Note Entry" % (title, my.parent.get_name())
        if notification_message:
            message = "%s (%s)" %(message, notification_message)

        submit_desc = ''

        from pyasm.prod.biz import Submission
        if isinstance(my.parent, Submission):
            update_info = ['']
            # add more info about the file and bin
            snapshot = Snapshot.get_latest_by_sobject(my.parent, "publish")
            xpath = "snapshot/file[@type='main']"
            xml = snapshot.get_xml_value('snapshot')
            file = None
            if xml.get_node(xpath) is not None:
                file = my._get_file_obj(snapshot)
            else:
                snapshots = snapshot.get_all_ref_snapshots()
                snapshot_file_objects = []
                if snapshots:
                    snapshot = snapshots[0]
                    file = my._get_file_obj(snapshot, type=None)
            if file:
                file_name = file.get_file_name()
                web_path = file.get_web_path()
                from pyasm.web import WebContainer 
                host = WebContainer.get_web().get_base_url()
                update_info.append('Browse: %s %s%s' %( file_name, host.to_string(), web_path))

            bins = my.parent.get_bins()
            bin_labels = [ bin.get_label() for bin in bins]
            update_info.append('Bin: %s' %', '.join(bin_labels))

            update_info.append('Artist: %s' %my.parent.get_value('artist'))
            update_info.append('Description: %s' %my.parent.get_value('description'))
             
            # get notes
            search = Note.get_search_by_sobjects([my.parent])
            if search:
                search.add_order_by("context")
                search.add_order_by("timestamp desc")
            notes = search.get_sobjects()

            last_context = None
            note_list = []
            for i, note in enumerate(notes):
                context = note.get_value('context')
                # explicit compare to None
                if last_context == None or context != last_context:
                    note_list.append( "[ %s ] " % context )
                last_context = context
                
                #child_notes = my.notes_dict.get(note.get_id())
                # draw note item
                date = Date(db=note.get_value('timestamp'))
                note_list.append('(%s) %s'%(date.get_display_time(), note.get_value("note")))
            update_info.append('Notes: \n %s' % '\n'.join(note_list))

            submit_desc =  '\n'.join(update_info)

            
        update_desc = my.sobject.get_update_description()
        command_desc = my.command.get_description()

        message = '%s\n\nReport from transaction:\n%s\n\n%s\n%s' \
            % (message, update_desc, command_desc, submit_desc)
        return message
Exemple #7
0
    def get_message(my):
        search_type_obj = my.parent.get_search_type_obj()
        title = search_type_obj.get_title()
        subject = my.get_subject()
        notification_message = my.notification.get_value("message")

        message = "%s %s Note Entry" % (title, my.parent.get_name())
        if notification_message:
            message = "%s (%s)" % (message, notification_message)

        submit_desc = ''

        from pyasm.prod.biz import Submission
        if isinstance(my.parent, Submission):
            update_info = ['']
            # add more info about the file and bin
            snapshot = Snapshot.get_latest_by_sobject(my.parent, "publish")
            xpath = "snapshot/file[@type='main']"
            xml = snapshot.get_xml_value('snapshot')
            file = None
            if xml.get_node(xpath) is not None:
                file = my._get_file_obj(snapshot)
            else:
                snapshots = snapshot.get_all_ref_snapshots()
                snapshot_file_objects = []
                if snapshots:
                    snapshot = snapshots[0]
                    file = my._get_file_obj(snapshot, type=None)
            if file:
                file_name = file.get_file_name()
                web_path = file.get_web_path()
                from pyasm.web import WebContainer
                host = WebContainer.get_web().get_base_url()
                update_info.append('Browse: %s %s%s' %
                                   (file_name, host.to_string(), web_path))

            bins = my.parent.get_bins()
            bin_labels = [bin.get_label() for bin in bins]
            update_info.append('Bin: %s' % ', '.join(bin_labels))

            update_info.append('Artist: %s' % my.parent.get_value('artist'))
            update_info.append('Description: %s' %
                               my.parent.get_value('description'))

            # get notes
            search = Note.get_search_by_sobjects([my.parent])
            if search:
                search.add_order_by("context")
                search.add_order_by("timestamp desc")
            notes = search.get_sobjects()

            last_context = None
            note_list = []
            for i, note in enumerate(notes):
                context = note.get_value('context')
                # explicit compare to None
                if last_context == None or context != last_context:
                    note_list.append("[ %s ] " % context)
                last_context = context

                #child_notes = my.notes_dict.get(note.get_id())
                # draw note item
                date = Date(db=note.get_value('timestamp'))
                note_list.append(
                    '(%s) %s' %
                    (date.get_display_time(), note.get_value("note")))
            update_info.append('Notes: \n %s' % '\n'.join(note_list))

            submit_desc = '\n'.join(update_info)

        update_desc = my.sobject.get_update_description()
        command_desc = my.command.get_description()

        message = '%s\n\nReport from transaction:\n%s\n\n%s\n%s' \
            % (message, update_desc, command_desc, submit_desc)
        return message
Exemple #8
0
def main(server=None, input=None):
    """
    The main function of the custom script. The entire script was copied
    and pasted into the body of the try statement in order to add some
    error handling. It's all legacy code, so edit with caution.

    :param server: the TacticServerStub object
    :param input: a dict with data like like search_key, search_type, sobject, and update_data
    :return: None
    """
    if not input:
        input = {}

    try:
        # CUSTOM_SCRIPT00091
        #
        # Created by Matthew Misenhimer
        #

        def no_incompletes_preceding(new_sob, initial_sob_code):
            comes_from = new_sob.get('comes_from').split('|^|')
            for c in comes_from:
                if initial_sob_code not in c:
                    task_code = c.split(',')[1]
                    task_code = task_code.replace(']', '').replace('[', '')
                    task_status = server.eval("@GET(sthpw/task['code','{0}'].status)".format(task_code))[0]
                    if task_status != 'Completed':
                        return False
            return True

        from pyasm.common import TacticException, Environment
        # input and server are assumed variables
        # define some constants here
        COMPLETE = 'Completed'
        READY = 'Ready'
        PENDING = 'Pending'
        sobj = input.get('sobject')

        # This next statement will basically skip the entire script if the task is a task assigned to onboarding,
        # asking them to create a workflow/pipeline. Ideally I would disable this entire script, since it's an
        # incoherent mess, but I can't do that without messing up a bunch of other things. Once the Order/Title/Task
        # logic has all been updated, then this script can be removed entirely, but until then, this will have to do.
        if 'Make a Workflow for' in sobj.get('process'):
            return

        this_process = sobj.get('process')
        this_lookup = sobj.get('lookup_code')
        sk = input.get('search_key')
        task_code = sobj.get('code')
        # These are the new values
        update_data = input.get('update_data')
        old_status = ''
        if 'prev_data' in input:
            # These are the old values
            prev_data = input.get('prev_data')
            old_status = prev_data.get('status', '')
        new_status = update_data.get('status')
        login = Environment.get_login()
        user_name = login.get_login()
        assigned_login_group = sobj.get('assigned_login_group')
        proj = None
        title = None
        order = None
        if 'PROJ' in this_lookup:
            # Parent Obj is the Proj attached to the task
            parent_obj = server.eval("@SOBJECT(twog/proj['code','{0}'])".format(this_lookup))[0]
            proj = parent_obj
            title = server.eval("@SOBJECT(twog/title['code','{0}'])".format(parent_obj.get('title_code')))[0]
            order = server.eval("@SOBJECT(twog/order['code','{0}'])".format(title.get('order_code')))[0]
        elif 'WORK_ORDER' in this_lookup:
            # Parent Obj is the Work Order attached to the task
            parent_obj = server.eval("@SOBJECT(twog/work_order['code','{0}'])".format(this_lookup))[0]
            work_order = parent_obj
            proj = server.eval("@SOBJECT(twog/proj['code','{0}'])".format(work_order.get('proj_code')))[0]
            title = server.eval("@SOBJECT(twog/title['code','{0}'])".format(proj.get('title_code')))[0]
            order = server.eval("@SOBJECT(twog/order['code','{0}'])".format(title.get('order_code')))[0]
        if 'PROJ' in this_lookup and title.get('priority_triggers') != 'No':
            pass
        elif 'WORK_ORDER' in this_lookup:
            if new_status == COMPLETE:
                # Make sure they have set the assigned person to the work order.
                if sobj.get('assigned') in [None, '']:
                    raise TacticException('Before completing a work order, someone must be assigned to it.')
                # Make sure they have added work hours. If not, error out.
                total_time = server.eval("@SUM(sthpw/work_hour['task_code','{0}'].straight_time)".format(task_code))
                if total_time < 0.001:  # account for floating point inaccuracy
                    raise TacticException('You need to save the hours you worked on this before you can set the status to "Completed".')
            # This is for the completion ratio on title
            t_wo_completed = title.get('wo_completed')
            # This is for the completion ratio on order
            o_wo_completed = order.get('wo_completed')
            if new_status == COMPLETE:
                # This is for a potential alert/exception
                title_str = title.get('title')
                if title.get('episode') not in [None, '']:
                    title_str = '{0}: {1}'.format(title_str, title.get('episode'))
                # Block QC and Edel from completing their work orders if the TRT or TRT w/Textless are not filled in
                if 'qc' in assigned_login_group or 'edeliveries' in assigned_login_group:
                    total_program_runtime = title.get('total_program_runtime')
                    total_runtime_w_textless = title.get('total_runtime_w_textless')
                    invalid_runtime = total_program_runtime in [None, ''] or total_runtime_w_textless in [None, '']
                    say_str = ''
                    say_str2 = ''
                    if invalid_runtime:
                        if total_program_runtime in [None, '']:
                            say_str = 'Total Program Runtime has'
                        if total_runtime_w_textless in [None, '']:
                            if say_str == '':
                                say_str = 'Total Runtime With Textless has'
                            else:
                                say_str = '%s and Total Runtime With Textless have' % (say_str[:-4])
                        say_str2 = "%s (%s)'s %s not been filled. You must enter this data before trying to complete this work order." % (title_str, title.get('code'), say_str)
                    if 'qc' in assigned_login_group:
                        if invalid_runtime:
                            raise TacticException(say_str2)
                        else:
                            # They were filled in, so finish completing the task and send a note
                            from pyasm.biz import Note
                            from pyasm.search import Search
                            # This is the type of object required for Note creation
                            title_obj2 = Search.get_by_search_key(title.get('__search_key__'))
                            note_text = '%s (%s) has been Passed and Completed by %s in QC' % (sobj.get('process'), this_lookup, user_name)
                            note = Note.create(title_obj2, note_text, context='QC Completed', process='QC Completed')
                    elif 'edeliveries' in assigned_login_group and invalid_runtime:
                        raise TacticException(say_str2)
                t_wo_completed += 1
                o_wo_completed += 1
                # Update the completion ratios attached, since there were no blocking exceptions
                server.update(title.get('__search_key__'), {'wo_completed': t_wo_completed})
                server.update(order.get('__search_key__'), {'wo_completed': o_wo_completed})
            elif old_status == COMPLETE:
                t_wo_completed -= 1
                o_wo_completed -= 1
                # Reduce the completion ratio, since it was completed but has now been taken off that status
                server.update(title.get('__search_key__'), {'wo_completed': t_wo_completed})
                server.update(order.get('__search_key__'), {'wo_completed': o_wo_completed})

        now_timestamp = make_timestamp()
        # Since there have been no blocking exceptions, record the status change
        stat_log_dict = {'login': user_name, 'timestamp': now_timestamp, 'from_status': old_status,
                         'status': new_status, 'task_code': task_code, 'lookup_code': this_lookup,
                         'order_code': sobj.get('order_code'), 'title_code': sobj.get('title_code'),
                         'process': this_process}
        server.insert('twog/status_log', stat_log_dict)
        if new_status == COMPLETE:
            # Record the completion date on the work order, and take it off the BigBoard
            updict = {'actual_end_date': make_timestamp()}
            do_indie = False
            if 'WORK_ORDER' in this_lookup:
                updict['bigboard'] = False
                if sobj.get('indie_bigboard') in [True, 'true', 't', 'T', 1]:
                    updict['indie_bigboard'] = False
                    do_indie = True
            server.update(sk, updict)
            if do_indie:
                indies = server.eval("@SOBJECT(twog/indie_bigboard['task_code','{0}'])".format(task_code))
                for indie in indies:
                    indie_dict = {'indie_bigboard': False}
                    if indie.get('removal_login') in [None, '']:
                        indie_dict['removal_login'] = user_name
                    if indie.get('removal_login') in [None, '']:
                        indie_dict['removal_timestamp'] = now_timestamp
                    server.update(indie.get('__search_key__'), indie_dict)
        elif new_status not in ['Pending', 'Ready', 'Completed'] and 'WORK_ORDER' in this_lookup:
            server.update(server.build_search_key('sthpw/task', proj.get('task_code')), {'status': new_status})
        if 'PROJ' in sobj.get('lookup_code'):
            # MTM: This annoying section is for passing Proj's their task's status.
            # I don't know if this is needed at all anymore. Will have to check other triggers and reports.
            # The "tripwire" stuff was just to keep it from infinitely passing statuses from proj to task, task to proj
            do_it = True
            if update_data.get('tripwire', '') == 'No Send Back':
                do_it = False
                # Empty the tripwire and do nothing
                server.update(input.get('search_key'), {'tripwire': ''}, triggers=False)
                server.update(proj.get('__search_key__'), {'tripwire': '', 'status': sobj.get('status')},
                              triggers=False)
            if do_it and proj:
                server.update(proj.get('__search_key__'), {'status': new_status})
        if title.get('priority_triggers') != 'No':
            # Update Title Priority for On Hold Status, or having that status removed -- BEGIN
            if sobj.get('status') in ['On_Hold', 'On Hold']:
                title_priority = title.get('priority')
                server.update(title.get('__search_key__'), {'saved_priority': title_priority, 'priority': 200},
                              triggers=False)
            elif old_status in ['On_Hold', 'On Hold']:
                saved_priority = title.get('saved_priority')
                server.update(title.get('__search_key__'), {'priority': saved_priority}, triggers=False)
            # Update Title Priority for On Hold Status, or having that status removed -- END

            # Update Title Priority for Client Response Status, or having that status removed -- BEGIN
            if sobj.get('status') == 'Client Response':
                title_priority = title.get('priority')
                crc = title.get('client_response_count')
                crc_num = 0
                if crc not in [None, '']:
                    crc_num = int(crc)
                crc_num += 1
                title_update_data = {'saved_priority': title_priority, 'priority': 300,
                                     'client_response_count': crc_num}
                server.update(title.get('__search_key__'), title_update_data, triggers=False)
            elif old_status == 'Client Response':
                saved_priority = title.get('saved_priority')
                crc = title.get('client_response_count')
                crc_num = 0
                if crc not in [None, '']:
                    crc_num = int(crc)
                if crc_num > 0:
                    crc_num -= 1
                title_update_data = {'priority': saved_priority, 'client_response_count': crc_num}
                server.update(title.get('__search_key__'), title_update_data, triggers=False)
            # Update Title Priority for Client Response Status, or having that status removed -- END

        statuses = ['In_Progress', 'In Progress', 'DR In_Progress', 'DR In Progress', 'Amberfin01_In_Progress',
                    'Amberfin01 In Progress', 'Amberfin02_In_Progress', 'Amberfin02 In Progress', 'BATON In_Progress',
                    'BATON In Progress', 'Export In_Progress', 'Export In Progress', 'Buddy Check In_Progress',
                    'Buddy Check In Progress', 'Need Buddy Check', 'In Review']
        if sobj.get('status') in statuses + ['Completed'] and old_status not in statuses:
            # Update the actual start date if they just set the status to 'In Progress'
            if sobj.get('actual_start_date') in ['', None]:
                now_timestamp = make_timestamp()
                server.update(sk, {'actual_start_date': now_timestamp, 'flag_future_changes': True})
        if sobj.get('status') in ['Ready', 'In_Progress', 'In Progress', 'In Review'] and 'WORK_ORDER' in sobj.get('lookup_code'):
            if title.get('client_status') != 'In Production':
                server.update(title.get('__search_key__'),
                              {'client_status': 'In Production', 'status': 'In Production'})
        elif sobj.get('status') in ['Rejected', 'Fix Needed'] and 'WORK_ORDER' in sobj.get('lookup_code'):
            from pyasm.biz import Note
            from pyasm.search import Search
            prod_error = {'error_type': sobj.get('status'), 'process': sobj.get('process'),
                          'work_order_code': sobj.get('lookup_code'), 'title': title.get('title'),
                          'episode': title.get('episode'), 'title_code': title.get('code'),
                          'order_code': order.get('code'), 'order_name': order.get('name'),
                          'po_number': order.get('po_number'), 'proj_code': proj.get('code'),
                          'scheduler_login': sobj.get('creator_login'), 'operator_login': user_name, 'login': user_name}
            server.insert('twog/production_error', prod_error, triggers=False)
            if sobj.get('status') == 'Rejected':
                server.update(title.get('__search_key__'), {'client_status': 'QC Rejected'})
                if title.get('priority_triggers') != 'No':
                    server.update(title.get('__search_key__'), {'priority': 90}, triggers=False)

        status_triggers = proj.get('status_triggers')
        if status_triggers in [None, '']:
            status_triggers = title.get('status_triggers')
        if sobj.get('status') == COMPLETE and status_triggers != 'No':
            # Now we need to set the next task(s) statuses to 'Ready'
            goes_to = sobj.get('goes_to').split('|^|')
            for gt in goes_to:
                if ',' not in gt:
                    continue

                next_task_code = gt.split(',')[1].replace('[', '').replace(']', '')
                nt_expr = "@SOBJECT(sthpw/task['code','{0}'])".format(next_task_code)
                next_task = server.eval(nt_expr)
                if next_task:
                    next_task = next_task[0]
                    if next_task.get('status') != 'Pending':
                        continue

                    if no_incompletes_preceding(next_task, task_code):
                        server.update(next_task.get('__search_key__'), {'status': READY})
                        if 'PROJ' not in next_task.get('lookup_code'):
                            continue

                        oip = next_task.get('order_in_pipe')
                        if oip in [None, '', 0]:
                            oip = 1
                        else:
                            oip = int(oip)
                        smallest_wo = (oip * 1000) + 10
                        nwt_expr = "@GET(twog/work_order['proj_code','{0}']['order_in_pipe','<=','{1}'].WT:sthpw/task['status','Pending']['@ORDER_BY','order_in_pipe desc'].__search_key__)"
                        task_search_keys = server.eval(nwt_expr.format(next_task.get('lookup_code'), smallest_wo))
                        task_update_data = dict.fromkeys(task_search_keys, {'status': READY})
                        server.update_multiple(task_update_data, triggers=False)

        # Now see if all wos under proj or all projs under title are completed.
        # If so, make their parent's status completed
        prj = None
        if new_status not in [COMPLETE, PENDING]:
            return

        if 'WORK_ORDER' in this_lookup:
            wo = server.eval("@SOBJECT(twog/work_order['code','{0}'])".format(sobj.get('lookup_code')))
            wo = wo[0]
            other_wotasks_expr = "@SOBJECT(twog/proj['code','{0}'].twog/work_order.WT:sthpw/task)".format(wo.get('proj_code'))
            other_wo_tasks = server.eval(other_wotasks_expr)
            all_wos_completed = True
            all_wos_pending = True
            if new_status == PENDING:
                all_wos_completed = False
            elif new_status == COMPLETE:
                all_wos_pending = False
            un_indie = False
            if sobj.get('indie_bigboard') in [True, 'true', 't', 'T', 1]:
                un_indie = True
            for owt in other_wo_tasks:
                if owt.get('lookup_code') != wo.get('code'):
                    if owt.get('status') != COMPLETE:
                        all_wos_completed = False
                    if owt.get('status') != PENDING:
                        all_wos_pending = False
                    if owt.get('indie_bigboard') in [True, 'true', 't', 'T', 1] and (owt.get('assigned_login_group') == sobj.get('assigned_login_group')):
                        un_indie = False
            # HERE NEED TO DETERMINE WHICH DEPT THIS WAS FOR AND SEE IF ANY OTHER WOs
            # IN THE SAME DEPT ARE STILL INDIE. IF NOT, THEN TAKE THE DEPT NAME OUT OF
            # active_dept_priorities ON THE TITLE
            if un_indie:
                that_dept = sobj.get('assigned_login_group').replace(' supervisor', '')
                adps = title.get('active_dept_priorities')
                adps = adps.replace(',%s' % that_dept, '').replace('%s,' % that_dept, '').replace(that_dept, '')
                indie_data = {'active_dept_priorities': adps}
                prio_name = '%s_priority' % that_dept.replace(' ', '_')
                indie_data[prio_name] = title.get('priority')
                server.update(title.get('__search_key__'), indie_data)
            prj = server.eval("@SOBJECT(twog/proj['code','{0}'])".format(wo.get('proj_code')))
            prj = prj[0] if prj else None
            if (all_wos_completed or all_wos_pending) and prj not in [None, '']:
                prj_task = server.eval("@SOBJECT(sthpw/task['lookup_code','{0}'])".format(prj.get('code')))
                if prj_task:
                    server.update(prj_task[0].get('__search_key__'), {'status': new_status})
        elif 'PROJ' in this_lookup:
            prj = server.eval("@SOBJECT(twog/proj['code','{0}'])".format(this_lookup))
            prj = prj[0] if prj else None

        all_projs_completed = True
        all_projs_pending = True
        all_titles_completed = False
        all_titles_pending = False
        if prj in [None, '']:
            return

        title_proj_tasks = server.eval("@SOBJECT(twog/title['code','{0}'].twog/proj.PT:sthpw/task)".format(prj.get('title_code')))
        for tpt in title_proj_tasks:
            if tpt.get('status') != COMPLETE:
                all_projs_completed = False
            if tpt.get('status') != PENDING:
                all_projs_pending = False
        title_updated = False
        if all_projs_completed:
            title_sk = server.build_search_key('twog/title', prj.get('title_code'))
            server.update(title_sk, {'status': COMPLETE, 'client_status': COMPLETE,
                                     'bigboard': False, 'priority': 5000})
            titles_completed = order.get('titles_completed')
            title_codes_completed = order.get('title_codes_completed')
            if title.get('code') not in title_codes_completed:
                if titles_completed in [None, '']:
                    titles_completed = 0
                else:
                    titles_completed = int(titles_completed)
                titles_completed += 1
                if title_codes_completed == '':
                    title_codes_completed = title.get('code')
                else:
                    title_codes_completed = '%s,%s' % (title_codes_completed, title.get('code'))
                server.update(order.get('__search_key__'), {'titles_completed': titles_completed,
                                                            'title_codes_completed': title_codes_completed})
                title_updated = True
            all_titles_completed = True
            title = server.eval("@SOBJECT(twog/title['code','{0}'])".format(prj.get('title_code')))
            if title and title_updated:
                title = title[0]
                other_titles = server.eval("@SOBJECT(twog/order['code','{0}'].twog/title)".format(title.get('order_code')))
                for ot in other_titles:
                    if title.get('code') != ot.get('code') and ot.get('status') != COMPLETE:
                        all_titles_completed = False
                        break
            else:
                all_titles_completed = False

        if all_projs_pending:
            title_sk = server.build_search_key('twog/title', prj.get('title_code'))
            if title.get('priority_triggers') != 'No' and title.get('status_triggers') != 'No':
                server.update(title_sk, {'status': '', 'bigboard': False})
                title_codes_completed = order.get('title_codes_completed')
                if title.get('code') in title_codes_completed:
                    title_codes_completed = title_codes_completed.replace(',%s' % title.get('code'), '').replace('%s,' % title.get('code'), '').replace('%s' % title.get('code'), '')
                    titles_completed = order.get('titles_completed')
                    if titles_completed in [None, '']:
                        titles_completed = 0
                    else:
                        titles_completed = int(titles_completed) - 1
                    server.update(order.get('__search_key__'), {'titles_completed': titles_completed,
                                                                'title_codes_completed': title_codes_completed})
                title_updated = True
            all_titles_pending = True
            title = server.eval("@SOBJECT(twog/title['code','{0}'])".format(prj.get('title_code')))
            if title and title_updated:
                title = title[0]
                other_titles = server.eval("@SOBJECT(twog/order['code','{0}'].twog/title)".format(title.get('order_code')))
                for ot in other_titles:
                    if title.get('code') != ot.get('code') and ot.get('status') != '':
                        all_titles_pending = False
                        break
            else:
                all_titles_pending = False

        if all_titles_pending:
            server.update(server.build_search_key('twog/order', title.get('order_code')),
                          {'needs_completion_review': False})
        if all_titles_completed:
            server.update(server.build_search_key('twog/order', title.get('order_code')),
                          {'needs_completion_review': True})

    except AttributeError as e:
        traceback.print_exc()
        print str(e) + '\nMost likely the server object does not exist.'
        raise e
    except KeyError as e:
        traceback.print_exc()
        print str(e) + '\nMost likely the input dictionary does not exist.'
        raise e
    except Exception as e:
        traceback.print_exc()
        print str(e)
        raise e
def main(server=None, input=None):
    """
    The main function of the custom script. The entire script was copied
    and pasted into the body of the try statement in order to add some
    error handling. It's all legacy code, so edit with caution.

    :param server: the TacticServerStub object
    :param input: a dict with data like like search_key, search_type, sobject, and update_data
    :return: None
    """
    if not input:
        input = {}

    try:
        # CUSTOM_SCRIPT00101
        def make_timestamp():
            from pyasm.common import SPTDate
            #Makes a Timestamp for postgres
            import datetime
            now = SPTDate.convert_to_local(datetime.datetime.now())
            return now
        
        sobject = input.get('sobject')
        update_data = input.get('update_data')
        sk = sobject.get('__search_key__')
        if 'is_external_rejection' in update_data.keys():
            from pyasm.biz import Note
            from pyasm.search import Search
            title_name = sobject.get('title')
            if sobject.get('episode') not in [None,'']:
                title_name = '%s: %s' % (title_name, sobject.get('episode'))
            title_obj = Search.get_by_search_key(sk) #Need this kind of object to make the note we'll be sending
            is_external_rejection = update_data.get('is_external_rejection')
            if is_external_rejection == 'true':
                non_rejected_titles = server.eval("@SOBJECT(twog/title['bigboard','True']['is_external_rejection','false']['status','!=','Completed']['@ORDER_BY','priority asc'])")
                smaller = .05
                if len(non_rejected_titles) > 0:
                    smallest_prio = non_rejected_titles[0].get('priority')
                    smaller = float(float(smallest_prio)/2) 
                el_timeo = make_timestamp()
                #Set priority to something smaller than all non-externally-rejected titles on the bigboard
                #Set due date and deliver by date to today's date
                #Set bigboard to true and put all WOs on bigboard
                server.update(sk, {'priority': smaller, 'bigboard': True, 'due_date': el_timeo, 'expected_delivery_date': el_timeo})
                all_tasks = server.eval("@SOBJECT(sthpw/task['title_code','%s'])" % sobject.get('code'))
                for task in all_tasks:
                    server.update(task.get('__search_key__'), {'bigboard': True}, triggers=False)
                #Now make the note
                note = "%s (%s) was rejected externally.\nThis title has been put on the bigboard and it's due & expected delivery dates have been set to today.\nPlease do all you can to get this title back out to the client by the end of the day.\n\nReason provided for External Rejection: %s\n\nOrder Code = %s\nTitle Code = %s" % (title_name, sobject.get('code'), sobject.get('external_rejection_reason'), sobject.get('order_code'), sobject.get('code')) 
                note2 = Note.create(title_obj, note, context='Received External Rejection', process='Received External Rejection')
                sources_str = ''
                source_links = server.eval("@SOBJECT(twog/title_origin['title_code','%s'])" % title_obj.get_code())
                for s in source_links:
                    source = server.eval("@SOBJECT(twog/source['code','%s'])" % s.get('source_code'))
                    if source:
                        source = source[0]
                        source_fn = source.get('title')
                        if source.get('episode') not in [None,'']:
                            source_fn = '%s: %s' % (source_fn, source.get('episode'))
                        if sources_str == '':
                            sources_str = '%s (%s) Barcode: %s' % (source.get('code'), source_fn, source.get('barcode'))
                        else:
                            sources_str = '%s\n%s (%s) Barcode: %s' % (sources_str, source.get('code'), source_fn, source.get('barcode'))
                server.insert('twog/external_rejection', {'order_code': title_obj.get_value('order_code'), 'order_name': title_obj.get_value('order_name'), 'status': 'Open', 'reported_issue': sobject.get('external_rejection_reason'), 'title_code': title_obj.get_code(), 'scheduler_reason': sobject.get('external_rejection_reason'), 'title': title_obj.get_value('title'), 'episode': title_obj.get_value('episode'), 'po_number': title_obj.get('po_number'), 'email_list': '', 'sources': sources_str})
            else:
                #DO THE OPPOSITE AS ABOVE
                saved_priority = sobject.get('saved_priority')
                server.update(sk, {'bigboard': False, 'priority': saved_priority})
                note = "%s (%s) had been marked as rejected externally, but this may have been in error. It is no longer marked as rejected externally.\nThis title has been removed from the bigboard, but it's due & expected delivery dates may still be set to today's date (might need to be addressed).\nOrder Code = %s\nTitle Code = %s" % (title_name, sobject.get('code'), sobject.get('order_code'), sobject.get('code')) 
                note2 = Note.create(title_obj, note, context='External Rejection Mark Removed', process='External Rejection Mark Removed')
    except AttributeError as e:
        traceback.print_exc()
        print str(e) + '\nMost likely the server object does not exist.'
        raise e
    except KeyError as e:
        traceback.print_exc()
        print str(e) + '\nMost likely the input dictionary does not exist.'
        raise e
    except Exception as e:
        traceback.print_exc()
        print str(e)
        raise e
def main(server=None, input=None):
    """
    The main function of the custom script. The entire script was copied
    and pasted into the body of the try statement in order to add some
    error handling. It's all legacy code, so edit with caution.

    :param server: the TacticServerStub object
    :param input: a dict with data like like search_key, search_type, sobject, and update_data
    :return: None
    """
    if not input:
        input = {}

    try:
        # CUSTOM_SCRIPT00078
        from pyasm.common import Environment
        from pyasm.biz import Note
        from pyasm.search import Search
        import common_tools.utils as ctu
        login = Environment.get_login()
        user_name = login.get_login()
        delim = '#Xs*'
        all_ccs = '[email protected]%[email protected]' % delim
        #This is for production_error operator_description update
        sobject = input.get('sobject')
        operator_description = sobject.get('operator_description')
        title_code = sobject.get('title_code')
        wo_code = sobject.get('work_order_code')
        title_id_pre = title_code.split('TITLE')[1]
        found_non_zero = False
        title_id = ''
        note = ''
        for ch in title_id_pre:
            if ch != '0':
                found_non_zero = True
            if ch == '0' and found_non_zero or (ch != '0'):
                title_id = '%s%s' % (title_id, ch)
        wo_code = sobject.get('work_order_code')
        expr = "@SOBJECT(sthpw/note['search_id','%s']['search_type','~','twog/title']['process','QC Rejected']['@ORDER_BY','timestamp desc'])" % (title_id)
        last_note = server.eval(expr)
        if last_note:
            last_note = last_note[0]
            # Now just need to update it with the operator description, wo code and title
            note = last_note.get('note')
            note = '%s\n%s' % (note, operator_description)
            server.update(last_note.get('__search_key__'), {'note': note}, triggers=False)
            wo_obj2 = Search.get_by_search_key(server.build_search_key('twog/work_order',wo_code))   #This is the type of object required for Note creation
            note2 = Note.create(wo_obj2, note, context='QC Rejected', process='QC Rejected')
        
        
        wo = server.eval("@SOBJECT(twog/work_order['code','%s'])" % wo_code)[0]
        proj = server.eval("@SOBJECT(twog/proj['code','%s'])" % wo.get('proj_code'))[0]
        title = server.eval("@SOBJECT(twog/title['code','%s'])" % proj.get('title_code'))[0]
        order = server.eval("@SOBJECT(twog/order['code','%s'])" % title.get('order_code'))[0]
        scheduler_name = order.get('login')
        scheduler = server.eval("@SOBJECT(sthpw/login['login','%s']['location','internal'])" % scheduler_name)
        if scheduler:
            scheduler = scheduler[0]
            all_ccs = '%s%s%s' % (all_ccs, delim, scheduler.get('email'))
            
        group = ''
        process = ''
        client_name = ''
        po_number = order.get('po_number')
        order_name = order.get('name')
        title_name = title.get('title')
        episode = title.get('episode')
        if wo:
            group = wo.get('work_group')
            process = wo.get('process')
            client_name = wo.get('client_name')
        error_type = sobject.get('error_type')
        rejection_cause = sobject.get('rejection_cause')
        time_spent = sobject.get('time_spent')
        client_description = sobject.get('client_description')
        client_description = client_description.replace('\t','        ')
        client_description = client_description.replace('\n','<br/>')
        client_description = client_description.replace('  ', '  ')
        operator_description = operator_description.replace('\t','        ')
        operator_description = operator_description.replace('\n','<br/>')
        operator_description = operator_description.replace('  ', '  ')
        action_taken = sobject.get('action_taken')

        order_builder_url = ctu.get_order_builder_url(order.get('code'), server)
        href = '<a href="{0}">{1}</a>'
        order_hyperlink = href.format(order_builder_url, order_name)

        title_row = ''
        proj_row = ''
        if title:
            full_title = title.get('title')
            if title.get('episode') not in [None,'']:
                full_title = '%s: %s' % (full_title, title.get('episode'))
            title_row = "<tr><td align='left' style='color: #06C; font-size: 16px;'>Title: <strong>%s</strong> | Title Code: <strong>%s</strong></td></tr>" % (full_title, title.get('code')) 
        if proj:
            proj_row = "<tr><td align='left' style='color: #06C; font-size: 16px;'>Project: <strong>%s</strong> | Project Code: <strong>%s</strong></td></tr>" % (proj.get('process'), proj.get('code'))
        template_path = '/opt/spt/custom/formatted_emailer/error_msg.html'
        filled_in_path = '/var/www/html/formatted_emails/error_msg_%s.html' % wo_code
        template = open(template_path, 'r')
        filled = ''
        for line in template:
            line = line.replace('[WORK_ORDER_CODE]', wo_code)
            line = line.replace('[TITLE_CODE]', title.get('code'))
            line = line.replace('[PROJ_CODE]', proj.get('code'))
            line = line.replace('[TITLE_ROW]', title_row)
            line = line.replace('[PROJ_ROW]', proj_row)
            line = line.replace('[ORDER_CODE]', order.get('code'))
            line = line.replace('[LOGIN]', user_name)
            line = line.replace('[GROUP]', group)
            line = line.replace('[PROCESS]', process)
            line = line.replace('[CLIENT_NAME]', client_name)
            line = line.replace('[PO_NUMBER]', po_number)
            line = line.replace('[ORDER_NAME]', order_hyperlink)
            line = line.replace('[TITLE]', title_name)
            line = line.replace('[EPISODE]', episode)
            line = line.replace('[ERROR_TYPE]', error_type)
            line = line.replace('[REJECTION_CAUSE]', rejection_cause)
            line = line.replace('[TIME_SPENT]', time_spent)
            line = line.replace('[CLIENT_DESCRIPTION]', client_description)
            line = line.replace('[OPERATOR_DESCRIPTION]', operator_description)
            line = line.replace('[ACTION_TAKEN]', action_taken)
            filled = '%s%s' % (filled, line)
        template.close()
        filler = open(filled_in_path, 'w')
        filler.write(filled)
        filler.close()
        server.insert('twog/bundled_message', {'filled_in_path': filled_in_path, 'message': 'New Error', 'from_email': '*****@*****.**', 'to_email': '*****@*****.**', 'from_name': 'Tech Alert', 'subject': 'Error: %s, %s, %s: %s' % (wo_code, po_number, title_name, episode), 'all_ccs': all_ccs, 'object_code': wo_code})
    except AttributeError as e:
        traceback.print_exc()
        print str(e) + '\nMost likely the server object does not exist.'
        raise e
    except KeyError as e:
        traceback.print_exc()
        print str(e) + '\nMost likely the input dictionary does not exist.'
        raise e
    except Exception as e:
        traceback.print_exc()
        print str(e)
        raise e
Exemple #11
0
def main(server=None, input=None):
    """
    The main function of the custom script. The entire script was copied
    and pasted into the body of the try statement in order to add some
    error handling. It's all legacy code, so edit with caution.

    :param server: the TacticServerStub object
    :param input: a dict with data like like search_key, search_type, sobject, and update_data
    :return: None
    """
    if not input:
        input = {}

    try:
        # CUSTOM_SCRIPT00091
        #
        # Created by Matthew Misenhimer
        #
        def make_timestamp():
            from pyasm.common import SPTDate
            #Makes a Timestamp for postgres
            import datetime
            now = SPTDate.convert_to_local(datetime.datetime.now())
            return now
        
        def no_incompletes_preceding(new_sob, initial_sob_code):
            comes_from = new_sob.get('comes_from').split('|^|')
            ret_val = True
            for c in comes_from:
                if initial_sob_code not in c:
                    task_code = c.split(',')[1]
                    task_code = task_code.replace(']','').replace('[','')
                    task_status = server.eval("@GET(sthpw/task['code','%s'].status)" % task_code)[0]
                    if task_status != 'Completed':
                        ret_val = False
                        return ret_val
            return ret_val
        
        from pyasm.common import TacticException, Environment
        # input and server are assumed variables
        # define some contants here
        #print "\n\nIN KICKOFF input = %s" % input
        COMPLETE = 'Completed'
        READY = 'Ready'
        PENDING = 'Pending'
        sobj = input.get('sobject')
        this_process = sobj.get('process')
        this_lookup = sobj.get('lookup_code')
        sk = input.get('search_key')
        task_code = sobj.get('code')
        update_data = input.get('update_data') #These are the new values
        #print "UPDATE DATA = %s" % update_data
        prev_data = {}
        old_status = ''
        if 'prev_data' in input.keys():
            prev_data = input.get('prev_data') #These are the old values
            if 'status' in prev_data.keys():
                old_status = prev_data.get('status')
        new_status = update_data.get('status')
        login = Environment.get_login()
        user_name = login.get_login()
        assigned_login_group = sobj.get('assigned_login_group')
        #print "STATUS = %s, ALG = %s" % (new_status, assigned_login_group)
        parent_obj = None
        proj = None
        title = None
        order = None
        if 'PROJ' in this_lookup:
            parent_obj = server.eval("@SOBJECT(twog/proj['code','%s'])" % this_lookup)[0] #Parent Obj is the Proj attached to the task
            proj = parent_obj
            title = server.eval("@SOBJECT(twog/title['code','%s'])" % parent_obj.get('title_code'))[0]
            order = server.eval("@SOBJECT(twog/order['code','%s'])" % title.get('order_code'))[0] 
        elif 'WORK_ORDER' in this_lookup:
            parent_obj = server.eval("@SOBJECT(twog/work_order['code','%s'])" % this_lookup)[0] #Parent Obj is the Work Order attached to the task
            work_order = parent_obj
            proj = server.eval("@SOBJECT(twog/proj['code','%s'])" % work_order.get('proj_code'))[0]
            title = server.eval("@SOBJECT(twog/title['code','%s'])" % proj.get('title_code'))[0] 
            order = server.eval("@SOBJECT(twog/order['code','%s'])" % title.get('order_code'))[0] 
        #print "PARENT = %s" % parent_obj
        #print "TITLE = %s" % title
        #print "ORDER = %s" % order
        if 'PROJ' in this_lookup and title.get('priority_triggers') != 'No':
            #TURNING THIS OFF FOR NOW, PER NEW SOLUTIONS AND CONVERSATION WITH SCHEDULERS
            #If the new status for this Proj is ready, then grab the priority attached to he proj and give it to the Title
            #This is to control priority order per department
            #if new_status == 'Ready':
            #    server.update(title.get('__search_key__'), {'priority': parent_obj.get('priority')}, triggers=False)
            nothing = 1
        elif 'WORK_ORDER' in this_lookup:
            #TURNING THIS OFF FOR NOW, PER NEW SOLUTIONS AND CONVERSATION WITH SCHEDULERS
            #status_triggers = proj.get('status_triggers')
            #if status_triggers in [None,'']:
            #    status_triggers = title.get('status_triggers')
            #if status_triggers == 'No' and status_triggers == 'Yes' and new_status == READY:
            #    pprio = 0
            #    if proj.get('priority') not in [None,'']:
            #        pprio = proj.get('priority')
            #    server.update(title.get('__search_key__'), {'priority': pprio}, triggers=False)
            nothing = 1
            if new_status == COMPLETE:
                #print "NEW STATUS COMPLETE 1"
                #Make sure they have set the assigned person to the work order.
                if sobj.get('assigned') in [None,'']:
                    raise TacticException('Before completing a work order, someone must be assigned to it.')
                #Make sure they have added work hours. If not, error out.
                whs_expr = "@SOBJECT(sthpw/work_hour['task_code','%s'])" % task_code
                whs = server.eval(whs_expr)
                sum = 0
                for wh in whs:
                    straight_time = wh.get('straight_time')
                    if straight_time in [None,'']:
                        straight_time = 0
                    else:
                        straight_time = float(straight_time)
                    sum = float(sum) + straight_time
                    sum = str(sum)
                if sum in ['0','',0,0.0]:
                    raise TacticException('You need to save the hours you worked on this before you can set the status to "Completed".')
                #print "SUM = %s" % sum
            t_wo_completed = title.get('wo_completed') #This is for the completion ratio on title
            o_wo_completed = order.get('wo_completed') #This is for the completion ratio on order
            if new_status == COMPLETE:
                #print "NEW STATUS COMPLETE 2"
                title_str = title.get('title') #This is for a potential alert/exception
                if title.get('episode') not in [None,'']:
                    title_str = '%s: %s' % (title_str, title.get('episode'))
                #Block QC and Edel from completing their work orders if the TRT or TRT w/Textless are not filled in
                if 'qc' in assigned_login_group or 'edeliveries' in assigned_login_group:
                    total_program_runtime = title.get('total_program_runtime')
                    total_runtime_w_textless = title.get('total_runtime_w_textless')
                    say_str = ''
                    say_str2 = ''
                    if total_program_runtime in [None,''] or total_runtime_w_textless in [None,'']:
                        if total_program_runtime in [None,'']:
                            say_str = 'Total Program Runtime has' 
                        if total_runtime_w_textless in [None,'']:
                            if say_str == '': 
                                say_str = 'Total Runtime With Textless has'
                            else:
                                say_str = '%s and Total Runtime With Textless have' % (say_str[:-4])  
                        say_str2 = "%s (%s)'s %s not been filled. You must enter this data before trying to complete this work order." % (title_str, title.get('code'), say_str)
                    if 'qc' in assigned_login_group:
                        if total_program_runtime in [None,''] or total_runtime_w_textless in [None,'']:
                            raise TacticException(say_str2)
                        else:
                            #They were filled in, so finish completing the task and send a note
                            from pyasm.biz import Note
                            from pyasm.search import Search
                            title_obj2 = Search.get_by_search_key(title.get('__search_key__')) #This is the type of object required for Note creation
                            note_text = '%s (%s) has been Passed and Completed by %s in QC' % (sobj.get('process'), this_lookup, user_name)
                            note = Note.create(title_obj2, note_text, context='QC Completed', process='QC Completed')
                    elif 'edeliveries' in assigned_login_group and (total_program_runtime in [None,''] or total_runtime_w_textless in [None,'']):
                        raise TacticException(say_str2)
                #This section is turned off due to logistical problems with it. 
                #It intended to block machine room, edit, and compression from completing a work order unless the pulled_blacks had been filled out.
                #if 'machine_room' in assigned_login_group or 'edit' in assigned_login_group or 'compression' in assigned_login_group:
                #    pulled_blacks = title.get('pulled_blacks')
                #    if pulled_blacks in [None,'','0']:
                #        raise TacticException("%s (%s)'s pulled_blacks has not been filled, or is still '0'." % (title_str, title.get('code'))) 
                t_wo_completed = t_wo_completed + 1
                o_wo_completed = o_wo_completed + 1
                #print "T WO COMPLETED = %s" % t_wo_completed
                #print "O WO COMPLETED = %s" % o_wo_completed
                #Update the completion ratios attached, since there were no blocking exceptions 
                server.update(title.get('__search_key__'), {'wo_completed': t_wo_completed})
                server.update(order.get('__search_key__'), {'wo_completed': o_wo_completed})
            elif old_status == COMPLETE:
                t_wo_completed = t_wo_completed - 1
                o_wo_completed = o_wo_completed - 1
                #Reduce the completion ratio, since it was completed but has now been taken off that status
                server.update(title.get('__search_key__'), {'wo_completed': t_wo_completed})
                server.update(order.get('__search_key__'), {'wo_completed': o_wo_completed})
        
        now_timestamp = make_timestamp() 
        #Since there have been no blocking exceptions, record the status change
        stat_log_dict =  {'login': user_name, 'timestamp': now_timestamp, 'from_status': old_status, 'status': new_status, 'task_code': task_code, 'lookup_code': this_lookup, 'order_code': sobj.get('order_code'), 'title_code': sobj.get('title_code'), 'process': this_process}
        #print "GOING TO INSERT INTO STATUS LOG = %s" % stat_log_dict
        server.insert('twog/status_log', stat_log_dict)
        if new_status == COMPLETE:
            #print "NEW STATUS COMPLETE 3"
            #Record the completion date on the work order, and take it off the BigBoard
            updict = {'actual_end_date': make_timestamp()}
            do_indie = False
            if 'WORK_ORDER' in this_lookup:
                updict['bigboard'] = False
                if sobj.get('indie_bigboard') in [True,'true','t','T',1]: 
                    updict['indie_bigboard'] = False
                    do_indie = True
            #print "REMOVING BIGBOARD..."
            server.update(sk, updict)
            if do_indie:
                indies = server.eval("@SOBJECT(twog/indie_bigboard['task_code','%s'])" % task_code)
                for indie in indies:
                    indie_dict =  {'indie_bigboard': False}
                    if indie.get('removal_login') in [None,'']:
                        indie_dict['removal_login'] =  user_name
                    if indie.get('removal_login') in [None,'']:
                        indie_dict['removal_timestamp'] = now_timestamp 
                    server.update(indie.get('__search_key__'), indie_dict) 
        elif new_status not in ['Pending','Ready','Completed'] and 'WORK_ORDER' in this_lookup:
            server.update(server.build_search_key('sthpw/task', proj.get('task_code')), {'status': new_status})        #NEW
        if 'PROJ' in sobj.get('lookup_code'):
            #MTM: This annoying section is for passing Proj's their task's status.
            #I don't know if this is needed at all anymore. Will have to check other triggers and reports.
            #The "tripwire" stuff was just to keep it from infinitely passing statuses from proj to task, task to proj
            do_it = True
            if 'tripwire' in update_data.keys():
                if update_data.get('tripwire') == 'No Send Back': #?
                    do_it = False
                    server.update(input.get('search_key'), {'tripwire': ''}, triggers=False) #Empty the tripwire and do nothing
                    server.update(proj.get('__search_key__'), {'tripwire': '', 'status': sobj.get('status')}, triggers=False) #?
            if do_it:
                if proj:
                    server.update(proj.get('__search_key__'), {'status': new_status})
        if title.get('priority_triggers') != 'No':
            #print "IN TITLE PRIORITY TRIGGERS ON"
            #Update Title Priority for On Hold Status, or having that status removed -- BEGIN
            if sobj.get('status') in ['On_Hold','On Hold']:
                title_priority = title.get('priority')
                server.update(title.get('__search_key__'), {'saved_priority': title_priority, 'priority': 200}, triggers=False)    
            else:
                if old_status in ['On_Hold','On Hold']:
                    saved_priority = title.get('saved_priority')
                    server.update(title.get('__search_key__'), {'priority': saved_priority}, triggers=False)    
            #Update Title Priority for On Hold Status, or having that status removed -- END
        
            #Update Title Priority for Client Response Status, or having that status removed -- BEGIN
            if sobj.get('status') == 'Client Response':
                title_priority = title.get('priority')
                crc = title.get('client_response_count')
                crc_num = 0
                if crc not in [None,'']:
                    crc_num = int(crc)
                crc_num = crc_num + 1        
                server.update(title.get('__search_key__'), {'saved_priority': title_priority, 'priority': 300, 'client_response_count': crc_num}, triggers=False)    
            else:
                if old_status == 'Client Response':
                    saved_priority = title.get('saved_priority')
                    crc = title.get('client_response_count')
                    crc_num = 0
                    if crc not in [None,'']:
                        crc_num = int(crc)
                    if crc_num > 0:
                        crc_num = crc_num - 1        
                    server.update(title.get('__search_key__'), {'priority': saved_priority, 'client_response_count': crc_num}, triggers=False)    
            #Update Title Priority for Client Response Status, or having that status removed -- END
        #print "HERE 0"
        if sobj.get('status') in ['In_Progress','In Progress','DR In_Progress','DR In Progress', 'Amberfin01_In_Progress','Amberfin01 In Progress', 'Amberfin02_In_Progress','Amberfin02 In Progress','BATON In_Progress','BATON In Progress','Export In_Progress','Export In Progress','Buddy Check In_Progress','Buddy Check In Progress','Need Buddy Check','Completed','In Review'] and old_status not in ['In_Progress','DR In_Progress','DR In Progress','Amberfin01_In_Progress','Amberfin01 In Progress', 'Amberfin02_In_Progress','Amberfin02 In Progress', 'BATON In_Progress','BATON In Progress','Export In_Progress','Export In Progress','Buddy Check In_Progress','Buddy Check In Progress','Need Buddy Check','In Progress','In Review']:
            #Update the actual start date if they just set the status to 'In Progress'
            if sobj.get('actual_start_date') in ['',None]:
                now_timestamp = make_timestamp() 
                server.update(sk, {'actual_start_date': now_timestamp, 'flag_future_changes': True})
        if sobj.get('status') in ['Ready','In_Progress','In Progress','In Review'] and 'WORK_ORDER' in sobj.get('lookup_code'):
            if title.get('client_status') != 'In Production':
                server.update(title.get('__search_key__'), {'client_status': 'In Production', 'status': 'In Production'})
        elif sobj.get('status') in ['Rejected','Fix Needed'] and 'WORK_ORDER' in sobj.get('lookup_code'):
            from pyasm.biz import Note
            from pyasm.search import Search
            server.insert('twog/production_error', {'error_type': sobj.get('status'), 'process': sobj.get('process'), 'work_order_code': sobj.get('lookup_code'), 'title': title.get('title'), 'episode': title.get('episode'), 'title_code': title.get('code'), 'order_code': order.get('code'), 'order_name': order.get('name'), 'po_number': order.get('po_number'), 'proj_code': proj.get('code'), 'scheduler_login': sobj.get('creator_login'), 'operator_login': user_name, 'login': user_name}, triggers=False) 
            if sobj.get('status') == 'Rejected':
                server.update(title.get('__search_key__'), {'client_status': 'QC Rejected'})
                if title.get('priority_triggers') != 'No':
                    server.update(title.get('__search_key__'), {'priority': 90}, triggers=False)
                #title_obj2 = Search.get_by_search_key(title.get('__search_key__'))   #This is the type of object required for Note creation
                #note_text = '%s (%s) has been Rejected, as marked by %s' % (sobj.get('process'), this_lookup, user_name)
                #note = Note.create(title_obj2, note_text, context='QC Rejected', process='QC Rejected', triggers=False)
        
        status_triggers = proj.get('status_triggers')
        if status_triggers in [None,'']:
            status_triggers = title.get('status_triggers')
        if sobj.get('status') == COMPLETE and status_triggers != 'No':
            # Now we need to set the next task(s) statuses to 'Ready'
            ready = True # Took out the checks to this WO's input WOs
            # make the next processes ready
            #print "STATUS TRIGGERS ON, STATUS = COMPLETE"
            if ready == True:
                goes_to = sobj.get('goes_to').split('|^|')
                #print "GOES TO = %s" % goes_to
                for gt in goes_to:
                    next_task_code = ''
                    next_task_code_split = gt.split(',')
                    if len(next_task_code_split) > 1:
                        next_task_code = next_task_code_split[1]
                        next_task_code = next_task_code.replace('[','').replace(']','')
                        nt_expr = "@SOBJECT(sthpw/task['code','%s'])" % next_task_code
                        next_task = server.eval(nt_expr)
                        #print "NEXT TASK = %s" % next_task
                        if next_task:
                            next_task = next_task[0]
                            if next_task.get('status') == 'Pending':
                                if no_incompletes_preceding(next_task, task_code):
                                    server.update(next_task.get('__search_key__'), {'status': READY})
                                    if 'PROJ' in next_task.get('lookup_code'):
                                        oip = next_task.get('order_in_pipe')
                                        if oip in [None,'',0]:
                                            oip = 1
                                        else:
                                            oip = int(oip)
                                        smallest_wo = (oip * 1000) + 10
                                        nwt_expr = "@SOBJECT(twog/work_order['proj_code','%s']['order_in_pipe','<=','%s'].WT:sthpw/task['status','Pending']['@ORDER_BY','order_in_pipe desc'])" % (next_task.get('lookup_code'), smallest_wo)
                                        next_wo_tasks = server.eval(nwt_expr)
                                        for nwo in next_wo_tasks:
                                            #print "MAKING %s READY" % nwo.get('__search_key__')
                                            server.update(nwo.get('__search_key__'), {'status': READY}, triggers=False)
                
        # Now see if all wos under proj or all projs under title are completed. If so, make their parent's status completed
        all_wos_completed = False
        all_wos_pending = False
        prj = None
        if new_status in [COMPLETE,PENDING]: 
            if 'WORK_ORDER' in this_lookup:
                #print "WORK ORDER IN LOOKUP"
                wo = server.eval("@SOBJECT(twog/work_order['code','%s'])" % sobj.get('lookup_code'))
                wo = wo[0]
                other_wotasks_expr = "@SOBJECT(twog/proj['code','%s'].twog/work_order.WT:sthpw/task)" % wo.get('proj_code')
                other_wo_tasks = server.eval(other_wotasks_expr)
                all_wos_completed = True
                all_wos_pending = True
                if new_status == PENDING:
                    all_wos_completed = False
                elif new_status == COMPLETE:
                    all_wos_pending = False
                un_indie = False
                if sobj.get('indie_bigboard') in [True,'true','t','T',1]:
                    un_indie = True
                for owt in other_wo_tasks:
                    if owt.get('lookup_code') != wo.get('code'):
                        if owt.get('status') != COMPLETE:
                            all_wos_completed = False
                        if owt.get('status') != PENDING:
                            all_wos_pending = False
                        if owt.get('indie_bigboard') in [True,'true','t','T',1] and (owt.get('assigned_login_group') == sobj.get('assigned_login_group')):
                            un_indie = False
                #HERE NEED TO DETERMINE WHICH DEPT THIS WAS FOR AND SEE IF ANY OTHER WOs
                #IN THE SAME DEPT ARE STILL INDIE. IF NOT, THEN TAKE THE DEPT NAME OUT OF 
                #active_dept_priorities ON THE TITLE
                if un_indie:
                    that_dept = sobj.get('assigned_login_group').replace(' supervisor','')
                    adps = title.get('active_dept_priorities')
                    adps = adps.replace(',%s' % that_dept, '').replace('%s,' % that_dept, '').replace(that_dept,'')
                    indie_data = {}
                    indie_data['active_dept_priorities'] = adps
                    prio_name = '%s_priority' % that_dept.replace(' ','_')
                    indie_data[prio_name] = title.get('priority')
                    server.update(title.get('__search_key__'), indie_data) 
                prj = server.eval("@SOBJECT(twog/proj['code','%s'])" % wo.get('proj_code'))
                if len(prj) > 0:
                    prj = prj[0]
                else:
                    prj = None
                if (all_wos_completed or all_wos_pending) and prj not in [None,'']:
                    prj_task = server.eval("@SOBJECT(sthpw/task['lookup_code','%s'])" % prj.get('code'))
                    if prj_task:
                        prj_task = prj_task[0]
                        server.update(prj_task.get('__search_key__'), {'status': new_status})
                #print "END OF WO IN LOOKUP"
            elif 'PROJ' in this_lookup:
                prj = server.eval("@SOBJECT(twog/proj['code','%s'])" % this_lookup)
                if prj:
                    prj = prj[0]
                else:
                    prj = None
        
            all_projs_completed = True
            all_projs_pending = True
            all_titles_completed = False
            all_titles_pending = False
            #print "HERE 1"
            if prj not in [None,'']:
                title_proj_tasks = server.eval("@SOBJECT(twog/title['code','%s'].twog/proj.PT:sthpw/task)" % prj.get('title_code'))
                for tpt in title_proj_tasks:
                    if tpt.get('status') != COMPLETE:
                        all_projs_completed = False
                    if tpt.get('status') != PENDING:
                        all_projs_pending = False
                title_updated = False
                if all_projs_completed:
                    title_sk = server.build_search_key('twog/title', prj.get('title_code'))
                    if 1:
                        server.update(title_sk, {'status': COMPLETE, 'client_status': COMPLETE, 'bigboard': False, 'priority': 5000})
                        titles_completed = order.get('titles_completed')
                        title_codes_completed = order.get('title_codes_completed')
                        if title.get('code') not in title_codes_completed:
                            if titles_completed in [None,'']:
                                titles_completed = 0
                            else:
                                titles_completed = int(titles_completed)
                            titles_completed = titles_completed + 1
                            if title_codes_completed == '':
                                title_codes_completed = title.get('code')
                            else:
                                title_codes_completed = '%s,%s' % (title_codes_completed, title.get('code'))
                            server.update(order.get('__search_key__'), {'titles_completed': titles_completed, 'title_codes_completed': title_codes_completed}) 
                        title_updated = True
                    all_titles_completed = True
                    title = server.eval("@SOBJECT(twog/title['code','%s'])" % prj.get('title_code'))
                    if title and title_updated:
                        title = title[0]
                        other_titles = server.eval("@SOBJECT(twog/order['code','%s'].twog/title)" % title.get('order_code'))
                        for ot in other_titles:
                            if title.get('code') != ot.get('code'):
                                if ot.get('status') != COMPLETE:
                                    all_titles_completed = False
                    else:
                        all_titles_completed = False
                #print "HERE 2"
                if all_projs_pending:
                    title_sk = server.build_search_key('twog/title', prj.get('title_code'))
                    if title.get('priority_triggers') != 'No' and title.get('status_triggers') != 'No':
                        server.update(title_sk, {'status': '', 'bigboard': False})
                        title_codes_completed = order.get('title_codes_completed')
                        if title.get('code') in title_codes_completed:
                            title_codes_completed = title_codes_completed.replace(',%s'  % title.get('code'),'').replace('%s,'  % title.get('code'),'').replace('%s'  % title.get('code'),'')
                            titles_completed = order.get('titles_completed')
                            if titles_completed in [None,'']:
                                titles_completed = 0
                            else:
                                titles_completed = int(titles_completed) - 1
                            server.update(order.get('__search_key__'), {'titles_completed': titles_completed, 'title_codes_completed': title_codes_completed})
                        title_updated = True
                    all_titles_pending = True
                    title = server.eval("@SOBJECT(twog/title['code','%s'])" % prj.get('title_code'))
                    if title and title_updated:
                        title = title[0]
                        other_titles = server.eval("@SOBJECT(twog/order['code','%s'].twog/title)" % title.get('order_code'))
                        for ot in other_titles:
                            if title.get('code') != ot.get('code'):
                                if ot.get('status') != '':
                                    all_titles_pending = False
                    else:
                        all_titles_pending = False
                #print "HERE 3"
            if all_titles_pending:
                server.update(server.build_search_key('twog/order', title.get('order_code')), {'needs_completion_review': False}) 
            if all_titles_completed:
                server.update(server.build_search_key('twog/order', title.get('order_code')), {'needs_completion_review': True}) 
                    
        #print "LEAVING KICKOFF"
    except AttributeError as e:
        traceback.print_exc()
        print str(e) + '\nMost likely the server object does not exist.'
        raise e
    except KeyError as e:
        traceback.print_exc()
        print str(e) + '\nMost likely the input dictionary does not exist.'
        raise e
    except Exception as e:
        traceback.print_exc()
        print str(e)
        raise e