2018-09-10 09:55:26 -07:00
|
|
|
from datetime import datetime
|
|
|
|
|
2018-11-13 06:17:06 -08:00
|
|
|
from flask import Blueprint, g
|
2018-10-22 15:31:33 -07:00
|
|
|
from flask_yoloapi import endpoint, parameter
|
2018-09-10 09:55:26 -07:00
|
|
|
from sqlalchemy.exc import IntegrityError
|
|
|
|
|
2018-09-18 15:17:34 -07:00
|
|
|
from grant.comment.models import Comment, comment_schema
|
2018-09-10 09:55:26 -07:00
|
|
|
from grant.milestone.models import Milestone
|
2018-09-25 13:09:25 -07:00
|
|
|
from grant.user.models import User, SocialMedia, Avatar
|
2018-11-13 06:17:06 -08:00
|
|
|
from grant.utils.auth import requires_sm, requires_team_member_auth
|
2018-11-02 09:24:28 -07:00
|
|
|
from .models import Proposal, proposals_schema, proposal_schema, ProposalUpdate, proposal_update_schema, db
|
2018-09-10 09:55:26 -07:00
|
|
|
|
2018-09-18 15:20:17 -07:00
|
|
|
blueprint = Blueprint("proposal", __name__, url_prefix="/api/v1/proposals")
|
2018-09-10 09:55:26 -07:00
|
|
|
|
|
|
|
|
|
|
|
@blueprint.route("/<proposal_id>", methods=["GET"])
|
2018-11-04 10:33:22 -08:00
|
|
|
@endpoint.api()
|
2018-09-10 09:55:26 -07:00
|
|
|
def get_proposal(proposal_id):
|
2018-11-07 09:33:19 -08:00
|
|
|
proposal = Proposal.query.filter_by(id=proposal_id).first()
|
2018-09-10 09:55:26 -07:00
|
|
|
if proposal:
|
|
|
|
dumped_proposal = proposal_schema.dump(proposal)
|
2018-11-04 10:33:22 -08:00
|
|
|
return dumped_proposal
|
2018-09-10 09:55:26 -07:00
|
|
|
else:
|
2018-11-04 10:33:22 -08:00
|
|
|
return {"message": "No proposal matching id"}, 404
|
2018-09-10 09:55:26 -07:00
|
|
|
|
|
|
|
|
|
|
|
@blueprint.route("/<proposal_id>/comments", methods=["GET"])
|
2018-11-04 10:33:22 -08:00
|
|
|
@endpoint.api()
|
2018-09-10 09:55:26 -07:00
|
|
|
def get_proposal_comments(proposal_id):
|
2018-11-07 09:33:19 -08:00
|
|
|
proposal = Proposal.query.filter_by(id=proposal_id).first()
|
2018-09-18 15:17:34 -07:00
|
|
|
if proposal:
|
|
|
|
dumped_proposal = proposal_schema.dump(proposal)
|
2018-11-04 10:33:22 -08:00
|
|
|
return {
|
|
|
|
"proposalId": proposal_id,
|
|
|
|
"totalComments": len(dumped_proposal["comments"]),
|
|
|
|
"comments": dumped_proposal["comments"]
|
|
|
|
}
|
2018-09-10 09:55:26 -07:00
|
|
|
else:
|
2018-11-04 10:33:22 -08:00
|
|
|
return {"message": "No proposal matching id"}, 404
|
2018-09-10 09:55:26 -07:00
|
|
|
|
|
|
|
|
2018-09-18 15:17:34 -07:00
|
|
|
@blueprint.route("/<proposal_id>/comments", methods=["POST"])
|
2018-11-13 06:17:06 -08:00
|
|
|
@requires_sm
|
2018-10-22 15:31:33 -07:00
|
|
|
@endpoint.api(
|
|
|
|
parameter('content', type=str, required=True)
|
|
|
|
)
|
|
|
|
def post_proposal_comments(proposal_id, user_id, content):
|
2018-11-07 09:33:19 -08:00
|
|
|
proposal = Proposal.query.filter_by(id=proposal_id).first()
|
2018-09-18 15:17:34 -07:00
|
|
|
if proposal:
|
2018-11-13 06:17:06 -08:00
|
|
|
comment = Comment(
|
|
|
|
proposal_id=proposal_id,
|
|
|
|
user_id=g.current_user.id,
|
|
|
|
content=content
|
|
|
|
)
|
|
|
|
db.session.add(comment)
|
|
|
|
db.session.commit()
|
|
|
|
dumped_comment = comment_schema.dump(comment)
|
|
|
|
return dumped_comment, 201
|
2018-09-18 15:17:34 -07:00
|
|
|
else:
|
2018-10-22 15:31:33 -07:00
|
|
|
return {"message": "No proposal matching id"}, 404
|
2018-09-18 15:17:34 -07:00
|
|
|
|
|
|
|
|
2018-09-10 09:55:26 -07:00
|
|
|
@blueprint.route("/", methods=["GET"])
|
2018-10-22 15:31:33 -07:00
|
|
|
@endpoint.api(
|
|
|
|
parameter('stage', type=str, required=False)
|
|
|
|
)
|
|
|
|
def get_proposals(stage):
|
2018-09-10 09:55:26 -07:00
|
|
|
if stage:
|
|
|
|
proposals = (
|
|
|
|
Proposal.query.filter_by(stage=stage)
|
2018-11-13 06:17:06 -08:00
|
|
|
.order_by(Proposal.date_created.desc())
|
|
|
|
.all()
|
2018-09-10 09:55:26 -07:00
|
|
|
)
|
|
|
|
else:
|
|
|
|
proposals = Proposal.query.order_by(Proposal.date_created.desc()).all()
|
2018-09-25 13:09:25 -07:00
|
|
|
dumped_proposals = proposals_schema.dump(proposals)
|
2018-10-22 15:31:33 -07:00
|
|
|
return dumped_proposals
|
2018-09-10 09:55:26 -07:00
|
|
|
|
|
|
|
|
2018-09-18 15:20:17 -07:00
|
|
|
@blueprint.route("/", methods=["POST"])
|
2018-11-13 06:17:06 -08:00
|
|
|
@requires_sm
|
2018-10-22 15:31:33 -07:00
|
|
|
@endpoint.api(
|
|
|
|
parameter('crowdFundContractAddress', type=str, required=True),
|
|
|
|
parameter('content', type=str, required=True),
|
|
|
|
parameter('title', type=str, required=True),
|
|
|
|
parameter('milestones', type=list, required=True),
|
|
|
|
parameter('category', type=str, required=True),
|
|
|
|
parameter('team', type=list, required=True)
|
|
|
|
)
|
|
|
|
def make_proposal(crowd_fund_contract_address, content, title, milestones, category, team):
|
2018-11-07 09:33:19 -08:00
|
|
|
existing_proposal = Proposal.query.filter_by(proposal_address=crowd_fund_contract_address).first()
|
2018-10-22 15:31:33 -07:00
|
|
|
if existing_proposal:
|
|
|
|
return {"message": "Oops! Something went wrong."}, 409
|
2018-09-10 09:55:26 -07:00
|
|
|
|
|
|
|
proposal = Proposal.create(
|
|
|
|
stage="FUNDING_REQUIRED",
|
2018-11-07 09:33:19 -08:00
|
|
|
proposal_address=crowd_fund_contract_address,
|
2018-09-10 09:55:26 -07:00
|
|
|
content=content,
|
|
|
|
title=title,
|
|
|
|
category=category
|
|
|
|
)
|
|
|
|
|
2018-09-26 01:46:30 -07:00
|
|
|
db.session.add(proposal)
|
|
|
|
|
2018-09-25 13:09:25 -07:00
|
|
|
if not len(team) > 0:
|
2018-10-22 15:31:33 -07:00
|
|
|
return {"message": "Team must be at least 1"}, 400
|
2018-09-26 01:46:30 -07:00
|
|
|
|
2018-09-25 13:09:25 -07:00
|
|
|
for team_member in team:
|
|
|
|
account_address = team_member.get("accountAddress")
|
|
|
|
display_name = team_member.get("displayName")
|
|
|
|
email_address = team_member.get("emailAddress")
|
|
|
|
title = team_member.get("title")
|
2018-09-26 12:35:22 -07:00
|
|
|
user = User.query.filter(
|
|
|
|
(User.account_address == account_address) | (User.email_address == email_address)).first()
|
2018-09-25 13:09:25 -07:00
|
|
|
if not user:
|
|
|
|
user = User(
|
|
|
|
account_address=account_address,
|
|
|
|
email_address=email_address,
|
|
|
|
display_name=display_name,
|
|
|
|
title=title
|
|
|
|
)
|
|
|
|
db.session.add(user)
|
2018-09-26 01:46:30 -07:00
|
|
|
db.session.flush()
|
2018-09-25 13:09:25 -07:00
|
|
|
|
|
|
|
avatar_data = team_member.get("avatar")
|
|
|
|
if avatar_data:
|
|
|
|
avatar = Avatar(image_url=avatar_data.get('link'), user_id=user.id)
|
|
|
|
db.session.add(avatar)
|
|
|
|
|
|
|
|
social_medias = team_member.get("socialMedias")
|
|
|
|
if social_medias:
|
|
|
|
for social_media in social_medias:
|
|
|
|
sm = SocialMedia(social_media_link=social_media.get("link"), user_id=user.id)
|
|
|
|
db.session.add(sm)
|
|
|
|
|
2018-09-26 01:46:30 -07:00
|
|
|
proposal.team.append(user)
|
2018-09-10 09:55:26 -07:00
|
|
|
|
|
|
|
for each_milestone in milestones:
|
|
|
|
m = Milestone(
|
|
|
|
title=each_milestone["title"],
|
|
|
|
content=each_milestone["description"],
|
|
|
|
date_estimated=datetime.strptime(each_milestone["date"], '%B %Y'),
|
|
|
|
payout_percent=str(each_milestone["payoutPercent"]),
|
|
|
|
immediate_payout=each_milestone["immediatePayout"],
|
|
|
|
proposal_id=proposal.id
|
|
|
|
)
|
|
|
|
|
|
|
|
db.session.add(m)
|
2018-09-26 01:46:30 -07:00
|
|
|
|
2018-09-10 09:55:26 -07:00
|
|
|
try:
|
|
|
|
db.session.commit()
|
|
|
|
except IntegrityError as e:
|
|
|
|
print(e)
|
2018-10-22 15:31:33 -07:00
|
|
|
return {"message": "Oops! Something went wrong."}, 409
|
2018-09-10 09:55:26 -07:00
|
|
|
|
|
|
|
results = proposal_schema.dump(proposal)
|
2018-10-22 15:31:33 -07:00
|
|
|
return results, 201
|
2018-11-02 09:24:28 -07:00
|
|
|
|
|
|
|
|
|
|
|
@blueprint.route("/<proposal_id>/updates", methods=["GET"])
|
|
|
|
@endpoint.api()
|
|
|
|
def get_proposal_updates(proposal_id):
|
2018-11-07 09:33:19 -08:00
|
|
|
proposal = Proposal.query.filter_by(id=proposal_id).first()
|
2018-11-02 09:24:28 -07:00
|
|
|
if proposal:
|
|
|
|
dumped_proposal = proposal_schema.dump(proposal)
|
|
|
|
return dumped_proposal["updates"]
|
|
|
|
else:
|
|
|
|
return {"message": "No proposal matching id"}, 404
|
|
|
|
|
|
|
|
|
|
|
|
@blueprint.route("/<proposal_id>/updates/<update_id>", methods=["GET"])
|
|
|
|
@endpoint.api()
|
|
|
|
def get_proposal_update(proposal_id, update_id):
|
2018-11-07 09:33:19 -08:00
|
|
|
proposal = Proposal.query.filter_by(id=proposal_id).first()
|
2018-11-02 09:24:28 -07:00
|
|
|
if proposal:
|
|
|
|
update = ProposalUpdate.query.filter_by(proposal_id=proposal.id, id=update_id).first()
|
|
|
|
if update:
|
|
|
|
return update
|
|
|
|
else:
|
|
|
|
return {"message": "No update matching id"}
|
|
|
|
else:
|
|
|
|
return {"message": "No proposal matching id"}, 404
|
|
|
|
|
|
|
|
|
|
|
|
@blueprint.route("/<proposal_id>/updates", methods=["POST"])
|
2018-11-13 06:17:06 -08:00
|
|
|
@requires_team_member_auth
|
|
|
|
@requires_sm
|
2018-11-02 09:24:28 -07:00
|
|
|
@endpoint.api(
|
|
|
|
parameter('title', type=str, required=True),
|
|
|
|
parameter('content', type=str, required=True)
|
|
|
|
)
|
|
|
|
def post_proposal_update(proposal_id, title, content):
|
2018-11-13 06:17:06 -08:00
|
|
|
update = ProposalUpdate(
|
|
|
|
proposal_id=g.current_proposal.id,
|
|
|
|
title=title,
|
|
|
|
content=content
|
|
|
|
)
|
|
|
|
db.session.add(update)
|
|
|
|
db.session.commit()
|
2018-11-02 09:24:28 -07:00
|
|
|
|
2018-11-13 06:17:06 -08:00
|
|
|
dumped_update = proposal_update_schema.dump(update)
|
|
|
|
return dumped_update, 201
|