Exemple #1
0
    def my_job_data(self):
        """dict: ``lists`` of ``Projects`` owned by the active user and
		organized by job number.
		
		Notes
		-----
		These ``Projects`` are no longer linked with their corresponding
		drawing numbers.

		"""
        return JobIO.sort_project_data(self.my_projects)
Exemple #2
0
	def _close(self, msg):
		"""Remove job files and send confirmation email.

		Parameters
		----------
		msg : list
			Document control message.
		
		"""
		if JobIO.clear_job_files(self._job_num):
			msg.append('Yes')
			send_email(self._to, [], '%s Completed' % self._job_num, 
				'<br>'.join(msg), True)
Exemple #3
0
    def my_projects(self):
        """dict: A collection of ``Projects`` owned by the active user and 
		organized by drawing number.

		"""
        my_projects = {}
        if self.my_name is None:
            my_projects

        existing_projects = JobIO.existing_projects()
        for project in existing_projects.keys():
            if existing_projects[project].owner == self.my_name:
                my_projects[project] = existing_projects[project]
        return my_projects
Exemple #4
0
	def _validate_job_num(self):
		"""Confirm that a job number is valid and does not already exist.

		Raises
		------
		JobNumberError
		ExistingJobError
		OSError

		"""
		if len(self._job_num) != 6:
			raise JobNumberError()
		elif JobIO.job_exists(self._job_num):
			raise ExistingJobError()
Exemple #5
0
    def process_complete_job_request(self, job_num, job=None, lock=None):
        """Process a request to remove job files from ``Nucleus``.
		
		Parameters
		----------
		job_num : str
			The 6-digit job number.

		job : Job or None
			A collection of work orders requesting completion.

		lock : GateKeeper or None
			Controls read and write access to `job` applicaton files.

		Returns
		-------
		True
			If `job` files were removed from ``Nucleus``.
		
		"""
        self.app_data.users.log('initiating a complete job request for %s' %
                                job_num)
        request = CompleteJobRequest(
            job_num, self.app_data.users.supervisor_email_addresses, job, lock)
        try:
            if not request.approved():
                self.app_data.users.log(
                    '%s complete job request was not approved' % job_num)
                return
        except (JobInUseError, IOError, EOFError, ProjectsFolderRootError,
                DestinationError) as error:
            self.app_data.users.log(error)
            ExceptionMessageBox(error).exec_()
        else:
            self.status.showMessage('Updating your jobs...')
            self.desk.refresh_home()

            # Log data to user file
            self.app_data.users.log('%s completed, due by %s' %
                                    (job_num, JobIO.job_due_date(job)))
            self.app_data.users.log('%s drawing count: %d' %
                                    (job_num, request.dwg_count))
            for project in request.projects:
                self.app_data.users.log('project:%s,%s' %
                                        (request.projects[project].alias_num,
                                         request.projects[project].owner))

            self.status.showMessage('%s closed successfully.' % job_num)
            return True
Exemple #6
0
    def _assign_job(self, job_num, df):
        """Create and update new job files.

		Parameters
		----------
		job_num : str

		df : DataFrame
			Contains information corresponding to `job_num` only.

		Raises
		------
		IOError
		JobNotFoundError
		JobInUseError
		EOFError

		"""
        JobIO.init_files(job_num, None)
        job, lock = JobIO.job_and_lock(job_num)
        for index, row in df.iterrows():
            self._transform_row_into_project(row, job)
        JobIO.save(job_num, job)
        lock.unlock()
Exemple #7
0
    def my_jobs_at_a_glance(self):
        """dict: ``dicts`` comprised of due date information for the active 
		user's projects organized by job number.

		Nested keys: 
		'expired' (past due), 'today' (due today), and 'approaching' 
		(due within 2 days). 
		
		Nested values (``int``): 
		The number of ``Projects`` whose due dates fall within the key category.

		"""
        # LEAD was introduced to provide the drafting lead with a glance at
        # all department projects, not just his/her own. LEAD is still
        # classified with a user level of 'Technician' so that he or she can be
        # assigned projects, which is an option 'Supervisor' users do not have.
        LEAD = 'Jaye'

        if self.my_level == 'Supervisor' or self.my_name == LEAD:
            # Supervisors and leads are linked with all jobs.
            return JobIO.jobs_at_a_glance(
                JobIO.sort_project_data(JobIO.existing_projects()))
        elif self.my_level == 'Technician':
            return JobIO.jobs_at_a_glance(self.my_job_data)
