Skip to content

Commit

Permalink
Merge branch 'SCRUM-23-explore-screen' of https://github.com/Generate…
Browse files Browse the repository at this point in the history
…NU/3stones into SCRUM-23-explore-screen
  • Loading branch information
aravgoyal committed Dec 2, 2024
2 parents 1dc7cfd + 5d7dddc commit a87b242
Show file tree
Hide file tree
Showing 88 changed files with 22,099 additions and 3,022 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
/node_modules
*.p12
*.env
.env*
27 changes: 25 additions & 2 deletions backend/internal/controllers/investors.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,30 @@ func (c *InvestorsController) GetProfile(ctx *fiber.Ctx) error {
return ctx.Status(fiber.StatusOK).JSON(investorProfile)
}

func (c *InvestorsController) UpdateProfile(ctx *fiber.Ctx) error {
userId, ok := ctx.Locals("userId").(string)
if !ok {
return &api_errors.INVALID_UUID
}

id, err := uuid.Parse(userId)
if err != nil {
return &api_errors.INVALID_UUID
}

var body models.InvestorProfile
if err := ctx.BodyParser(&body); err != nil {
return &api_errors.INVALID_REQUEST_BODY
}

updatedInvestorProfile, err := transactions.UpdateProfile(c.ServiceParams.DB, id, body)
if err != nil {
return err
}

return ctx.Status(fiber.StatusOK).JSON(updatedInvestorProfile)
}

