Use Enum for request statuses
This commit is contained in:
parent
0c9005aaf6
commit
49b9fca793
@ -1,9 +1,9 @@
|
|||||||
from enum import Enum
|
|
||||||
from sqlalchemy import exists, and_
|
from sqlalchemy import exists, and_
|
||||||
from sqlalchemy.orm.exc import NoResultFound
|
from sqlalchemy.orm.exc import NoResultFound
|
||||||
from sqlalchemy.orm.attributes import flag_modified
|
from sqlalchemy.orm.attributes import flag_modified
|
||||||
|
|
||||||
from atst.models import Request, RequestStatusEvent
|
from atst.models.request import Request
|
||||||
|
from atst.models.request_status_event import RequestStatusEvent, RequestStatus
|
||||||
from atst.database import db
|
from atst.database import db
|
||||||
|
|
||||||
from .exceptions import NotFoundError
|
from .exceptions import NotFoundError
|
||||||
@ -27,13 +27,6 @@ def deep_merge(source, destination: dict):
|
|||||||
return _deep_merge(source, dict(destination))
|
return _deep_merge(source, dict(destination))
|
||||||
|
|
||||||
|
|
||||||
class RequestStatus(Enum):
|
|
||||||
STARTED = "started"
|
|
||||||
PENDING_FINANCIAL_VERIFICATION = "pending_financial_verification"
|
|
||||||
PENDING_CCPO_APPROVAL = "pending_ccpo_approval"
|
|
||||||
APPROVED = "approved"
|
|
||||||
|
|
||||||
|
|
||||||
class Requests(object):
|
class Requests(object):
|
||||||
AUTO_APPROVE_THRESHOLD = 1000000
|
AUTO_APPROVE_THRESHOLD = 1000000
|
||||||
|
|
||||||
@ -118,7 +111,7 @@ class Requests(object):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def set_status(cls, request: Request, status: RequestStatus):
|
def set_status(cls, request: Request, status: RequestStatus):
|
||||||
status_event = RequestStatusEvent(new_status=status.value)
|
status_event = RequestStatusEvent(new_status=status)
|
||||||
request.status_events.append(status_event)
|
request.status_events.append(status_event)
|
||||||
return request
|
return request
|
||||||
|
|
||||||
|
@ -24,3 +24,4 @@ class Request(Base):
|
|||||||
|
|
||||||
def set_status(self, status):
|
def set_status(self, status):
|
||||||
self.status_events.append(status)
|
self.status_events.append(status)
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
from sqlalchemy import Column, func, ForeignKey
|
from enum import Enum, auto
|
||||||
from sqlalchemy.types import DateTime, String, BigInteger
|
from sqlalchemy import Column, func, ForeignKey, Enum as SQLAEnum
|
||||||
|
from sqlalchemy.types import DateTime, BigInteger
|
||||||
from sqlalchemy.schema import Sequence
|
from sqlalchemy.schema import Sequence
|
||||||
from sqlalchemy.dialects.postgresql import UUID
|
from sqlalchemy.dialects.postgresql import UUID
|
||||||
|
|
||||||
@ -7,11 +8,18 @@ from atst.models import Base
|
|||||||
from atst.models.types import Id
|
from atst.models.types import Id
|
||||||
|
|
||||||
|
|
||||||
|
class RequestStatus(Enum):
|
||||||
|
STARTED = auto()
|
||||||
|
PENDING_FINANCIAL_VERIFICATION = auto()
|
||||||
|
PENDING_CCPO_APPROVAL = auto()
|
||||||
|
APPROVED = auto()
|
||||||
|
|
||||||
|
|
||||||
class RequestStatusEvent(Base):
|
class RequestStatusEvent(Base):
|
||||||
__tablename__ = "request_status_events"
|
__tablename__ = "request_status_events"
|
||||||
|
|
||||||
id = Id()
|
id = Id()
|
||||||
new_status = Column(String())
|
new_status = Column(SQLAEnum(RequestStatus))
|
||||||
time_created = Column(DateTime(timezone=True), server_default=func.now())
|
time_created = Column(DateTime(timezone=True), server_default=func.now())
|
||||||
request_id = Column(
|
request_id = Column(
|
||||||
UUID(as_uuid=True), ForeignKey("requests.id", ondelete="CASCADE")
|
UUID(as_uuid=True), ForeignKey("requests.id", ondelete="CASCADE")
|
||||||
|
@ -3,6 +3,7 @@ from uuid import uuid4
|
|||||||
|
|
||||||
from atst.domain.exceptions import NotFoundError
|
from atst.domain.exceptions import NotFoundError
|
||||||
from atst.domain.requests import Requests
|
from atst.domain.requests import Requests
|
||||||
|
from atst.models.request_status_event import RequestStatus
|
||||||
|
|
||||||
from tests.factories import RequestFactory
|
from tests.factories import RequestFactory
|
||||||
|
|
||||||
@ -25,25 +26,25 @@ def test_nonexistent_request_raises():
|
|||||||
|
|
||||||
def test_new_request_has_started_status():
|
def test_new_request_has_started_status():
|
||||||
request = Requests.create(uuid4(), {})
|
request = Requests.create(uuid4(), {})
|
||||||
assert request.status == "started"
|
assert request.status == RequestStatus.STARTED
|
||||||
|
|
||||||
|
|
||||||
def test_auto_approve_less_than_1m(new_request):
|
def test_auto_approve_less_than_1m(new_request):
|
||||||
new_request.body = {"details_of_use": {"dollar_value": 999999}}
|
new_request.body = {"details_of_use": {"dollar_value": 999999}}
|
||||||
request = Requests.submit(new_request)
|
request = Requests.submit(new_request)
|
||||||
|
|
||||||
assert request.status == "pending_financial_verification"
|
assert request.status == RequestStatus.PENDING_FINANCIAL_VERIFICATION
|
||||||
|
|
||||||
|
|
||||||
def test_dont_auto_approve_if_dollar_value_is_1m_or_above(new_request):
|
def test_dont_auto_approve_if_dollar_value_is_1m_or_above(new_request):
|
||||||
new_request.body = {"details_of_use": {"dollar_value": 1000000}}
|
new_request.body = {"details_of_use": {"dollar_value": 1000000}}
|
||||||
request = Requests.submit(new_request)
|
request = Requests.submit(new_request)
|
||||||
|
|
||||||
assert request.status == "pending_ccpo_approval"
|
assert request.status == RequestStatus.PENDING_CCPO_APPROVAL
|
||||||
|
|
||||||
|
|
||||||
def test_dont_auto_approve_if_no_dollar_value_specified(new_request):
|
def test_dont_auto_approve_if_no_dollar_value_specified(new_request):
|
||||||
new_request.body = {"details_of_use": {}}
|
new_request.body = {"details_of_use": {}}
|
||||||
request = Requests.submit(new_request)
|
request = Requests.submit(new_request)
|
||||||
|
|
||||||
assert request.status == "pending_ccpo_approval"
|
assert request.status == RequestStatus.PENDING_CCPO_APPROVAL
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import factory
|
import factory
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
||||||
from atst.models import Request, RequestStatusEvent
|
from atst.models.request import Request
|
||||||
|
from atst.models.request_status_event import RequestStatusEvent, RequestStatus
|
||||||
from atst.models.pe_number import PENumber
|
from atst.models.pe_number import PENumber
|
||||||
from atst.models.task_order import TaskOrder
|
from atst.models.task_order import TaskOrder
|
||||||
from atst.models.user import User
|
from atst.models.user import User
|
||||||
@ -9,34 +10,31 @@ from atst.models.role import Role
|
|||||||
|
|
||||||
|
|
||||||
class RequestStatusFactory(factory.alchemy.SQLAlchemyModelFactory):
|
class RequestStatusFactory(factory.alchemy.SQLAlchemyModelFactory):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = RequestStatusEvent
|
model = RequestStatusEvent
|
||||||
|
|
||||||
|
|
||||||
class RequestFactory(factory.alchemy.SQLAlchemyModelFactory):
|
class RequestFactory(factory.alchemy.SQLAlchemyModelFactory):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Request
|
model = Request
|
||||||
|
|
||||||
id = factory.Sequence(lambda x: uuid4())
|
id = factory.Sequence(lambda x: uuid4())
|
||||||
status_events = factory.RelatedFactory(RequestStatusFactory, "request", new_status="started")
|
status_events = factory.RelatedFactory(
|
||||||
|
RequestStatusFactory, "request", new_status=RequestStatus.STARTED
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class PENumberFactory(factory.alchemy.SQLAlchemyModelFactory):
|
class PENumberFactory(factory.alchemy.SQLAlchemyModelFactory):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = PENumber
|
model = PENumber
|
||||||
|
|
||||||
|
|
||||||
class TaskOrderFactory(factory.alchemy.SQLAlchemyModelFactory):
|
class TaskOrderFactory(factory.alchemy.SQLAlchemyModelFactory):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = TaskOrder
|
model = TaskOrder
|
||||||
|
|
||||||
|
|
||||||
class RoleFactory(factory.alchemy.SQLAlchemyModelFactory):
|
class RoleFactory(factory.alchemy.SQLAlchemyModelFactory):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Role
|
model = Role
|
||||||
|
|
||||||
@ -44,7 +42,6 @@ class RoleFactory(factory.alchemy.SQLAlchemyModelFactory):
|
|||||||
|
|
||||||
|
|
||||||
class UserFactory(factory.alchemy.SQLAlchemyModelFactory):
|
class UserFactory(factory.alchemy.SQLAlchemyModelFactory):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
|
|
||||||
@ -53,4 +50,3 @@ class UserFactory(factory.alchemy.SQLAlchemyModelFactory):
|
|||||||
first_name = "Fake"
|
first_name = "Fake"
|
||||||
last_name = "User"
|
last_name = "User"
|
||||||
atat_role = factory.SubFactory(RoleFactory)
|
atat_role = factory.SubFactory(RoleFactory)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user