Exemple #8
0
    def load_job(self, job_num):
        """Send a ``Job`` to `desk` and open for viewing.

		Parameters
		----------
		job_num : str
			The 6-digit job number.

		Raises
		------
		JobNotFoundError
		JobInUseError
		IOError
		EOFError

		"""
        job, lock = JobIO.job_and_lock(job_num)
        self.desk.open_job_folder(job, lock)
Exemple #9
0
    def _drop_active_jobs(self, df):
        """Remove rows that have been assigned.

		Parameters
		----------
		df : DataFrame

		Raises
		------
		EmptyModelError
			All rows in `df` were removed.

		"""
        assigned = JobIO.active_job_nums()
        assigned_indices = [
            index for index, row in df.iterrows()
            if row['WC line alias'][:6] in assigned
        ]
        df.drop(assigned_indices, inplace=True)
        if len(df.index) == 0:
            raise EmptyModelError()
Exemple #10
0
	def approved(self):
		"""Evaluate a new job request.

		Returns
		-------
		True
			If job files were created successfully.

		Raises
		------
		JobNumberError
		ExistingJobError
		WorkspaceError
		OSError
		IOError

		"""
		self._validate_job_num()
		self.workspace = ProjectWorkspace.make(self._job_num, self._logger)
		if self.workspace is not None:
			return JobIO.init_files(
				self._job_num, 
				self.workspace
			)
Exemple #11
0
	def status(selected_dwg_nums, projects, status, workspace, log):
		"""Modify a project's status attribute.

		Parameters
		----------
		selected_dwg_nums : list
			Drawing numbers associated with the ``Projects`` that are requesting 
			modification.

		projects : dict
			``Projects`` organized by drawing number.

		status : str
			The new status.

		workspace : str
			The toplevel project workspace directory.

		log : callable
			Interface to user log file.

		Notes
		-----
		When `status` signifies the completion of a work order, an attempt is 
		made to send the corresponding non-controlled drawing PDF to the issued
		prints folder. This PDF should be created through Autodesk Inventor per
		the local iLogic code, otherwise the resulting PDF name may not match 
		the required convention. In this case, this method will not find the PDF
		and the user will be responsible to completing this action.

		"""
		if status == WorkOrderConstants.STATUS_LIST[-1]:
			job_num = selected_dwg_nums[0][:6]
			dwgs_nums = JobIO.drawing_nums_from_list(selected_dwg_nums)
			target_count = len(dwgs_nums)
			actual_count = 0
			moved_dwg_nums = []
			
			# Get the destination for non-controlled drawing PDFs.
			try:
				dst = Extract.issued_prints_folder(job_num)
			except (DestinationError, ProjectsFolderRootError) as error:
				ExceptionMessageBox(error).exec_()
				return

			pdfs = ContextHandler.workspace_pdfs(workspace)

			for pdf in pdfs:
				if actual_count < target_count:
					# Get the filename and drawing number from pdf.
					# The '_' separator is driven by Inventor iLogic code.
					# Non-controlled PDF files must conform to this convention.
					filename = os.path.basename(pdf)
					target_dwg_num = filename.split('_')[0]

					if target_dwg_num in selected_dwg_nums:
						dst_path = os.path.join(dst, filename)
						shutil.move(pdf, dst_path)
						actual_count += 1
						moved_dwg_nums.append(target_dwg_num)

			# Check for PDFs that should exist, but don't.
			missing_pdfs = [i for i in dwgs_nums if i not in moved_dwg_nums]
			if len(missing_pdfs) != 0:
				log('%s PDF not moved, there may be others' % missing_pdfs[0])
				MissingPDFError.show(missing_pdfs)

		for p in selected_dwg_nums:
			projects[p].status = status
 def refresh(self):
     """Update data model."""
     self._data = JobIO.existing_projects()