def render_readonly(self, **kwargs): request = self.request te = request.model_instance if not request.has_permission('view', te.project): return '#%s' % te.ticket try: ticket_data = ticket_store.get_ticket(request, te.project_id, te.ticket) except xmlrpclib.Fault: ticket_data = None if ticket_data: ticket_id, dummy_time, dummy_changetime, tkt = ticket_data ret = HTML.A(u'#%s - %s' % (ticket_id, tkt['summary']), href=ticket_url(request, te.project, te.ticket)) cr_id = tkt['customerrequest'] if cr_id: cr = DBSession.query(CustomerRequest).get(cr_id) ret += HTML.BR() + HTML.SPAN('CR: ') + HTML.A(cr.name, href='/admin/CustomerRequest/%s' % cr_id) return ret else: return HTML.SPAN(u'#%s - ' % te.ticket, HTML.SPAN(u'NOT FOUND', class_='label label-important'))
def search(self, customer_id, project_id, date_from, date_to, users, customer_requests, workflow_states, detail_level, render_links=True): # also search archived projects, if none are specified qry = DBSession.query(TimeEntry).join(TimeEntry.project).join(Project.customer).outerjoin(TimeEntry.author) qry = qry.options(lazyload(TimeEntry.project, TimeEntry.author, Project.customer)) if customer_id is not colander.null: qry = qry.filter(Project.customer_id == customer_id) if project_id is not colander.null: qry = qry.filter(TimeEntry.project_id == project_id) if date_from is not colander.null: qry = qry.filter(TimeEntry.date>=date_from) if date_to is not colander.null: qry = qry.filter(TimeEntry.date<=date_to) if users: qry = qry.filter(TimeEntry.author_id.in_(users)) if workflow_states: qry = qry.filter(TimeEntry.workflow_state.in_(workflow_states)) qry = qry.filter(te_filter_by_customer_requests(customer_requests, request=self.request)) qry = qry.order_by(sa.desc(TimeEntry.date), sa.desc(TimeEntry.start), sa.desc(TimeEntry.creation_date)) time_entries = self.request.filter_viewables(qry) proj_tickets = collections.defaultdict(set) for te in time_entries: if te.ticket is None: continue proj_tickets[te.project_id].add(te.ticket) # projectsmap = { # 'project_id': { # 'ticket_id': 'customer_request_id', # ... # }, # ... # } projectsmap = {} for project_id, ticket_ids in proj_tickets.items(): project = DBSession.query(Project).get(project_id) projectsmap[project_id] = dict(ticket_store.get_requests_from_tickets( project, tuple(ticket_ids), request=self.request)) tkts = {} for project_id, ticket_ids in proj_tickets.items(): project = DBSession.query(Project).get(project_id) for tkt in ticket_store.get_tickets_for_project(project, request=self.request): tkts[(project_id, tkt['id'])] = tkt rows = [] cr_get = DBSession.query(CustomerRequest).get for te in time_entries: if te.ticket is None: rendered_request = NullCustomerRequest().name ticket_type = '-' ticket_summary = '-' else: cr_id = projectsmap[te.project_id].get(te.ticket) if not cr_id: continue customer_request = cr_get(cr_id) if customer_request: if render_links: rendered_request = HTML.A(customer_request.name.strip(), href="%s/admin/CustomerRequest/%s" % ( self.request.application_url, customer_request.id ) ) else: rendered_request = customer_request.name.strip() else: rendered_request = NullCustomerRequest().name tkt = tkts[(te.project_id, te.ticket)] ticket_type = tkt['type'] ticket_summary = tkt['summary'] if render_links: ticket_summary = HTML.A(ticket_summary, href=ticket_url(request=self.request, project=te.project, ticket_id=te.ticket)) description = HTML.A(te.description, href=timeentry_url(request=self.request, time_entry=te)) entry = { 'customer': te.project.customer.name.strip(), 'project': te.project.name.strip(), 'request': rendered_request, 'ticket_summary': ticket_summary, 'user': te.author.fullname.strip(), 'date': te.date.strftime('%Y-%m-%d'), 'description': description, 'location': te.location, 'ticket_type': ticket_type, 'sensitive': ['no', 'yes'][tkt['sensitive']], 'hours': te.hours, } event = AfterEntryCreatedEvent(entry, te) self.request.registry.notify(event) rows.append(entry) columns = [ ('customer', u'Cliente'), ('project', u'Progetto'), ('request', u'Request'), ('ticket_summary', u'Ticket'), ('ticket_type', u'Tipologia'), ('sensitive', u'Sensitive'), ('user', u'Persona'), ('date', u'Data'), ('description', u'Descrizione attività'), ('location', u'Sede'), ('hours', u'Ore'), ] group_by = { 'project': ['customer', 'project', 'user'], 'request': ['customer', 'project', 'request', 'user'], 'ticket': ['customer', 'project', 'request', 'ticket_summary', 'ticket_type', 'sensitive', 'user'], 'timeentry': None, 'date': ['user', 'date', 'location'], }[detail_level] if group_by: rows, columns = self.group(rows, columns, group_by) return { 'rows': rows, 'columns': columns, }
def search(self, customer_id, project_id, date_from, date_to, users, customer_requests, invoice_number, workflow_states): # also search archived projects, if none are specified qry = DBSession.query(TimeEntry).join(TimeEntry.project).join(Project.customer).outerjoin(TimeEntry.author) qry = qry.options(lazyload(TimeEntry.project, TimeEntry.author, Project.customer)) if customer_id is not colander.null: qry = qry.filter(Project.customer_id == customer_id) if project_id is not colander.null: qry = qry.filter(TimeEntry.project_id == project_id) if date_from is not colander.null: qry = qry.filter(TimeEntry.date>=date_from) if date_to is not colander.null: qry = qry.filter(TimeEntry.date<=date_to) if users: qry = qry.filter(TimeEntry.author_id.in_(users)) if invoice_number: qry = qry.filter(TimeEntry.invoice_number==invoice_number) if workflow_states: qry = qry.filter(TimeEntry.workflow_state.in_(workflow_states)) qry = qry.filter(te_filter_by_customer_requests(customer_requests, request=self.request)) qry = qry.order_by(sa.desc(TimeEntry.date), sa.desc(TimeEntry.start), sa.desc(TimeEntry.creation_date)) time_entries = self.request.filter_viewables(qry) proj_tickets = collections.defaultdict(set) for te in time_entries: if te.ticket is None: continue proj_tickets[te.project_id].add(te.ticket) # projectsmap = { # 'project_id': { # 'ticket_id': 'customer_request_id', # ... # }, # ... # } projectsmap = {} for project_id, ticket_ids in proj_tickets.items(): project = DBSession.query(Project).get(project_id) projectsmap[project_id] = dict(ticket_store.get_requests_from_tickets( project, tuple(ticket_ids), request=self.request)) tkts = {} for project_id, ticket_ids in proj_tickets.items(): project = DBSession.query(Project).get(project_id) for tkt in ticket_store.get_tickets_for_project(project, request=self.request): tkts[(project_id, tkt['id'])] = tkt entries_tree = collections.defaultdict(lambda: collections.defaultdict(list)) cr_get = DBSession.query(CustomerRequest).get # one nullcr for each project, to better group them nullcrs = dict( (project, NullCustomerRequest(project=project)) for project in DBSession.query(Project) ) for te in time_entries: if te.ticket is None: customer_request = nullcrs[project] else: cr_id = projectsmap[te.project_id].get(te.ticket) if not cr_id: continue customer_request = cr_get(cr_id) or nullcrs[project] entry = { 'customer': te.project.customer.name.strip(), 'project': te.project.name.strip(), 'user': te.author.fullname.strip(), 'date': te.date.strftime('%Y-%m-%d'), 'contract': te.contract, 'description': te.description, 'hours_str': te.hours_str, 'workflow_state': te.workflow_state, 'tickettype': te.tickettype, 'invoice_number': te.invoice_number, 'location': te.location, 'id': te.id, } if te.ticket is None: ticket_description = '(no ticket)' else: tkt = tkts[(te.project_id, te.ticket)] href = ticket_url(request=self.request, project=te.project, ticket_id=te.ticket) ticket_description = HTML.SPAN( HTML.A('#%(id)s - %(summary)s' % tkt, href=href), ' ', HTML.SUP(tkt['type']), ) entries_tree[customer_request][ticket_description].append(entry) return { 'entries_tree': entries_tree, }