Add New Portfolio Workflow
This commit is contained in:
@@ -15,10 +15,8 @@ class PortfolioError(Exception):
|
||||
|
||||
class Portfolios(object):
|
||||
@classmethod
|
||||
def create(cls, user, name, defense_component=None):
|
||||
portfolio = PortfoliosQuery.create(
|
||||
name=name, defense_component=defense_component
|
||||
)
|
||||
def create(cls, user, portfolio_attrs):
|
||||
portfolio = PortfoliosQuery.create(**portfolio_attrs)
|
||||
perms_sets = PermissionSets.get_many(PortfolioRoles.PORTFOLIO_PERMISSION_SETS)
|
||||
Portfolios._create_portfolio_role(
|
||||
user,
|
||||
|
@@ -1,9 +1,24 @@
|
||||
from wtforms.fields import StringField
|
||||
from wtforms.validators import Length
|
||||
from wtforms.fields import (
|
||||
RadioField,
|
||||
SelectField,
|
||||
SelectMultipleField,
|
||||
StringField,
|
||||
TextAreaField,
|
||||
)
|
||||
from wtforms.validators import Length, Optional
|
||||
from wtforms.widgets import ListWidget, CheckboxInput
|
||||
|
||||
from .forms import BaseForm
|
||||
from atst.utils.localization import translate
|
||||
|
||||
from .data import (
|
||||
APPLICATION_COMPLEXITY,
|
||||
APP_MIGRATION,
|
||||
DEV_TEAM,
|
||||
SERVICE_BRANCHES,
|
||||
TEAM_EXPERIENCE,
|
||||
)
|
||||
|
||||
|
||||
class PortfolioForm(BaseForm):
|
||||
name = StringField(
|
||||
@@ -16,3 +31,84 @@ class PortfolioForm(BaseForm):
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
class PortfolioCreationForm(BaseForm):
|
||||
name = StringField(
|
||||
translate("forms.portfolio.name_label"),
|
||||
validators=[
|
||||
Length(
|
||||
min=4,
|
||||
max=100,
|
||||
message=translate("forms.portfolio.name_length_validation_message"),
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
defense_component = SelectField(
|
||||
translate("forms.task_order.defense_component_label"),
|
||||
choices=SERVICE_BRANCHES,
|
||||
default="",
|
||||
filters=[BaseForm.remove_empty_string],
|
||||
)
|
||||
|
||||
description = TextAreaField(
|
||||
translate("forms.task_order.scope_label"),
|
||||
description=translate("forms.task_order.scope_description"),
|
||||
)
|
||||
|
||||
app_migration = RadioField(
|
||||
translate("forms.task_order.app_migration.label"),
|
||||
description=translate("forms.task_order.app_migration.description"),
|
||||
choices=APP_MIGRATION,
|
||||
default="",
|
||||
validators=[Optional()],
|
||||
)
|
||||
|
||||
native_apps = RadioField(
|
||||
translate("forms.task_order.native_apps.label"),
|
||||
description=translate("forms.task_order.native_apps.description"),
|
||||
choices=[("yes", "Yes"), ("no", "No"), ("not_sure", "Not Sure")],
|
||||
default="",
|
||||
validators=[Optional()],
|
||||
)
|
||||
|
||||
complexity = SelectMultipleField(
|
||||
translate("forms.task_order.complexity.label"),
|
||||
description=translate("forms.task_order.complexity.description"),
|
||||
choices=APPLICATION_COMPLEXITY,
|
||||
default=None,
|
||||
filters=[BaseForm.remove_empty_string],
|
||||
widget=ListWidget(prefix_label=False),
|
||||
option_widget=CheckboxInput(),
|
||||
)
|
||||
|
||||
complexity_other = StringField(
|
||||
translate("forms.task_order.complexity_other_label"),
|
||||
default=None,
|
||||
filters=[BaseForm.remove_empty_string],
|
||||
)
|
||||
|
||||
dev_team = SelectMultipleField(
|
||||
translate("forms.task_order.dev_team.label"),
|
||||
description=translate("forms.task_order.dev_team.description"),
|
||||
choices=DEV_TEAM,
|
||||
default=None,
|
||||
filters=[BaseForm.remove_empty_string],
|
||||
widget=ListWidget(prefix_label=False),
|
||||
option_widget=CheckboxInput(),
|
||||
)
|
||||
|
||||
dev_team_other = StringField(
|
||||
translate("forms.task_order.dev_team_other_label"),
|
||||
default=None,
|
||||
filters=[BaseForm.remove_empty_string],
|
||||
)
|
||||
|
||||
team_experience = RadioField(
|
||||
translate("forms.task_order.team_experience.label"),
|
||||
description=translate("forms.task_order.team_experience.description"),
|
||||
choices=TEAM_EXPERIENCE,
|
||||
default="",
|
||||
validators=[Optional()],
|
||||
)
|
||||
|
@@ -1,5 +1,6 @@
|
||||
from sqlalchemy import Column, String
|
||||
from sqlalchemy.orm import relationship
|
||||
from sqlalchemy.types import ARRAY
|
||||
from itertools import chain
|
||||
|
||||
from atst.models import Base, mixins, types
|
||||
@@ -16,6 +17,15 @@ class Portfolio(Base, mixins.TimestampsMixin, mixins.AuditableMixin):
|
||||
name = Column(String)
|
||||
defense_component = Column(String) # Department of Defense Component
|
||||
|
||||
app_migration = Column(String) # App Migration
|
||||
complexity = Column(ARRAY(String)) # Application Complexity
|
||||
complexity_other = Column(String)
|
||||
description = Column(String)
|
||||
dev_team = Column(ARRAY(String)) # Development Team
|
||||
dev_team_other = Column(String)
|
||||
native_apps = Column(String) # Native Apps
|
||||
team_experience = Column(String) # Team Experience
|
||||
|
||||
applications = relationship(
|
||||
"Application",
|
||||
back_populates="portfolio",
|
||||
|
@@ -1,8 +1,9 @@
|
||||
from datetime import date, timedelta
|
||||
|
||||
from flask import render_template, request as http_request, g
|
||||
from flask import redirect, render_template, url_for, request as http_request, g
|
||||
|
||||
from . import portfolios_bp
|
||||
from atst.forms.portfolio import PortfolioCreationForm
|
||||
from atst.domain.reports import Reports
|
||||
from atst.domain.portfolios import Portfolios
|
||||
from atst.models.permissions import Permissions
|
||||
@@ -19,6 +20,26 @@ def portfolios():
|
||||
return render_template("portfolios/blank_slate.html")
|
||||
|
||||
|
||||
@portfolios_bp.route("/portfolios/new")
|
||||
def new_portfolio():
|
||||
form = PortfolioCreationForm()
|
||||
|
||||
return render_template("portfolios/new.html", form=form)
|
||||
|
||||
|
||||
@portfolios_bp.route("/portfolios", methods=["POST"])
|
||||
def create_portfolio():
|
||||
form = PortfolioCreationForm(http_request.form)
|
||||
|
||||
if form.validate():
|
||||
portfolio = Portfolios.create(user=g.current_user, portfolio_attrs=form.data)
|
||||
return redirect(
|
||||
url_for("applications.portfolio_applications", portfolio_id=portfolio.id)
|
||||
)
|
||||
else:
|
||||
return render_template("portfolios/new.html", form=form), 400
|
||||
|
||||
|
||||
@portfolios_bp.route("/portfolios/<portfolio_id>/reports")
|
||||
@user_can(Permissions.VIEW_PORTFOLIO_REPORTS, message="view portfolio reports")
|
||||
def reports(portfolio_id):
|
||||
|
@@ -242,9 +242,11 @@ class UpdateTaskOrderWorkflow(ShowTaskOrderWorkflow):
|
||||
pf = Portfolios.get(self.user, self.portfolio_id)
|
||||
else:
|
||||
pf = Portfolios.create(
|
||||
self.user,
|
||||
self.form.portfolio_name.data,
|
||||
self.form.defense_component.data,
|
||||
user=self.user,
|
||||
portfolio_attrs={
|
||||
"name": self.form.portfolio_name.data,
|
||||
"defense_component": self.form.defense_component.data,
|
||||
},
|
||||
)
|
||||
self._task_order = TaskOrders.create(portfolio=pf, creator=self.user)
|
||||
TaskOrders.update(self.task_order, **self.task_order_form_data)
|
||||
|
Reference in New Issue
Block a user