def contract(contract_id): '''Contract profile page ''' contract = ContractBase.query.get(contract_id) if contract: note_form = NoteForm() if note_form.validate_on_submit(): new_note = ContractNote( note=note_form.data['note'], contract_id=contract_id, taken_by_id=current_user.id ) db.session.add(new_note) db.session.commit() return redirect(url_for('wexplorer.contract', contract_id=contract_id)) notes = ContractNote.query.filter( ContractNote.contract_id == contract_id, ContractNote.taken_by_id == current_user.id ).all() departments = set([i.department for i in contract.followers]) current_app.logger.info('WEXCONTRACT - Viewed contract page {}'.format(contract.description)) return dict( contract=contract, departments=departments, choices=Department.choices(), path='{path}?{query}'.format( path=request.path, query=request.query_string ), notes=notes, note_form=note_form ) abort(404)
def filter(department_id): '''Filter contracts by which ones have departmental subscribers :param department_id: Department's unique ID :status 200: Renders template with all contracts followed by that department :status 404: When department is not found with the specified ID ''' department = Department.query.get(int(department_id)) if department: pagination_per_page = current_app.config.get('PER_PAGE', 50) page = int(request.args.get('page', 1)) lower_bound_result = (page - 1) * pagination_per_page upper_bound_result = lower_bound_result + pagination_per_page contracts = db.session.execute( ''' SELECT contract.id, description, count(contract_user_association.user_id) AS follows FROM contract LEFT OUTER JOIN contract_user_association ON contract.id = contract_user_association.contract_id FULL OUTER JOIN users ON contract_user_association.user_id = users.id JOIN department ON users.department_id = department.id WHERE department.id = :department GROUP BY 1,2 HAVING count(contract_user_association.user_id) > 0 ORDER BY 3 DESC, 1 ASC ''', {'department': int(department_id)} ).fetchall() if len(contracts) > 0: pagination = SimplePagination(page, pagination_per_page, len(contracts)) results = contracts[lower_bound_result:upper_bound_result] else: pagination = None results = [] current_app.logger.info('WEXFILTER - {department}: Filter by {department}'.format( department=department.name )) return render_template( 'scout/filter.html', search_form=SearchForm(), results=results, pagination=pagination, department=department, choices=Department.choices(), path='{path}?{query}'.format( path=request.path, query=request.query_string ) ) abort(404)
def feedback_handler(contract_id=None, search_for=None): ''' Allow user to send feedback on the data present in a specific contract ''' if contract_id: contract = ContractBase.query.get(contract_id) else: contract = ContractBase( description='Search term: ' + search_for ) search_form = SearchForm() if contract: form = FeedbackForm() if not current_user.is_anonymous(): form.sender.data = current_user.email if form.validate_on_submit(): current_app.logger.info('WEXFEEDBACK - Feedback from {email} about {contract}'.format( email=form.sender.data, contract=contract.description )) feedback_sent = Notification( to_email=db.session.query(User.email).join(Role, User.role_id == Role.id).filter( Role.name.in_(['admin', 'superadmin']) ).all(), subject='Scout contract feedback - ID: {id}, Description: {description}'.format( id=contract.id if contract.id else 'N/A', description=contract.description ), html_template='wexplorer/feedback_email.html', contract=contract, sender=form.data.get('sender'), body=form.data.get('body') ).send() if feedback_sent: flash('Thank you for your feedback!', 'alert-success') else: flash('Oh no! Something went wrong. We are looking into it.', 'alert-danger') if contract.id: return redirect(url_for('wexplorer.contract', contract_id=contract.id)) return redirect(url_for('wexplorer.explore')) return render_template( 'wexplorer/feedback.html', search_form=search_form, contract=contract, choices=Department.choices(), feedback_form=form, search_for=search_for ) abort(404)
def feedback_handler(contract, search_for=None): """Allow user to send feedback on the data present in a specific contract Arguments: contract: :py:class:`~purchasing.data.contracts.ContractBase` object search_for: search term or None. Returns: Redirects to or renders the appropriate feedback handling template """ form = FeedbackForm() search_form = SearchForm() if not current_user.is_anonymous(): form.sender.data = current_user.email if form.validate_on_submit(): current_app.logger.info( "WEXFEEDBACK - Feedback from {email} about {contract}".format( email=form.sender.data, contract=contract.description ) ) feedback_sent = Notification( to_email=db.session.query(User.email) .join(Role, User.role_id == Role.id) .filter(Role.name.in_(["admin", "superadmin"])) .all(), subject="Scout contract feedback - ID: {id}, Description: {description}".format( id=contract.id if contract.id else "N/A", description=contract.description ), html_template="scout/feedback_email.html", contract=contract, sender=form.data.get("sender"), body=form.data.get("body"), ).send() if feedback_sent: flash("Thank you for your feedback!", "alert-success") else: flash("Oh no! Something went wrong. We are looking into it.", "alert-danger") if contract.id: return redirect(url_for("scout.contract", contract_id=contract.id)) return redirect(url_for("scout.explore")) return render_template( "scout/feedback.html", search_form=search_form, contract=contract, choices=Department.choices(), feedback_form=form, search_for=search_for, )
def filter_no_department(): '''The landing page for filtering by departments :status 200: Renders the appropriate landing page. ''' return render_template('scout/filter.html', search_form=SearchForm(), results=[], choices=Department.choices(), path='{path}?{query}'.format( path=request.path, query=request.query_string))
def filter_no_department(): '''The landing page for filtering by departments ''' return render_template( 'wexplorer/filter.html', search_form=SearchForm(), results=[], choices=Department.choices(), path='{path}?{query}'.format( path=request.path, query=request.query_string ) )
def filter_no_department(): """The landing page for filtering by departments :status 200: Renders the appropriate landing page. """ return render_template( "scout/filter.html", search_form=SearchForm(), results=[], choices=Department.choices(), path="{path}?{query}".format(path=request.path, query=request.query_string), )
def feedback_handler(contract, search_for=None): '''Allow user to send feedback on the data present in a specific contract Arguments: contract: :py:class:`~purchasing.data.contracts.ContractBase` object search_for: search term or None. Returns: Redirects to or renders the appropriate feedback handling template ''' form = FeedbackForm() search_form = SearchForm() if not current_user.is_anonymous: form.sender.data = current_user.email if form.validate_on_submit(): current_app.logger.info('WEXFEEDBACK - Feedback from {email} about {contract}'.format( email=form.sender.data, contract=contract.description )) feedback_sent = Notification( to_email=db.session.query(User.email).filter( User.roles.any(Role.name.in_(['admin', 'superadmin'])) ).all(), subject='Scout contract feedback - ID: {id}, Description: {description}'.format( id=contract.id if contract.id else 'N/A', description=contract.description ), html_template='scout/feedback_email.html', contract=contract, sender=form.data.get('sender'), body=form.data.get('body') ).send() if feedback_sent: flash('Thank you for your feedback!', 'alert-success') else: flash('Oh no! Something went wrong. We are looking into it.', 'alert-danger') if contract.id: return redirect(url_for('scout.contract', contract_id=contract.id)) return redirect(url_for('scout.explore')) return render_template( 'scout/feedback.html', search_form=search_form, contract=contract, choices=Department.choices(), feedback_form=form, search_for=search_for )
def company(company_id): company = Company.query.get(company_id) if company: current_app.logger.info('WEXCOMPANY - Viewed company page {}'.format(company.company_name)) return dict( company=company, choices=Department.choices(), path='{path}?{query}'.format( path=request.path, query=request.query_string ) ) abort(404)
def feedback_handler(contract, search_for=None): '''Allow user to send feedback on the data present in a specific contract Arguments: contract: :py:class:`~purchasing.data.contracts.ContractBase` object search_for: search term or None. Returns: Redirects to or renders the appropriate feedback handling template ''' form = FeedbackForm() search_form = SearchForm() if not current_user.is_anonymous(): form.sender.data = current_user.email if form.validate_on_submit(): current_app.logger.info( 'WEXFEEDBACK - Feedback from {email} about {contract}'.format( email=form.sender.data, contract=contract.description)) feedback_sent = Notification( to_email=db.session.query(User.email).join( Role, User.role_id == Role.id).filter( Role.name.in_(['admin', 'superadmin'])).all(), subject= 'Scout contract feedback - ID: {id}, Description: {description}'. format(id=contract.id if contract.id else 'N/A', description=contract.description), html_template='scout/feedback_email.html', contract=contract, sender=form.data.get('sender'), body=form.data.get('body')).send() if feedback_sent: flash('Thank you for your feedback!', 'alert-success') else: flash('Oh no! Something went wrong. We are looking into it.', 'alert-danger') if contract.id: return redirect(url_for('scout.contract', contract_id=contract.id)) return redirect(url_for('scout.explore')) return render_template('scout/feedback.html', search_form=search_form, contract=contract, choices=Department.choices(), feedback_form=form, search_for=search_for)
def company(company_id): '''Company profile page :param contract_id: Unique ID for a :py:class:`~purchasing.data.companies.Company` object :status 200: Renders the company profile template :status 404: Unique company ID not found ''' company = Company.query.get(company_id) if company: current_app.logger.info('WEXCOMPANY - Viewed company page {}'.format( company.company_name)) return dict(company=company, choices=Department.choices(), path='{path}?{query}'.format(path=request.path, query=request.query_string)) abort(404)
def company(company_id): """Company profile page :param contract_id: Unique ID for a :py:class:`~purchasing.data.companies.Company` object :status 200: Renders the company profile template :status 404: Unique company ID not found """ company = Company.query.get(company_id) if company: current_app.logger.info("WEXCOMPANY - Viewed company page {}".format(company.company_name)) return dict( company=company, choices=Department.choices(), path="{path}?{query}".format(path=request.path, query=request.query_string), ) abort(404)
def contract(contract_id): '''Contract profile page For GET requests, render the profile page. For POSTs, try to submit a new note. :param contract_id: Unique ID for a :py:class:`~purchasing.data.contracts.ContractBase` object :status 200: Renders the contract profile template :status 302: Try to post note, then redirect to the same page's contract view :status 404: Unique contract ID not found ''' contract = ContractBase.query.get(contract_id) if contract: note_form = NoteForm() if note_form.validate_on_submit(): new_note = ContractNote( note=note_form.data['note'], contract_id=contract_id, taken_by_id=current_user.id ) db.session.add(new_note) db.session.commit() return redirect(url_for('scout.contract', contract_id=contract_id)) notes = ContractNote.query.filter( ContractNote.contract_id == contract_id, ContractNote.taken_by_id == current_user.id ).all() departments = set([i.department for i in contract.followers]) current_app.logger.info('WEXCONTRACT - Viewed contract page {}'.format(contract.description)) return dict( contract=contract, departments=departments, choices=Department.choices(), path='{path}?{query}'.format( path=request.path, query=request.query_string ), notes=notes, note_form=note_form ) abort(404)
def search(): '''The search results page for scout In order to create permalinks to each search/filter result combination, POST methods have their form arguments popped off and then are immediately redirected to GET methods. .. seealso :: * :py:mod:`purchasing.data.searches` for more on the search query * :py:class:`~purchasing.scout.forms.SearchForm` for the search form construction * :py:func:`~purchasing.scout.util.build_filter` for how filters are built * :py:func:`~purchasing.scout.util.build_cases` for how case statements are built :status 200: Render the search template with the given results :status 302: Pop the passed form arguments to the request URL and redirect to the search view ''' if request.method == 'POST': args = request.form.to_dict() if args.get('contract_type') == '__None': del args['contract_type'] return redirect(url_for('scout.search', **args)) department = request.args.get('department') if department and department not in ['', 'None']: return redirect(url_for('scout.filter', department=department)) search_form = SearchForm() search_for = request.args.get('q') or '' search_form.q.data = search_for # strip out "crazy" characters search_for = re.sub(CRAZY_CHARS, '', search_for) search_for = ' | '.join(search_for.split()) pagination_per_page = current_app.config.get('PER_PAGE', 50) page = int(request.args.get('page', 1)) lower_bound_result = (page - 1) * pagination_per_page upper_bound_result = lower_bound_result + pagination_per_page filter_or = build_filter( request.args, FILTER_FIELDS, search_for, search_form, not any([request.args.get(name) for name, _, _ in FILTER_FIELDS]) ) filter_and = [] if request.args.get('contract_type') is not None: filter_and = [ ContractBase.contract_type_id == int(request.args.get('contract_type')) ] search_form.contract_type.data = ContractType.query.get(int(request.args.get('contract_type'))) found_in_case = build_cases( request.args, FILTER_FIELDS, search_for, not any([request.args.get(name) for name, _, _ in FILTER_FIELDS]) ) # determine if we are getting archived contracts if request.args.get('archived') == 'y': search_form['archived'].checked = True archived = True else: archived = False if search_for != '': contracts = find_contract_metadata( search_for, found_in_case, filter_or, filter_and, archived ) else: contracts = return_all_contracts( filter_and, archived ) pagination = SimplePagination(page, pagination_per_page, len(contracts)) current_app.logger.info('WEXSEARCH - {search_for}: {user} searched for "{search_for}"'.format( search_for=search_for, user=current_user.email if not current_user.is_anonymous else 'anonymous' )) user_follows = [] if current_user.is_anonymous else current_user.get_following() return render_template( 'scout/search.html', current_user=current_user, user_follows=user_follows, search_for=search_for, results=contracts[lower_bound_result:upper_bound_result], pagination=pagination, search_form=search_form, choices=Department.choices(), path='{path}?{query}'.format( path=request.path, query=request.query_string ) )
def search(): ''' The search results page for scout ''' if request.method == 'POST': args = request.form.to_dict() if args.get('contract_type') == '__None': del args['contract_type'] return redirect(url_for('wexplorer.search', **args)) department = request.args.get('department') if department and department not in ['', 'None']: return redirect(url_for('wexplorer.filter', department=department)) search_form = SearchForm() search_for = request.args.get('q') or '' search_form.q.data = search_for # strip out "crazy" characters search_for = re.sub(CRAZY_CHARS, '', search_for) search_for = ' | '.join(search_for.split()) pagination_per_page = current_app.config.get('PER_PAGE', 50) page = int(request.args.get('page', 1)) lower_bound_result = (page - 1) * pagination_per_page upper_bound_result = lower_bound_result + pagination_per_page # build filter and filter form fields = [ ('company_name', 'Company Name', SearchView.tsv_company_name), ('line_item', 'Line Item', SearchView.tsv_line_item_description), ('contract_description', 'Contract Description', SearchView.tsv_contract_description), ('contract_detail', 'Contract Detail', SearchView.tsv_detail_value), ('financial_id', 'Controller Number', SearchView.financial_id), ] filter_or = build_filter( request.args, fields, search_for, search_form, not any([request.args.get(name) for name, _, _ in fields]) ) filter_and = [] if request.args.get('contract_type') is not None: filter_and = [ ContractBase.contract_type_id == int(request.args.get('contract_type')) ] search_form.contract_type.data = ContractType.query.get(int(request.args.get('contract_type'))) found_in_case = build_cases( request.args, fields, search_for, not any([request.args.get(name) for name, _, _ in fields]) ) # determine if we are getting archived contracts if request.args.get('archived') == 'y': search_form['archived'].checked = True archived = True else: archived = False if search_for != '': contracts = find_contract_metadata( search_for, found_in_case, filter_or, filter_and, archived ) else: contracts = return_all_contracts( filter_and, archived ) pagination = SimplePagination(page, pagination_per_page, len(contracts)) current_app.logger.info('WEXSEARCH - {search_for}: {user} searched for "{search_for}"'.format( search_for=search_for, user=current_user.email if not current_user.is_anonymous() else 'anonymous' )) user_follows = [] if current_user.is_anonymous() else current_user.get_following() return render_template( 'wexplorer/search.html', current_user=current_user, user_follows=user_follows, search_for=search_for, results=contracts[lower_bound_result:upper_bound_result], pagination=pagination, search_form=search_form, choices=Department.choices(), path='{path}?{query}'.format( path=request.path, query=request.query_string ) )
def explore(): '''The landing page for scout. Renders the "big search" template. :status 200: Renders the appropriate landing page. ''' return dict(current_user=current_user, choices=Department.choices())
def search(): '''The search results page for scout In order to create permalinks to each search/filter result combination, POST methods have their form arguments popped off and then are immediately redirected to GET methods. .. seealso :: * :py:mod:`purchasing.data.searches` for more on the search query * :py:class:`~purchasing.scout.forms.SearchForm` for the search form construction * :py:func:`~purchasing.scout.util.build_filter` for how filters are built * :py:func:`~purchasing.scout.util.build_cases` for how case statements are built :status 200: Render the search template with the given results :status 302: Pop the passed form arguments to the request URL and redirect to the search view ''' if request.method == 'POST': args = request.form.to_dict() if args.get('contract_type') == '__None': del args['contract_type'] return redirect(url_for('scout.search', **args)) department = request.args.get('department') if department and department not in ['', 'None']: return redirect(url_for('scout.filter', department=department)) search_form = SearchForm() search_for = request.args.get('q') or '' search_form.q.data = search_for # strip out "crazy" characters search_for = re.sub(CRAZY_CHARS, '', search_for) search_for = ' | '.join(search_for.split()) pagination_per_page = current_app.config.get('PER_PAGE', 50) page = int(request.args.get('page', 1)) lower_bound_result = (page - 1) * pagination_per_page upper_bound_result = lower_bound_result + pagination_per_page filter_or = build_filter( request.args, FILTER_FIELDS, search_for, search_form, not any([request.args.get(name) for name, _, _ in FILTER_FIELDS]) ) filter_and = [] if request.args.get('contract_type') is not None: filter_and = [ ContractBase.contract_type_id == int(request.args.get('contract_type')) ] search_form.contract_type.data = ContractType.query.get(int(request.args.get('contract_type'))) found_in_case = build_cases( request.args, FILTER_FIELDS, search_for, not any([request.args.get(name) for name, _, _ in FILTER_FIELDS]) ) # determine if we are getting archived contracts if request.args.get('archived') == 'y': search_form['archived'].checked = True archived = True else: archived = False if search_for != '': contracts = find_contract_metadata( search_for, found_in_case, filter_or, filter_and, archived ) else: contracts = return_all_contracts( filter_and, archived ) pagination = SimplePagination(page, pagination_per_page, len(contracts)) current_app.logger.info('WEXSEARCH - {search_for}: {user} searched for "{search_for}"'.format( search_for=search_for, user=current_user.email if not current_user.is_anonymous() else 'anonymous' )) user_follows = [] if current_user.is_anonymous() else current_user.get_following() return render_template( 'scout/search.html', current_user=current_user, user_follows=user_follows, search_for=search_for, results=contracts[lower_bound_result:upper_bound_result], pagination=pagination, search_form=search_form, choices=Department.choices(), path='{path}?{query}'.format( path=request.path, query=request.query_string ) )
def explore(): ''' The landing page for wexplorer. Renders the "big search" template. ''' return dict(current_user=current_user, choices=Department.choices())
def search(): """The search results page for scout In order to create permalinks to each search/filter result combination, POST methods have their form arguments popped off and then are immediately redirected to GET methods. .. seealso :: * :py:mod:`purchasing.data.searches` for more on the search query * :py:class:`~purchasing.scout.forms.SearchForm` for the search form construction * :py:func:`~purchasing.scout.util.build_filter` for how filters are built * :py:func:`~purchasing.scout.util.build_cases` for how case statements are built """ if request.method == "POST": args = request.form.to_dict() if args.get("contract_type") == "__None": del args["contract_type"] return redirect(url_for("scout.search", **args)) department = request.args.get("department") if department and department not in ["", "None"]: return redirect(url_for("scout.filter", department=department)) search_form = SearchForm() search_for = request.args.get("q") or "" search_form.q.data = search_for # strip out "crazy" characters search_for = re.sub(CRAZY_CHARS, "", search_for) search_for = " | ".join(search_for.split()) pagination_per_page = current_app.config.get("PER_PAGE", 50) page = int(request.args.get("page", 1)) lower_bound_result = (page - 1) * pagination_per_page upper_bound_result = lower_bound_result + pagination_per_page filter_or = build_filter( request.args, FILTER_FIELDS, search_for, search_form, not any([request.args.get(name) for name, _, _ in FILTER_FIELDS]), ) filter_and = [] if request.args.get("contract_type") is not None: filter_and = [ContractBase.contract_type_id == int(request.args.get("contract_type"))] search_form.contract_type.data = ContractType.query.get(int(request.args.get("contract_type"))) found_in_case = build_cases( request.args, FILTER_FIELDS, search_for, not any([request.args.get(name) for name, _, _ in FILTER_FIELDS]) ) # determine if we are getting archived contracts if request.args.get("archived") == "y": search_form["archived"].checked = True archived = True else: archived = False if search_for != "": contracts = find_contract_metadata(search_for, found_in_case, filter_or, filter_and, archived) else: contracts = return_all_contracts(filter_and, archived) pagination = SimplePagination(page, pagination_per_page, len(contracts)) current_app.logger.info( 'WEXSEARCH - {search_for}: {user} searched for "{search_for}"'.format( search_for=search_for, user=current_user.email if not current_user.is_anonymous() else "anonymous" ) ) user_follows = [] if current_user.is_anonymous() else current_user.get_following() return render_template( "scout/search.html", current_user=current_user, user_follows=user_follows, search_for=search_for, results=contracts[lower_bound_result:upper_bound_result], pagination=pagination, search_form=search_form, choices=Department.choices(), path="{path}?{query}".format(path=request.path, query=request.query_string), )
def __init__(self, contract): self.title = better_title(contract.description) self.opportunity_type = ContractType.get_type(current_app.config.get('CONDUCTOR_TYPE', '')) self.department = Department.get_dept(current_app.config.get('CONDUCTOR_DEPARTMENT', ''))
def __init__(self, contract): self.title = better_title(contract.description) self.opportunity_type = ContractType.get_type( current_app.config.get('CONDUCTOR_TYPE', '')) self.department = Department.get_dept( current_app.config.get('CONDUCTOR_DEPARTMENT', ''))