def detail(contract_id, stage_id=-1): '''View to control an individual stage update process ''' contract = ContractBase.query.get(contract_id) if not contract: abort(404) if contract.completed_last_stage(): return redirect(url_for('conductor.edit', contract_id=contract.id)) if stage_id == -1: # redirect to the current stage page contract_stage = contract.get_current_stage() if contract_stage: return redirect(url_for( 'conductor.detail', contract_id=contract_id, stage_id=contract_stage.id )) current_app.logger.warning('Could not find stages for this contract, aborting!') abort(500) stages = get_contract_stages(contract) try: active_stage = [i for i in stages if i.id == stage_id][0] current_stage = [i for i in stages if i.entered and not i.exited][0] if active_stage.entered is None: abort(404) except IndexError: abort(404) note_form = NoteForm() update_form = SendUpdateForm(obj=UpdateFormObj(current_stage)) opportunity_form = PostOpportunityForm( obj=contract.opportunity if contract.opportunity else ConductorObj(contract) ) metadata_form = ContractMetadataForm(obj=ContractMetadataObj(contract)) complete_form = CompleteForm() if session.get('invalid_date-{}'.format(contract_id), False): complete_form.errors['complete'] = session.pop('invalid_date-{}'.format(contract_id)) forms = { 'activity': note_form, 'update': update_form, 'post': opportunity_form, 'update-metadata': metadata_form } active_tab = '#activity' submitted_form = request.args.get('form', None) if submitted_form: if handle_form( forms[submitted_form], submitted_form, stage_id, current_user, contract, active_stage ): return redirect(url_for( 'conductor.detail', contract_id=contract_id, stage_id=stage_id )) else: active_tab = '#' + submitted_form actions = contract.filter_action_log() # actions = contract.build_complete_action_log() subscribers, total_subscribers = build_subscribers(contract) flows = Flow.query.filter(Flow.id != contract.flow_id).all() current_app.logger.info( 'CONDUCTOR DETAIL VIEW - Detail view for contract {} (ID: {}), stage {}'.format( contract.description, contract.id, current_stage.name ) ) opportunity_form.display_cleanup() if len(stages) > 0: return render_template( 'conductor/detail.html', stages=stages, actions=actions, active_tab=active_tab, note_form=note_form, update_form=update_form, opportunity_form=opportunity_form, metadata_form=metadata_form, complete_form=complete_form, contract=contract, current_user=current_user, active_stage=active_stage, current_stage=current_stage, flows=flows, subscribers=subscribers, total_subscribers=total_subscribers, current_stage_enter=pytz.UTC.localize( current_stage.entered ).astimezone(current_app.config['DISPLAY_TIMEZONE']), categories=opportunity_form.get_categories(), subcategories=opportunity_form.get_subcategories() ) abort(404)
def detail(contract_id, stage_id=-1): '''View to control an individual stage update process This is the primary view for conductor. All actions that users can take with a :py:class:`~purchasing.data.contracts.ContractBase` flow through here. .. seealso:: There are a number of forms that are used on this page to allow the users to do actions directly from the management step: * :py:class:`~purchasing.conductor.forms.NoteForm` to allow users to take notes * :py:class:`~purchasing.conductor.forms.SendUpdateForm` to allow users to send email updates * :py:class:`~purchasing.conductor.forms.PostOpportunityForm` to allow users to post opportunities directly to :doc:`/beacon` * :py:class:`~purchasing.conductor.forms.ContractMetadataForm` to allow users to update a contract's metadata * :py:class:`~purchasing.conductor.forms.CompleteForm` to allow users to transition to the next :py:class:`~purchasing.data.stages.Stage` in the contract's :py:class:`~purchasing.data.flows.Flow` :param contract_id: Primary key ID for a :py:class:`~purchasing.data.contracts.ContractBase` :param stage_id: Primary key ID for a :py:class:`~purchasing.data.contract_stages.ContractStage` :status 200: Render the detail :status 302: Post a specific form. This form will either transition to the next contract stage if it is a :py:class:`~purchasing.conductor.forms.CompleteForm`, or perform whatever action is in that form's ``post_validate_action`` method :status 404: Contract not found ''' contract = ContractBase.query.get(contract_id) if not contract: abort(404) if contract.completed_last_stage(): return redirect(url_for('conductor.edit', contract_id=contract.id)) if stage_id == -1: # redirect to the current stage page contract_stage = contract.get_current_stage() if contract_stage: return redirect( url_for('conductor.detail', contract_id=contract_id, stage_id=contract_stage.id)) current_app.logger.warning( 'Could not find stages for this contract, aborting!') abort(500) stages = contract.get_contract_stages() try: active_stage = [i for i in stages if i.id == stage_id][0] current_stage = [i for i in stages if i.entered and not i.exited][0] if active_stage.entered is None: abort(404) except IndexError: abort(404) note_form = NoteForm() update_form = SendUpdateForm(obj=UpdateFormObj(current_stage)) opportunity_form = PostOpportunityForm( obj=contract.opportunity if contract. opportunity else ConductorToBeaconObj(contract)) metadata_form = ContractMetadataForm(obj=ContractMetadataObj(contract)) complete_form = CompleteForm() if session.get('invalid_date-{}'.format(contract_id), False): complete_form.errors['complete'] = session.pop( 'invalid_date-{}'.format(contract_id)) forms = { 'activity': note_form, 'update': update_form, 'post': opportunity_form, 'update-metadata': metadata_form } active_tab = '#activity' submitted_form_name = request.args.get('form', None) if submitted_form_name: submitted_form = forms[submitted_form_name] if submitted_form.validate_on_submit(): action = ContractStageActionItem( contract_stage_id=stage_id, action_type=submitted_form_name, taken_by=current_user.id, taken_at=datetime.datetime.utcnow()) action = submitted_form.post_validate_action( action, contract, current_stage) db.session.add(action) db.session.commit() return redirect( url_for('conductor.detail', contract_id=contract_id, stage_id=stage_id)) else: active_tab = '#' + submitted_form_name actions = contract.filter_action_log() # actions = contract.build_complete_action_log() subscribers, total_subscribers = contract.build_subscribers() flows = Flow.query.filter(Flow.id != contract.flow_id).all() current_app.logger.info( 'CONDUCTOR DETAIL VIEW - Detail view for contract {} (ID: {}), stage {}' .format(contract.description, contract.id, current_stage.name)) opportunity_form.display_cleanup() if len(stages) > 0: return render_template( 'conductor/detail.html', stages=stages, actions=actions, active_tab=active_tab, note_form=note_form, update_form=update_form, opportunity_form=opportunity_form, metadata_form=metadata_form, complete_form=complete_form, contract=contract, current_user=current_user, active_stage=active_stage, current_stage=current_stage, flows=flows, subscribers=subscribers, total_subscribers=total_subscribers, current_stage_enter=localize_datetime(current_stage.entered), categories=opportunity_form.get_categories(), subcategories=opportunity_form.get_subcategories()) abort(404)
def detail(contract_id, stage_id=-1): '''View to control an individual stage update process ''' if request.args.get('transition'): clicked = int(request.args.get('destination')) if \ request.args.get('destination') else None stage, mod_contract, complete = transition_stage( contract_id, destination=clicked, user=current_user ) if complete: return redirect(url_for('conductor.edit', contract_id=mod_contract.id)) return redirect(url_for( 'conductor.detail', contract_id=contract_id, stage_id=stage.id )) if stage_id == -1: # redirect to the current stage page contract_stage = ContractStage.query.join( ContractBase, ContractBase.id == ContractStage.contract_id ).filter( ContractStage.contract_id == contract_id, ContractStage.stage_id == ContractBase.current_stage_id ).first() return redirect(url_for( 'conductor.detail', contract_id=contract_id, stage_id=contract_stage.id )) stages = db.session.query( ContractStage.contract_id, ContractStage.stage_id, ContractStage.id, ContractStage.entered, ContractStage.exited, Stage.name, Stage.send_notifs, Stage.post_opportunities, ContractBase.description ).join(Stage, Stage.id == ContractStage.stage_id).join( ContractBase, ContractBase.id == ContractStage.contract_id ).filter( ContractStage.contract_id == contract_id ).order_by(ContractStage.id).all() try: active_stage = [i for i in stages if i.id == stage_id][0] current_stage = [i for i in stages if i.entered and not i.exited][0] if active_stage.entered is None: abort(404) except IndexError: abort(404) note_form = NoteForm() update_form = SendUpdateForm() opportunity_form = PostOpportunityForm() forms = { 'activity': note_form, 'update': update_form, 'post': opportunity_form } active_tab = '#activity' submitted_form = request.args.get('form', None) if submitted_form: if handle_form(forms[submitted_form], submitted_form, stage_id, current_user): return redirect(url_for( 'conductor.detail', contract_id=contract_id, stage_id=stage_id )) else: active_tab = '#' + submitted_form actions = ContractStageActionItem.query.filter( ContractStageActionItem.contract_stage_id == stage_id ).order_by(db.text('taken_at asc')).all() actions.extend([ ContractStageActionItem(action_type='entered', action_detail=active_stage.entered, taken_at=active_stage.entered), ContractStageActionItem(action_type='exited', action_detail=active_stage.exited, taken_at=active_stage.exited) ]) actions = sorted(actions, key=lambda stage: stage.get_sort_key()) if len(stages) > 0: return render_template( 'conductor/detail.html', stages=stages, actions=actions, active_tab=active_tab, note_form=note_form, update_form=update_form, opportunity_form=opportunity_form, contract_id=contract_id, current_user=current_user, active_stage=active_stage, current_stage=current_stage ) abort(404)
def detail(contract_id, stage_id=-1): '''View to control an individual stage update process This is the primary view for conductor. All actions that users can take with a :py:class:`~purchasing.data.contracts.ContractBase` flow through here. .. seealso:: There are a number of forms that are used on this page to allow the users to do actions directly from the management step: * :py:class:`~purchasing.conductor.forms.NoteForm` to allow users to take notes * :py:class:`~purchasing.conductor.forms.SendUpdateForm` to allow users to send email updates * :py:class:`~purchasing.conductor.forms.PostOpportunityForm` to allow users to post opportunities directly to :doc:`/beacon` * :py:class:`~purchasing.conductor.forms.ContractMetadataForm` to allow users to update a contract's metadata * :py:class:`~purchasing.conductor.forms.CompleteForm` to allow users to transition to the next :py:class:`~purchasing.data.stages.Stage` in the contract's :py:class:`~purchasing.data.flows.Flow` :param contract_id: Primary key ID for a :py:class:`~purchasing.data.contracts.ContractBase` :param stage_id: Primary key ID for a :py:class:`~purchasing.data.contract_stages.ContractStage` :status 200: Render the detail :status 302: Post a specific form. This form will either transition to the next contract stage if it is a :py:class:`~purchasing.conductor.forms.CompleteForm`, or perform whatever action is in that form's ``post_validate_action`` method :status 404: Contract not found ''' contract = ContractBase.query.get(contract_id) if not contract: abort(404) if contract.completed_last_stage(): return redirect(url_for('conductor.edit', contract_id=contract.id)) if stage_id == -1: # redirect to the current stage page contract_stage = contract.get_current_stage() if contract_stage: return redirect(url_for( 'conductor.detail', contract_id=contract_id, stage_id=contract_stage.id )) current_app.logger.warning('Could not find stages for this contract, aborting!') abort(500) stages = contract.get_contract_stages() try: active_stage = [i for i in stages if i.id == stage_id][0] current_stage = [i for i in stages if i.entered and not i.exited][0] if active_stage.entered is None: abort(404) except IndexError: abort(404) note_form = NoteForm() update_form = SendUpdateForm(obj=UpdateFormObj(current_stage)) opportunity_form = PostOpportunityForm( obj=contract.opportunity if contract.opportunity else ConductorToBeaconObj(contract) ) metadata_form = ContractMetadataForm(obj=ContractMetadataObj(contract)) complete_form = CompleteForm() if session.get('invalid_date-{}'.format(contract_id), False): complete_form.errors['complete'] = session.pop('invalid_date-{}'.format(contract_id)) forms = { 'activity': note_form, 'update': update_form, 'post': opportunity_form, 'update-metadata': metadata_form } active_tab = '#activity' submitted_form_name = request.args.get('form', None) if submitted_form_name: submitted_form = forms[submitted_form_name] if submitted_form.validate_on_submit(): action = ContractStageActionItem( contract_stage_id=stage_id, action_type=submitted_form_name, taken_by=current_user.id, taken_at=datetime.datetime.utcnow() ) action = submitted_form.post_validate_action(action, contract, current_stage) db.session.add(action) db.session.commit() return redirect(url_for( 'conductor.detail', contract_id=contract_id, stage_id=stage_id )) else: active_tab = '#' + submitted_form_name actions = contract.filter_action_log() # actions = contract.build_complete_action_log() subscribers, total_subscribers = contract.build_subscribers() flows = Flow.query.filter(Flow.id != contract.flow_id).all() current_app.logger.info( 'CONDUCTOR DETAIL VIEW - Detail view for contract {} (ID: {}), stage {}'.format( contract.description, contract.id, current_stage.name ) ) opportunity_form.display_cleanup() if len(stages) > 0: return render_template( 'conductor/detail.html', stages=stages, actions=actions, active_tab=active_tab, note_form=note_form, update_form=update_form, opportunity_form=opportunity_form, metadata_form=metadata_form, complete_form=complete_form, contract=contract, current_user=current_user, active_stage=active_stage, current_stage=current_stage, flows=flows, subscribers=subscribers, total_subscribers=total_subscribers, current_stage_enter=localize_datetime(current_stage.entered), categories=opportunity_form.get_categories(), subcategories=opportunity_form.get_subcategories() ) abort(404)