From 54b0d58ffaba0dc54a053bc291199afb213063db Mon Sep 17 00:00:00 2001 From: Danny Skubak Date: Thu, 10 Oct 2019 20:12:38 -0400 Subject: [PATCH] Disallow Proposal Submissions to Expired RFPs (#25) * disallow rfp proposal submissions after close * Add closed tag to closed RFPs --- backend/grant/proposal/views.py | 7 +++- frontend/client/components/RFP/index.tsx | 46 +++++++++++++++--------- 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/backend/grant/proposal/views.py b/backend/grant/proposal/views.py index eba7ed00..50c016fb 100644 --- a/backend/grant/proposal/views.py +++ b/backend/grant/proposal/views.py @@ -1,4 +1,5 @@ from decimal import Decimal +from datetime import datetime from flask import Blueprint, g, request, current_app from marshmallow import fields, validate @@ -25,7 +26,7 @@ from grant.utils.auth import ( internal_webhook ) from grant.utils.enums import Category -from grant.utils.enums import ProposalStatus, ProposalStage, ContributionStatus +from grant.utils.enums import ProposalStatus, ProposalStage, ContributionStatus, RFPStatus from grant.utils.exceptions import ValidationException from grant.utils.misc import is_email, make_url, from_zat, make_explore_url from .models import ( @@ -187,6 +188,10 @@ def make_proposal_draft(rfp_id): rfp = RFP.query.filter_by(id=rfp_id).first() if not rfp: return {"message": "The request this proposal was made for doesn’t exist"}, 400 + if datetime.now() > rfp.date_closes: + return {"message": "The request this proposal was made for has expired"}, 400 + if rfp.status == RFPStatus.CLOSED: + return {"message": "The request this proposal was made for has been closed"}, 400 proposal.category = rfp.category rfp.proposals.append(proposal) db.session.add(rfp) diff --git a/frontend/client/components/RFP/index.tsx b/frontend/client/components/RFP/index.tsx index 1278f825..fd81c57d 100644 --- a/frontend/client/components/RFP/index.tsx +++ b/frontend/client/components/RFP/index.tsx @@ -13,6 +13,7 @@ import Markdown from 'components/Markdown'; import ProposalCard from 'components/Proposals/ProposalCard'; import UnitDisplay from 'components/UnitDisplay'; import HeaderDetails from 'components/HeaderDetails'; +import { RFP_STATUS } from 'api/constants'; import './index.less'; interface OwnProps { @@ -48,6 +49,7 @@ class RFPDetail extends React.Component { } } + const isLive = rfp.status === RFP_STATUS.LIVE; const tags = []; if (rfp.matching) { @@ -66,6 +68,14 @@ class RFPDetail extends React.Component { ); } + if (!isLive) { + tags.push( + + Closed + + ); + } + return (
@@ -117,23 +127,25 @@ class RFPDetail extends React.Component {
)} -
- -
- Ready to take on this request?{' '} - - - -
-
-
+ {isLive && ( +
+ +
+ Ready to take on this request?{' '} + + + +
+
+
+ )} ); }