Proposal milestone date validation

This commit is contained in:
Daniel Ternyak 2019-07-24 13:29:11 -05:00
parent cddf392c50
commit 36c150afcd
No known key found for this signature in database
GPG Key ID: DF212D2DC5D0E245
4 changed files with 54 additions and 29 deletions

View File

@ -309,17 +309,6 @@ class Proposal(db.Model):
payout_total += p
try:
present = datetime.datetime.today().replace(day=1)
if present > milestone.date_estimated:
raise ValidationException("Milestone date estimate must be in the future ")
except Exception as e:
current_app.logger.warn(
f"Unexpected validation error - client prohibits {e}"
)
raise ValidationException("Date estimate is not a valid datetime")
if payout_total != 100.0:
raise ValidationException("Payout percentages of milestones must add up to exactly 100%")
@ -358,6 +347,14 @@ class Proposal(db.Model):
# Then run through regular validation
Proposal.simple_validate(vars(self))
# only do this when user submits for approval, there is a chance the dates will
# be passed by the time admin approval / user publishing occurs
def validate_milestone_dates(self):
present = datetime.datetime.today().replace(day=1, hour=0, minute=0, second=0, microsecond=0)
for milestone in self.milestones:
if present > milestone.date_estimated:
raise ValidationException("Milestone date estimate must be in the future ")
@staticmethod
def create(**kwargs):
Proposal.simple_validate(kwargs)
@ -475,6 +472,7 @@ class Proposal(db.Model):
# state: status (DRAFT || REJECTED) -> (PENDING || STAKING)
def submit_for_approval(self):
self.validate_publishable()
self.validate_milestone_dates()
allowed_statuses = [ProposalStatus.DRAFT, ProposalStatus.REJECTED]
# specific validation
if self.status not in allowed_statuses:

View File

@ -56,6 +56,7 @@ typings/
# dotenv environment variables file
.env
.env.testnet
# next.js build output
.next

View File

@ -161,7 +161,9 @@ const MilestoneFields = ({
}
format="MMMM YYYY"
allowClear={false}
onChange={time => onChange(index, { ...milestone, dateEstimated: time.unix() })}
onChange={time =>
onChange(index, { ...milestone, dateEstimated: time.startOf('month').unix() })
}
disabled={milestone.immediatePayout}
disabledDate={current => {
if (!previousMilestoneDateEstimate) {

View File

@ -1,4 +1,11 @@
import { ProposalDraft, STATUS, MILESTONE_STAGE, PROPOSAL_ARBITER_STATUS } from 'types';
import {
ProposalDraft,
STATUS,
MILESTONE_STAGE,
PROPOSAL_ARBITER_STATUS,
CreateMilestone,
} from 'types';
import moment from 'moment';
import { User } from 'types';
import {
getAmountError,
@ -127,23 +134,9 @@ export function getCreateErrors(
// Milestones
if (milestones) {
let cumulativeMilestonePct = 0;
let lastMsEst: CreateMilestone['dateEstimated'] = 0;
const milestoneErrors = milestones.map((ms, idx) => {
if (!ms.title) {
return 'Title is required';
} else if (ms.title.length > 40) {
return 'Title length can only be 40 characters maximum';
}
if (!ms.content) {
return 'Description is required';
} else if (ms.content.length > 200) {
return 'Description can only be 200 characters maximum';
}
if (!ms.dateEstimated) {
return 'Estimate date is required';
}
// check payout first so we collect the cumulativePayout even if other fields are invalid
if (!ms.payoutPercent) {
return 'Payout percent is required';
} else if (Number.isNaN(parseInt(ms.payoutPercent, 10))) {
@ -158,6 +151,37 @@ export function getCreateErrors(
// Last one shows percentage errors
cumulativeMilestonePct += parseInt(ms.payoutPercent, 10);
if (!ms.title) {
return 'Title is required';
} else if (ms.title.length > 40) {
return 'Title length can only be 40 characters maximum';
}
if (!ms.content) {
return 'Description is required';
} else if (ms.content.length > 200) {
return 'Description can only be 200 characters maximum';
}
if (!ms.dateEstimated) {
return 'Estimate date is required';
} else {
// FE validation on milestone estimation
if (
ms.dateEstimated <
moment(Date.now())
.startOf('month')
.unix()
) {
return 'Estimate date should be in the future';
}
if (ms.dateEstimated <= lastMsEst) {
return 'Estimate date should be later than previous estimate date';
}
lastMsEst = ms.dateEstimated;
}
if (
idx === milestones.length - 1 &&
cumulativeMilestonePct !== 100 &&