func (c *InvestorsController) GetPortfolio(ctx *fiber.Ctx) error {
userId, ok := ctx.Locals("userId").(string)
if !ok {
Expand Down Expand Up @@ -119,8 +143,7 @@ func (c *InvestorsController) GetInvestor(ctx *fiber.Ctx) error {

investor := models.Investor{
ID: id,
FirstName: profile.FirstName,
LastName: profile.LastName,
Profile: profile,
TotalInvestmentAmount: totalValue,
InvestmentBreakdown: investments,
}
Expand Down
17 changes: 13 additions & 4 deletions backend/internal/models/investor.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,24 @@ import "github.com/google/uuid"

type Investor struct {
ID uuid.UUID `json:"id"`
FirstName string `json:"first"`
LastName string `json:"last"`
Profile InvestorProfile `json:"profile"`
TotalInvestmentAmount int `json:"total_investment_amount"`
InvestmentBreakdown map[uuid.UUID]int `json:"investment_breakdown"`
}

type InvestorProfile struct {
FirstName string `json:"first"`
LastName string `json:"last"`
FirstName string `json:"first"`
LastName string `json:"last"`
Email string `json:"email"`
PhoneNumber string `json:"phone_number"`
SSN string `json:"ssn"`
Premise string `json:"premise"`
Subpremise string `json:"subpremise"`
Street string `json:"street"`
Locality string `json:"locality"`
State string `json:"state"`
Zipcode string `json:"zipcode"`
ProfilePictureUrl string `json:"profile_picture_url"`
}

type HistoryEntry struct {
Expand Down
1 change: 1 addition & 0 deletions backend/internal/models/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type Project struct {
Latitude float32 `json:"latitude"`
Longitude float32 `json:"longitude"`
Images []ImageLink `json:"images"`
CompletionDate string `json:"completion_date"`
}

type InvestRequestBody struct {
Expand Down
1 change: 1 addition & 0 deletions backend/internal/routes/investors.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ func Investors(params types.RouterParams) {
// api/v1/investors/*
investors := params.Router.Group("/investors")
investors.Get("/profile", params.Auth.Middleware(), investorsController.GetProfile)
investors.Put("/profile", params.Auth.Middleware(), investorsController.UpdateProfile)
investors.Get("/portfolio", params.Auth.Middleware(), investorsController.GetPortfolio)
investors.Get("/history", params.Auth.Middleware(), investorsController.GetHistory)
investors.Get("/", params.Auth.Middleware(), investorsController.GetInvestor)
Expand Down
147 changes: 140 additions & 7 deletions backend/internal/transactions/investors.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package transactions
import (
"context"
"fmt"
"strings"
"time"

"backend/internal/models"
Expand All @@ -27,14 +28,38 @@ func CheckInvestorExists(pool *pgxpool.Pool, investorID string) (bool, error) {
}

func CreateInvestor(pool *pgxpool.Pool, supabaseID string) error {
// Define the INSERT query
query := `
INSERT INTO investors (supabase_id, first_name, last_name)
VALUES ($1, $2, $3);
INSERT INTO investors (
supabase_id,
first_name,
last_name,
email,
phone_number,
ssn,
premise,
street,
locality,
state,
zipcode
)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11);
`

// Execute the query, setting first_name and last_name as empty strings
_, err := pool.Exec(context.Background(), query, supabaseID, "", "")
_, err := pool.Exec(
context.Background(),
query,
supabaseID,
"John",
"Doe",
"[email protected]",
"000-000-0000",
"000-00-0000",
"123",
"Main St",
"Anytown",
"MA",
"12345",
)
if err != nil {
return fmt.Errorf("failed to insert investor: %w", err)
}
Expand All @@ -43,17 +68,125 @@ func CreateInvestor(pool *pgxpool.Pool, supabaseID string) error {
}

func GetProfile(db *pgxpool.Pool, investorId uuid.UUID) (models.InvestorProfile, error) {
query := "SELECT first_name, last_name FROM investors WHERE supabase_id = $1"
query := "SELECT first_name, last_name, email, phone_number, ssn, premise, COALESCE(subpremise, '') as subpremise, street, locality, state, zipcode, COALESCE(profile_picture_url, '') as profile_picture_url FROM investors WHERE supabase_id = $1"

var investorProfile models.InvestorProfile
err := db.QueryRow(context.Background(), query, investorId).Scan(&investorProfile.FirstName, &investorProfile.LastName)
err := db.QueryRow(context.Background(), query, investorId).Scan(
&investorProfile.FirstName,
&investorProfile.LastName,
&investorProfile.Email,
&investorProfile.PhoneNumber,
&investorProfile.SSN,
&investorProfile.Premise,
&investorProfile.Subpremise,
&investorProfile.Street,
&investorProfile.Locality,
&investorProfile.State,
&investorProfile.Zipcode,
&investorProfile.ProfilePictureUrl,
)

if err != nil {
return models.InvestorProfile{}, err
}

return investorProfile, nil
}

func UpdateProfile(db *pgxpool.Pool, investorID uuid.UUID, investorProfile models.InvestorProfile) (models.InvestorProfile, error) {
var setFields []string
var args []interface{}
argPosition := 1

args = append(args, investorID)

// TODO: validation is probably important
if investorProfile.FirstName != "" {
argPosition++
setFields = append(setFields, fmt.Sprintf("first_name = $%d", argPosition))
args = append(args, investorProfile.FirstName)
}

if investorProfile.LastName != "" {
argPosition++
setFields = append(setFields, fmt.Sprintf("last_name = $%d", argPosition))
args = append(args, investorProfile.LastName)
}

if investorProfile.Email != "" {
argPosition++
setFields = append(setFields, fmt.Sprintf("email = $%d", argPosition))
args = append(args, investorProfile.Email)
}

if investorProfile.PhoneNumber != "" {
argPosition++
setFields = append(setFields, fmt.Sprintf("phone_number = $%d", argPosition))
args = append(args, investorProfile.PhoneNumber)
}

if investorProfile.SSN != "" {
argPosition++
setFields = append(setFields, fmt.Sprintf("ssn = $%d", argPosition))
args = append(args, investorProfile.SSN)
}

if investorProfile.Premise != "" {
argPosition++
setFields = append(setFields, fmt.Sprintf("premise = $%d", argPosition))
args = append(args, investorProfile.Premise)
}

if investorProfile.Subpremise != "" {
argPosition++
setFields = append(setFields, fmt.Sprintf("subpremise = $%d", argPosition))
args = append(args, investorProfile.Subpremise)
}

if investorProfile.Street != "" {
argPosition++
setFields = append(setFields, fmt.Sprintf("street = $%d", argPosition))
args = append(args, investorProfile.Street)
}

if investorProfile.Locality != "" {
argPosition++
setFields = append(setFields, fmt.Sprintf("locality = $%d", argPosition))
args = append(args, investorProfile.Locality)
}

if investorProfile.State != "" {
argPosition++
setFields = append(setFields, fmt.Sprintf("state = $%d", argPosition))
args = append(args, investorProfile.State)
}

if investorProfile.Zipcode != "" {
argPosition++
setFields = append(setFields, fmt.Sprintf("zipcode = $%d", argPosition))
args = append(args, investorProfile.Zipcode)
}

if investorProfile.ProfilePictureUrl != "" {
argPosition++
setFields = append(setFields, fmt.Sprintf("profile_picture_url = $%d", argPosition))
args = append(args, investorProfile.ProfilePictureUrl)
}

// If no fields to update, return early
if len(setFields) == 0 {
return GetProfile(db, investorID)
}

query := fmt.Sprintf("UPDATE investors SET %s WHERE supabase_id = $1", strings.Join(setFields, ", "))
_, err := db.Exec(context.Background(), query, args...)
if err != nil {
return models.InvestorProfile{}, err
}

return GetProfile(db, investorID)
}

func GetHistory(db *pgxpool.Pool, investorID uuid.UUID, limit int, offset int) ([]models.HistoryEntry, error) {
query := "SELECT created_at, project_id, funded_cents FROM investor_investments WHERE investor_id = $1 ORDER BY created_at LIMIT $2 OFFSET $3"
rows, err := db.Query(context.Background(), query, investorID, limit, offset)
Expand Down
6 changes: 4 additions & 2 deletions backend/internal/transactions/projects.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
func GetProjects(db *pgxpool.Pool) ([]models.Project, error) {
rows, err := db.Query(
context.Background(),
"SELECT id, developer_id, title, description, completed, funding_goal_cents, milestone, premise, street, locality, state, zipcode, ST_X(coordinates::geometry) as latitude, ST_Y(coordinates::geometry) as longitude FROM projects")
"SELECT id, developer_id, title, description, completed, funding_goal_cents, milestone, completion_date, premise, street, locality, state, zipcode, ST_X(coordinates::geometry) as latitude, ST_Y(coordinates::geometry) as longitude FROM projects")
if err != nil {
return nil, err
}
Expand All @@ -34,6 +34,7 @@ func GetProjects(db *pgxpool.Pool) ([]models.Project, error) {
&project.Completed,
&project.FundingGoalCents,
&project.Milestone,
&project.CompletionDate,
&project.Premise,
&project.Street,
&project.Locality,
Expand Down Expand Up @@ -72,7 +73,7 @@ func GetProjectById(db *pgxpool.Pool, id uuid.UUID) (*models.Project, error) {
// Execute the query with the provided context and developer ID
row := db.QueryRow(
context.Background(),
"SELECT id, developer_id, title, description, completed, funding_goal_cents, milestone, premise, street, locality, state, zipcode, ST_X(coordinates::geometry) as latitude, ST_Y(coordinates::geometry) as longitude FROM projects WHERE ID = $1",
"SELECT id, developer_id, title, description, completed, funding_goal_cents, milestone, completion_date, premise, street, locality, state, zipcode, ST_X(coordinates::geometry) as latitude, ST_Y(coordinates::geometry) as longitude FROM projects WHERE ID = $1",
id)

var project models.Project
Expand All @@ -84,6 +85,7 @@ func GetProjectById(db *pgxpool.Pool, id uuid.UUID) (*models.Project, error) {
&project.Completed,
&project.FundingGoalCents,
&project.Milestone,
&project.CompletionDate,
&project.Premise,
&project.Street,
&project.Locality,
Expand Down
13 changes: 12 additions & 1 deletion backend/supabase/migrations/20240910200423_initialize.sql
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,19 @@ CREATE TABLE investors (
created_at timestamp WITH time zone NOT NULL DEFAULT CURRENT_TIMESTAMP,
first_name varchar(256) NOT NULL,
last_name varchar(256) NOT NULL,
email varchar(256) NOT NULL,
phone_number varchar(20) NOT NULL,
ssn varchar(20) NOT NULL,
premise varchar(10) NOT NULL,
subpremise varchar(10),
street varchar(256) NOT NULL,
locality varchar(256) NOT NULL,
state us_state NOT NULL,
zipcode varchar(10) NOT NULL,
access_token varchar(256),
cash_balance_cents bigint NOT NULL DEFAULT 0,
item_id varchar(256)
item_id varchar(256),
profile_picture_url varchar(256)
);

CREATE TABLE developers (
Expand All @@ -102,6 +112,7 @@ CREATE TABLE projects (
completed boolean NOT NULL DEFAULT FALSE,
funding_goal_cents bigint NOT NULL, -- Total funding is in cents - 1234 = $12.34
milestone varchar(256) NOT NULL, -- Very basic but I think this is OK for MVP
completion_date varchar(256) NOT NULL,
premise varchar(10) NOT NULL,
subpremise varchar(10),
street varchar(256) NOT NULL,
Expand Down
40 changes: 36 additions & 4 deletions backend/supabase/seed.sql
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,41 @@ INSERT INTO
auth.users
);

-- test investor data matching auth users
INSERT INTO
investors (
supabase_id,
first_name,
last_name,
email,
phone_number,
ssn,
premise,
subpremise,
street,
locality,
state,
zipcode,
profile_picture_url
) (
select
id,
'Test',
'User' || (ROW_NUMBER() OVER ()),
email,
'555-555-5555',
'123-45-6789',
'123',
null,
'Main St',
'Boston',
'MA',
'02115',
'https://api.dicebear.com/7.x/avataaars/svg?seed=' || (ROW_NUMBER() OVER ())
from
auth.users
);

-- SQLBook: Code
INSERT INTO contributors (first_name, last_name, email) VALUES ('Michael', 'Brennan', '[email protected]');
INSERT INTO contributors (first_name, last_name, email) VALUES ('Ryan', 'Saperstein', '[email protected]');
Expand All @@ -74,7 +109,7 @@ INSERT INTO developers (id, name, description, premise, street, locality, state,
INSERT INTO developers (id, name, description, premise, street, locality, state, zipcode) VALUES ('56ebee48-d844-4fcd-aa58-fb71688c3e81', 'Arav', 'Developer for Generate', '7', 'Speare Pl', 'Boston', 'MA', '02115');

INSERT INTO projects (id, developer_id, title, description, completed, funding_goal_cents, milestone, premise, street, locality, state, zipcode, coordinates) VALUES ('c3733692-5a86-441f-8ad0-9c32c648bb72', '56ebee48-d844-4fcd-aa58-fb71688c3e81', 'Bowser Castle', 'A big fiery castle sitting on prime real estate', 'FALSE', '100000000', 'Land Control Secured', '7', 'Speare Pl', 'Boston', 'MA', '02115', ST_GeogFromText('SRID=4326;POINT(42.34135 -71.09007)'));
INSERT INTO projects (id, developer_id, title, description, completed, funding_goal_cents, milestone, premise, street, locality, state, zipcode, coordinates) VALUES ('d09c8f0f-13d3-4336-92e9-b0b2c8bce570', '56ebee48-d844-4fcd-aa58-fb71688c3e81', 'Spongebob Pineapple', 'A pineapple under the sea', 'TRUE', '18000000', 'Construction Completed', '716', 'Columbus Ave', 'Boston', 'MA', '02120', ST_GeogFromText('SRID=4326;POINT(42.33772 -71.08530)'));
INSERT INTO projects (id, developer_id, title, description, completed, funding_goal_cents, milestone, premise, street, locality, state, zipcode, coordinates) VALUES ('d09c8f0f-13d3-4336-92e9-b0b2c8bce570', '56ebee48-d844-4fcd-aa58-fb71688c3e81', 'Spongebob Pineapple', 'A pineapple under the sea', 'TRUE', '18000000', 'Construction Complete', '716', 'Columbus Ave', 'Boston', 'MA', '02120', ST_GeogFromText('SRID=4326;POINT(42.33772 -71.08530)'));

INSERT INTO project_images (project_id, image_url) VALUES ('c3733692-5a86-441f-8ad0-9c32c648bb72', 'https://cdn2.thecatapi.com/images/MTk3OTMzMg.jpg');
INSERT INTO project_images (project_id, image_url) VALUES ('c3733692-5a86-441f-8ad0-9c32c648bb72', 'https://cdn2.thecatapi.com/images/MjA1MTYzNg.jpg');
Expand All @@ -84,9 +119,6 @@ INSERT INTO project_images (project_id, image_url) VALUES ('d09c8f0f-13d3-4336-9
INSERT INTO project_images (project_id, image_url) VALUES ('d09c8f0f-13d3-4336-92e9-b0b2c8bce570', 'https://cdn2.thecatapi.com/images/MjA1MTYzNg.jpg');
INSERT INTO project_images (project_id, image_url) VALUES ('d09c8f0f-13d3-4336-92e9-b0b2c8bce570', 'https://cdn2.thecatapi.com/images/MuEGe1-Sz.jpg');

INSERT INTO investors (supabase_id, first_name, last_name) VALUES ((SELECT id from auth.users where email='[email protected]'), 'Dwight', 'Howard');
INSERT INTO investors (supabase_id, first_name, last_name) VALUES ((SELECT id from auth.users where email='[email protected]'), 'Taj', 'Gibson');

INSERT INTO investor_investments (id, project_id, investor_id, funded_cents) VALUES ('bdd66406-64bd-41a5-b797-a486751ea429', 'c3733692-5a86-441f-8ad0-9c32c648bb72', (SELECT id FROM auth.users WHERE email='[email protected]'), '1200');
INSERT INTO investor_investments (id, project_id, investor_id, funded_cents) VALUES ('ba995313-1b8a-4b4e-ad02-0b72efd22309', 'c3733692-5a86-441f-8ad0-9c32c648bb72', (SELECT id FROM auth.users WHERE email='[email protected]'), '400');
INSERT INTO investor_investments (id, project_id, investor_id, funded_cents) VALUES ('de194a16-c0be-4519-bf6a-9a3bceea1b42', 'c3733692-5a86-441f-8ad0-9c32c648bb72', (SELECT id FROM auth.users WHERE email='[email protected]'), '800');
Expand Down
Loading

0 comments on commit a87b242

Please sign in to comment.