Proposal milestone date validation
This commit is contained in:
parent
cddf392c50
commit
36c150afcd
|
@ -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:
|
||||
|
|
|
@ -56,6 +56,7 @@ typings/
|
|||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.testnet
|
||||
|
||||
# next.js build output
|
||||
.next
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 &&
|
||||
|
|
Loading…
Reference in New Issue