diff --git a/setupdb.sh b/setupdb.sh index b611d2d..a637570 100644 --- a/setupdb.sh +++ b/setupdb.sh @@ -17,6 +17,16 @@ sudo -u postgres psql -c "CREATE TABLE requests( upFrontPaid boolean, onDeliverPaid boolean ); - " cavecomm - +sudo -u postgres psql -c "CREATE TABLE freelancers( + id INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + emailAddress text, + name text UNIQUE, + generalInformation text, + basicInformation text, + stripeAccountInformation text, + cryptoWalletAddresses text[][], + commissionLimit int, + templates text[][] + ); +" cavecomm diff --git a/src/database.cpp b/src/database.cpp index 62e21ce..09655f3 100644 --- a/src/database.cpp +++ b/src/database.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include "crow.h" @@ -12,15 +13,40 @@ namespace Database { //Valid names for the JSON const static std::string JSON_ITEM_NAMES[] = {"id", "customerEmailAddress", "freelancer", "templateName", "currencyPreference", "priceUpFront", "priceOnDeliver", "requestDescription", "accepted", "upFrontInvoiceID", "onDeliverInvoiceID", "upFrontPaid", "onDeliverPaid"}; - //Name and Statement for prepared statement to insert an item into Requests + /* + * Name and Statement for prepared statement to insert an item into Requests + * Takes the name of the freelancer and the template and resolves them to create the request + * todo:validate + * todo:createAlternative + */ const static std::string PREPARED_STATEMENT_INSERT_ITEM_IN_REQUESTS = "insertItemInRequests"; - const static std::string SQL_STATEMENT_INSERT_ITEM_IN_REQUESTS = "INSERT INTO requests(id, customerEmailAddress, freelancer, templateName, currencyPreference, priceUpFront, priceOnDeliver, requestDescription, accepted, upFrontInvoiceID, onDeliverInvoiceID, upFrontPaid, onDeliverPaid) VALUES(DEFAULT, $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12 );"; + const static std::string SQL_STATEMENT_INSERT_ITEM_IN_REQUESTS = "INSERT INTO requests(id, customerEmailAddress, freelancerid , templateid , currencyPreference, priceUpFront, priceOnDeliver, requestDescription, accepted, upFrontInvoiceID, onDeliverInvoiceID, upFrontPaid, onDeliverPaid) VALUES(DEFAULT, $1, (select id from freelancers where name = $2), (select id from templates where name = $3), $4, $5, $6, $7, $8, $9, $10, $11, $12 );"; + /* * Name and Statement for prepared statement to select an item based on a given ID * Case for boolean return values because the default return value is f/t instead of 0/1 or false/true + * todo:validate */ const static std::string PREPARED_STATEMENT_SELECT_ITEM_BY_ID = "selectItemByID"; - const static std::string SQL_STATEMENT_SELECT_ITEM_BY_ID = "SELECT id , customerEmailAddress, freelancer, templateName, currencyPreference, priceUpFront, priceOnDeliver, requestDescription, (CASE WHEN requests.accepted THEN 1 ELSE 0 END) AS accepted, upFrontInvoiceID, onDeliverInvoiceID, (CASE WHEN requests.upFrontPaid THEN 1 ELSE 0 END) AS upFrontPaid, (CASE WHEN requests.onDeliverPaid THEN 1 ELSE 0 END) AS onDeliverPaid FROM requests WHERE id=$1;"; + const static std::string SQL_STATEMENT_SELECT_ITEM_BY_ID = "SELECT requests.id , customerEmailAddress, freelancers.name, templates.name, currencyPreference, priceUpFront, priceOnDeliver, requestDescription, (CASE WHEN requests.accepted THEN 1 ELSE 0 END) AS accepted, upFrontInvoiceID, onDeliverInvoiceID, (CASE WHEN requests.upFrontPaid THEN 1 ELSE 0 END) AS upFrontPaid, (CASE WHEN requests.onDeliverPaid THEN 1 ELSE 0 END) AS onDeliverPaid FROM requests INNER JOIN freelancers ON freelancers.id=requests.freelancerID INNER JOIN templates ON templates.id=requests.templateID WHERE requests.id=$1;"; + + /* + * Name and Statement for prepared statement to select a freelancer based on a given id + */ + const static std::string PREPARED_STATEMENT_SELECT_FREELANCER = "selectFreelancer"; + const static std::string SQL_STATEMENT_SELECT_FREELANCER = "select id, name, generalinformation, basicinformation from freelancers WHERE id=$1;"; + + /* + * Name and Statement for prepared statement to select a freelancers templates based on a given freelancer id + */ + const static std::string PREPARED_STATEMENT_SELECT_FREELANCER_TEMPLATES = "selectFreelancerTemplates"; + const static std::string SQL_STATEMENT_SELECT_FREELANCER_TEMPLATES = "select id, name, content from templates where freelancerid = $1 order by id;"; + + /* + * Selects freelancers, their basicInfo and if the commissions are closed/open ordered by name. + * Delivers if the commission limit has been reached and if the commissions are closed based on the accepted/completed state of the freelancers requests + */ + const static std::string SQL_Statement_SELECT_FREELANCERS_WITHCOMMISSIONSSTATE = "select id, name, basicInformation , (case when (commissionlimit <= (select count(*) as requestCount from requests where requests.accepted = true and requests.completed = false and requests.freelancerid = freelancers.id group by freelancers.id)) then 'Closed' else 'Open' end) as commissionsclosed from freelancers order by name;"; /* * Struct Representing an item in Requests @@ -29,7 +55,9 @@ namespace Database { int id; std::string customerEmailAddress; std::string freelancer; + std::string freelancerid; std::string templateName; + std::string templateNameid; std::string currencyPreference; std::string priceUpFront; std::string priceOnDeliver; @@ -87,6 +115,17 @@ namespace Database { return result; } + /* + * Executes the prepared statement SELECT_ITEM_BY_ID + * Takes an open pqxx::connection + */ + pqxx::result executeStatement_SELECT_FREELANCERS_WITHCOMMISSIONSSTATE(pqxx::connection &connection) { + pqxx::work work(connection); + pqxx::result result = work.exec(SQL_Statement_SELECT_FREELANCERS_WITHCOMMISSIONSSTATE); + work.commit(); + return result; + } + /* * Executes the prepared statement SELECT_ITEM_BY_ID * Takes an open pqxx::connection and the id to select by @@ -99,6 +138,32 @@ namespace Database { return result; } + /* + * Executes the prepared statement SELECT_FREELANCER + * Takes an open pqxx::connection and the id to select by + */ + pqxx::result executePreparedStatement_SELECT_FREELANCER(pqxx::connection &connection, int freelancerID) { + connection.prepare(PREPARED_STATEMENT_SELECT_FREELANCER, SQL_STATEMENT_SELECT_FREELANCER); + pqxx::work work(connection); + pqxx::result result = work.exec_prepared(PREPARED_STATEMENT_SELECT_FREELANCER, freelancerID); + work.commit(); + return result; + } + + /* + * Executes the prepared statement SELECT_FREELANCER_TEMPLATES + * Takes an open pqxx::connection and the id to select by + */ + pqxx::result executePreparedStatement_SELECT_FREELANCER_TEMPLATES(pqxx::connection &connection, int freelancerID) { + connection.prepare(PREPARED_STATEMENT_SELECT_FREELANCER_TEMPLATES, SQL_STATEMENT_SELECT_FREELANCER_TEMPLATES); + pqxx::work work(connection); + pqxx::result result = work.exec_prepared(PREPARED_STATEMENT_SELECT_FREELANCER_TEMPLATES, freelancerID); + work.commit(); + return result; + } + + + /* * parses the result and returns a JSON * Takes a result and optionally the desired row @@ -112,4 +177,29 @@ namespace Database { } return returnJson; } + + /* + * parses the result and returns a JSON + * parses it fully and returns a JSON containing it at the top or below a variable + * takes the result and optionally a name for the top level variable + */ + crow::json::wvalue convertResultToJSON(pqxx::result &result, std::string jsonName = ""){ + std::vector jsonVector; + for (int row = 0; row < result.size(); ++row) { + crow::json::wvalue jsonVectorItem; + for (int i = 0; i < result.columns(); ++i) { + jsonVectorItem[result.column_name(i)] = result.at(row).at(i).c_str(); + } + jsonVector.push_back(jsonVectorItem); + } + crow::json::wvalue returnJson; + if (jsonName != ""){ + returnJson[jsonName] = crow::json::wvalue(jsonVector); + } + else + { + returnJson = crow::json::wvalue(jsonVector); + } + return returnJson; + } } \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 7a8a171..d7da9a7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,10 +8,6 @@ using namespace std; int main() { crow::SimpleApp app; - //define your endpoint at the root directory - CROW_ROUTE(app, "/")([]() { - return "Hello world"; - }); // CROW_ROUTE(app, "/test.json") // ([](){ @@ -25,6 +21,29 @@ int main() { string databaseURI = "postgresql://cavecommadmin:cavecomm@localhost:5432/cavecomm"; + /* + * Freelancer Profile listing for customers + */ + CROW_ROUTE(app, "/") + ([databaseURI]() { + pqxx::connection databaseConnection(databaseURI); + pqxx::result result = Database::executeStatement_SELECT_FREELANCERS_WITHCOMMISSIONSSTATE(databaseConnection); + + auto page = crow::mustache::load("customerIndex_FreelancerListing.html"); + crow::json::wvalue resultJson = Database::convertResultToJSON(result, "freelancerProfiles"); + + crow::mustache::context ctx(resultJson); + return page.render(ctx); + }); + + + + + + + + + CROW_ROUTE(app, "/getEntry/") ([databaseURI](int entry) { pqxx::connection databaseConnection(databaseURI); diff --git a/templates/customerIndex_FreelancerListing.html b/templates/customerIndex_FreelancerListing.html new file mode 100644 index 0000000..3cefb14 --- /dev/null +++ b/templates/customerIndex_FreelancerListing.html @@ -0,0 +1,39 @@ + + + + + + +

Freelancer Profiles

+ + + + + + + {{#freelancerProfiles}} + + + + + + {{/freelancerProfiles}} +
FreelancerBasic InformationCommission State
{{name}}{{basicinformation}}{{commissionsclosed}}
+ + \ No newline at end of file