From dcfb097114c5b7285271a09fdd35efa56be70685 Mon Sep 17 00:00:00 2001 From: Max Hohlfeld Date: Mon, 7 Jul 2025 16:07:57 +0200 Subject: [PATCH] refactor: db availability --- ...3d8ac3f81b082932c6502eadbffee18a1087.json} | 4 +- ...e12bd9b31ef0e805427e5e48142ab2189a9f.json} | 4 +- ...2afcf0f97afd335ddc70fe11cb5e7d9e978a.json} | 4 +- ...9cc8a35bac096b8fd0a86645dc2bc5b175210.json | 17 +++ ...dee29ef920f49d7e088bf23064c2eedadc10.json} | 4 +- ...d6a0751e87d31fa50f173fc2eb44d0a0a133.json} | 4 +- ...1e368475972884c13cf9990b279077c619ba.json} | 4 +- ...7cb17eb5221c1dbe4d4c5e83167b2d2807db4.json | 48 -------- ...e63fc1c981807dfa25b42a9d52124f3096e6.json} | 5 +- ...b7d4e80387970467bf940c79433c08cb4f879.json | 17 --- ...f474f05dbeb27a3aecc292ef0d2e982349d2.json} | 4 +- ...5c0a6e2c15d92e6e8f259b4d1e06d93ed55e7.json | 47 ++++++++ db/sql/availability/create.sql | 2 + ...ad_all_by_date_and_area_including_user.sql | 22 ++++ ...area_including_user_for_event_planning.sql | 24 ++++ .../read_all_by_user_and_date.sql | 11 ++ .../read_all_by_user_and_daterange.sql | 12 ++ db/src/models/availability.rs | 107 ++++-------------- db/src/models/availability_changeset.rs | 2 +- doc/design-decisions.md | 9 ++ .../endpoints/availability/get_calendar.rs | 4 +- web/src/endpoints/availability/get_new.rs | 2 +- .../endpoints/availability/get_overview.rs | 2 +- web/src/endpoints/availability/get_update.rs | 2 +- web/src/utils/event_planning_template.rs | 14 +-- 25 files changed, 193 insertions(+), 182 deletions(-) rename db/.sqlx/{query-47bd20303899d5e804f8651c17428ee92f80321d1a5423be52e4f9a275180748.json => query-13c282f93a07edc488d1734917ff3d8ac3f81b082932c6502eadbffee18a1087.json} (64%) rename db/.sqlx/{query-ae18073da63db05840fdd113a2a4727a7e2531cc54ca2bf35ba4f4f86d35a4d3.json => query-14fbf5259ce8c783177fbdc7304ce12bd9b31ef0e805427e5e48142ab2189a9f.json} (67%) rename db/.sqlx/{query-7b3d623440f6ab8060223289d13687921a5c27317ea27d1b2c960b5e809a7497.json => query-1881e09cead57f5bc1888b41d0a52afcf0f97afd335ddc70fe11cb5e7d9e978a.json} (70%) create mode 100644 db/.sqlx/query-4087f8c12d7ea29be931f9205919cc8a35bac096b8fd0a86645dc2bc5b175210.json rename db/.sqlx/{query-9315f185d76ae8e25c9bb0273fce388ca559c4494f82d31524f224c6b70000f9.json => query-499c8a6a46ea5efb42cdde670f8ddee29ef920f49d7e088bf23064c2eedadc10.json} (68%) rename db/.sqlx/{query-8893828aa4509fc81f078b313a88c34d05eb7c5988e4d595768bc7dd47a7892f.json => query-500739a566f98cbfd96605d2d5d7d6a0751e87d31fa50f173fc2eb44d0a0a133.json} (67%) rename db/.sqlx/{query-6788747f70812d6a87833d821c9845f59b4338bc42a40050a68736ba30d937d5.json => query-5b5795f479ec4dcc01c15278d4f71e368475972884c13cf9990b279077c619ba.json} (58%) delete mode 100644 db/.sqlx/query-66638de4a321ba610206a9f5c237cb17eb5221c1dbe4d4c5e83167b2d2807db4.json rename db/.sqlx/{query-f90aa1fd76ddf0f667fc77f1cbb02b219aff6d73a3ee1e0afeb9eeea7e194f9d.json => query-996b63cfc4e08c874f24286c2467e63fc1c981807dfa25b42a9d52124f3096e6.json} (54%) delete mode 100644 db/.sqlx/query-a55c1e8926f4aa039d8b14a054cb7d4e80387970467bf940c79433c08cb4f879.json rename db/.sqlx/{query-d2014068ac3b84a3682054e13e20ada311b1c36389b60ce8800d52ba4047730c.json => query-bdcaf04876e24ac0dad5b9733261f474f05dbeb27a3aecc292ef0d2e982349d2.json} (65%) create mode 100644 db/.sqlx/query-ec5dfa3b6bcc1cc70d34287e1405c0a6e2c15d92e6e8f259b4d1e06d93ed55e7.json create mode 100644 db/sql/availability/create.sql create mode 100644 db/sql/availability/read_all_by_date_and_area_including_user.sql create mode 100644 db/sql/availability/read_all_by_daterange_and_area_including_user_for_event_planning.sql create mode 100644 db/sql/availability/read_all_by_user_and_date.sql create mode 100644 db/sql/availability/read_all_by_user_and_daterange.sql diff --git a/db/.sqlx/query-47bd20303899d5e804f8651c17428ee92f80321d1a5423be52e4f9a275180748.json b/db/.sqlx/query-13c282f93a07edc488d1734917ff3d8ac3f81b082932c6502eadbffee18a1087.json similarity index 64% rename from db/.sqlx/query-47bd20303899d5e804f8651c17428ee92f80321d1a5423be52e4f9a275180748.json rename to db/.sqlx/query-13c282f93a07edc488d1734917ff3d8ac3f81b082932c6502eadbffee18a1087.json index 7c731770..c5980076 100644 --- a/db/.sqlx/query-47bd20303899d5e804f8651c17428ee92f80321d1a5423be52e4f9a275180748.json +++ b/db/.sqlx/query-13c282f93a07edc488d1734917ff3d8ac3f81b082932c6502eadbffee18a1087.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n INSERT INTO assignment (eventId, availabilityId, function, startTimestamp, endTimestamp)\n VALUES ($1, $2, $3, $4, $5);\n ", + "query": "INSERT INTO assignment (eventId, availabilityId, function, startTimestamp, endTimestamp)\nVALUES ($1, $2, $3, $4, $5);\n", "describe": { "columns": [], "parameters": { @@ -25,5 +25,5 @@ }, "nullable": [] }, - "hash": "47bd20303899d5e804f8651c17428ee92f80321d1a5423be52e4f9a275180748" + "hash": "13c282f93a07edc488d1734917ff3d8ac3f81b082932c6502eadbffee18a1087" } diff --git a/db/.sqlx/query-ae18073da63db05840fdd113a2a4727a7e2531cc54ca2bf35ba4f4f86d35a4d3.json b/db/.sqlx/query-14fbf5259ce8c783177fbdc7304ce12bd9b31ef0e805427e5e48142ab2189a9f.json similarity index 67% rename from db/.sqlx/query-ae18073da63db05840fdd113a2a4727a7e2531cc54ca2bf35ba4f4f86d35a4d3.json rename to db/.sqlx/query-14fbf5259ce8c783177fbdc7304ce12bd9b31ef0e805427e5e48142ab2189a9f.json index f8d2c52f..3ebb832b 100644 --- a/db/.sqlx/query-ae18073da63db05840fdd113a2a4727a7e2531cc54ca2bf35ba4f4f86d35a4d3.json +++ b/db/.sqlx/query-14fbf5259ce8c783177fbdc7304ce12bd9b31ef0e805427e5e48142ab2189a9f.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n availability.id,\n availability.userId,\n availability.startTimestamp,\n availability.endTimestamp,\n availability.comment,\n user_.name,\n user_.email,\n user_.password,\n user_.salt,\n user_.role AS \"role: Role\",\n user_.function AS \"function: UserFunction\",\n user_.areaId,\n user_.locked,\n user_.lastLogin,\n user_.receiveNotifications\n FROM availability\n JOIN user_ ON availability.userId = user_.id\n WHERE availability.startTimestamp::date = $1\n AND user_.areaId = $2;\n ", + "query": "SELECT\n availability.id,\n availability.userId,\n availability.startTimestamp,\n availability.endTimestamp,\n availability.comment,\n user_.name,\n user_.email,\n user_.password,\n user_.salt,\n user_.role AS \"role: Role\",\n user_.function AS \"function: UserFunction\",\n user_.areaId,\n user_.locked,\n user_.lastLogin,\n user_.receiveNotifications\nFROM availability\nJOIN\n user_ ON availability.userId = user_.id\nWHERE\n availability.startTimestamp::date = $1\n AND user_.areaId = $2;\n", "describe": { "columns": [ { @@ -132,5 +132,5 @@ false ] }, - "hash": "ae18073da63db05840fdd113a2a4727a7e2531cc54ca2bf35ba4f4f86d35a4d3" + "hash": "14fbf5259ce8c783177fbdc7304ce12bd9b31ef0e805427e5e48142ab2189a9f" } diff --git a/db/.sqlx/query-7b3d623440f6ab8060223289d13687921a5c27317ea27d1b2c960b5e809a7497.json b/db/.sqlx/query-1881e09cead57f5bc1888b41d0a52afcf0f97afd335ddc70fe11cb5e7d9e978a.json similarity index 70% rename from db/.sqlx/query-7b3d623440f6ab8060223289d13687921a5c27317ea27d1b2c960b5e809a7497.json rename to db/.sqlx/query-1881e09cead57f5bc1888b41d0a52afcf0f97afd335ddc70fe11cb5e7d9e978a.json index 408ccbf4..68585594 100644 --- a/db/.sqlx/query-7b3d623440f6ab8060223289d13687921a5c27317ea27d1b2c960b5e809a7497.json +++ b/db/.sqlx/query-1881e09cead57f5bc1888b41d0a52afcf0f97afd335ddc70fe11cb5e7d9e978a.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n availability.id,\n availability.userId,\n availability.startTimestamp,\n availability.endTimestamp,\n availability.comment,\n user_.name,\n user_.email,\n user_.password,\n user_.salt,\n user_.role AS \"role: Role\",\n user_.function AS \"function: UserFunction\",\n user_.areaId,\n user_.locked,\n user_.lastLogin,\n user_.receiveNotifications\n FROM availability\n JOIN user_ ON availability.userId = user_.id\n WHERE availability.starttimestamp::date = $1\n AND user_.areaId = $2\n AND availability.startTimestamp <= $3 AND availability.endTimestamp >= $4;\n ", + "query": "SELECT\n availability.id,\n availability.userId,\n availability.startTimestamp,\n availability.endTimestamp,\n availability.comment,\n user_.name,\n user_.email,\n user_.password,\n user_.salt,\n user_.role AS \"role: Role\",\n user_.function AS \"function: UserFunction\",\n user_.areaId,\n user_.locked,\n user_.lastLogin,\n user_.receiveNotifications\nFROM availability\nJOIN\n user_ ON availability.userId = user_.id\nWHERE\n availability.starttimestamp::date = $1\n AND user_.areaId = $2\n AND availability.startTimestamp <= $3\n AND availability.endTimestamp >= $4;\n", "describe": { "columns": [ { @@ -134,5 +134,5 @@ false ] }, - "hash": "7b3d623440f6ab8060223289d13687921a5c27317ea27d1b2c960b5e809a7497" + "hash": "1881e09cead57f5bc1888b41d0a52afcf0f97afd335ddc70fe11cb5e7d9e978a" } diff --git a/db/.sqlx/query-4087f8c12d7ea29be931f9205919cc8a35bac096b8fd0a86645dc2bc5b175210.json b/db/.sqlx/query-4087f8c12d7ea29be931f9205919cc8a35bac096b8fd0a86645dc2bc5b175210.json new file mode 100644 index 00000000..a7832f05 --- /dev/null +++ b/db/.sqlx/query-4087f8c12d7ea29be931f9205919cc8a35bac096b8fd0a86645dc2bc5b175210.json @@ -0,0 +1,17 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO availability (userId, startTimestamp, endTimestamp, comment)\nVALUES ($1, $2, $3, $4);\n", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int4", + "Timestamptz", + "Timestamptz", + "Text" + ] + }, + "nullable": [] + }, + "hash": "4087f8c12d7ea29be931f9205919cc8a35bac096b8fd0a86645dc2bc5b175210" +} diff --git a/db/.sqlx/query-9315f185d76ae8e25c9bb0273fce388ca559c4494f82d31524f224c6b70000f9.json b/db/.sqlx/query-499c8a6a46ea5efb42cdde670f8ddee29ef920f49d7e088bf23064c2eedadc10.json similarity index 68% rename from db/.sqlx/query-9315f185d76ae8e25c9bb0273fce388ca559c4494f82d31524f224c6b70000f9.json rename to db/.sqlx/query-499c8a6a46ea5efb42cdde670f8ddee29ef920f49d7e088bf23064c2eedadc10.json index 6fd0025d..a3a42b3f 100644 --- a/db/.sqlx/query-9315f185d76ae8e25c9bb0273fce388ca559c4494f82d31524f224c6b70000f9.json +++ b/db/.sqlx/query-499c8a6a46ea5efb42cdde670f8ddee29ef920f49d7e088bf23064c2eedadc10.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n assignment.eventId,\n assignment.availabilityId,\n assignment.function AS \"function: Function\",\n assignment.startTimestamp,\n assignment.endTimestamp\n FROM assignment\n WHERE assignment.eventId = $1;\n ", + "query": "SELECT\n assignment.eventId,\n assignment.availabilityId,\n assignment.function AS \"function: Function\",\n assignment.startTimestamp,\n assignment.endTimestamp\nFROM assignment\nWHERE assignment.eventId = $1;\n", "describe": { "columns": [ { @@ -53,5 +53,5 @@ false ] }, - "hash": "9315f185d76ae8e25c9bb0273fce388ca559c4494f82d31524f224c6b70000f9" + "hash": "499c8a6a46ea5efb42cdde670f8ddee29ef920f49d7e088bf23064c2eedadc10" } diff --git a/db/.sqlx/query-8893828aa4509fc81f078b313a88c34d05eb7c5988e4d595768bc7dd47a7892f.json b/db/.sqlx/query-500739a566f98cbfd96605d2d5d7d6a0751e87d31fa50f173fc2eb44d0a0a133.json similarity index 67% rename from db/.sqlx/query-8893828aa4509fc81f078b313a88c34d05eb7c5988e4d595768bc7dd47a7892f.json rename to db/.sqlx/query-500739a566f98cbfd96605d2d5d7d6a0751e87d31fa50f173fc2eb44d0a0a133.json index e2b445b9..1694d5cf 100644 --- a/db/.sqlx/query-8893828aa4509fc81f078b313a88c34d05eb7c5988e4d595768bc7dd47a7892f.json +++ b/db/.sqlx/query-500739a566f98cbfd96605d2d5d7d6a0751e87d31fa50f173fc2eb44d0a0a133.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n assignment.eventId,\n assignment.availabilityId,\n assignment.function AS \"function: Function\",\n assignment.startTimestamp,\n assignment.endTimestamp\n FROM assignment\n WHERE assignment.AvailabilityId = $1;\n ", + "query": "SELECT\n assignment.eventId,\n assignment.availabilityId,\n assignment.function AS \"function: Function\",\n assignment.startTimestamp,\n assignment.endTimestamp\nFROM assignment\nWHERE assignment.AvailabilityId = $1;\n", "describe": { "columns": [ { @@ -53,5 +53,5 @@ false ] }, - "hash": "8893828aa4509fc81f078b313a88c34d05eb7c5988e4d595768bc7dd47a7892f" + "hash": "500739a566f98cbfd96605d2d5d7d6a0751e87d31fa50f173fc2eb44d0a0a133" } diff --git a/db/.sqlx/query-6788747f70812d6a87833d821c9845f59b4338bc42a40050a68736ba30d937d5.json b/db/.sqlx/query-5b5795f479ec4dcc01c15278d4f71e368475972884c13cf9990b279077c619ba.json similarity index 58% rename from db/.sqlx/query-6788747f70812d6a87833d821c9845f59b4338bc42a40050a68736ba30d937d5.json rename to db/.sqlx/query-5b5795f479ec4dcc01c15278d4f71e368475972884c13cf9990b279077c619ba.json index afbbfd95..5ee4fa00 100644 --- a/db/.sqlx/query-6788747f70812d6a87833d821c9845f59b4338bc42a40050a68736ba30d937d5.json +++ b/db/.sqlx/query-5b5795f479ec4dcc01c15278d4f71e368475972884c13cf9990b279077c619ba.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n assignment.eventId,\n assignment.availabilityId,\n assignment.function AS \"function: Function\",\n assignment.startTimestamp,\n assignment.endTimestamp\n FROM assignment\n JOIN availability ON assignment.availabilityId = availability.id\n WHERE assignment.starttimestamp::date >= $1\n AND assignment.starttimestamp::date <= $2\n AND availability.userId = $3\n ORDER BY assignment.starttimestamp;\n ", + "query": "SELECT\n assignment.eventId,\n assignment.availabilityId,\n assignment.function AS \"function: Function\",\n assignment.startTimestamp,\n assignment.endTimestamp\nFROM assignment\nJOIN\n availability ON assignment.availabilityId = availability.id\nWHERE\n assignment.starttimestamp::date >= $1\n AND assignment.starttimestamp::date <= $2\n AND availability.userId = $3\nORDER BY assignment.starttimestamp;\n", "describe": { "columns": [ { @@ -55,5 +55,5 @@ false ] }, - "hash": "6788747f70812d6a87833d821c9845f59b4338bc42a40050a68736ba30d937d5" + "hash": "5b5795f479ec4dcc01c15278d4f71e368475972884c13cf9990b279077c619ba" } diff --git a/db/.sqlx/query-66638de4a321ba610206a9f5c237cb17eb5221c1dbe4d4c5e83167b2d2807db4.json b/db/.sqlx/query-66638de4a321ba610206a9f5c237cb17eb5221c1dbe4d4c5e83167b2d2807db4.json deleted file mode 100644 index dd497d36..00000000 --- a/db/.sqlx/query-66638de4a321ba610206a9f5c237cb17eb5221c1dbe4d4c5e83167b2d2807db4.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n SELECT\n availability.id,\n availability.userId,\n availability.startTimestamp,\n availability.endTimestamp,\n availability.comment\n FROM availability\n WHERE availability.userId = $1\n AND availability.starttimestamp::date >= $2\n AND availability.endtimestamp::date <= $3\n ORDER BY availability.starttimestamp;\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int4" - }, - { - "ordinal": 1, - "name": "userid", - "type_info": "Int4" - }, - { - "ordinal": 2, - "name": "starttimestamp", - "type_info": "Timestamptz" - }, - { - "ordinal": 3, - "name": "endtimestamp", - "type_info": "Timestamptz" - }, - { - "ordinal": 4, - "name": "comment", - "type_info": "Text" - } - ], - "parameters": { - "Left": [ - "Int4", - "Date", - "Date" - ] - }, - "nullable": [ - false, - false, - false, - false, - true - ] - }, - "hash": "66638de4a321ba610206a9f5c237cb17eb5221c1dbe4d4c5e83167b2d2807db4" -} diff --git a/db/.sqlx/query-f90aa1fd76ddf0f667fc77f1cbb02b219aff6d73a3ee1e0afeb9eeea7e194f9d.json b/db/.sqlx/query-996b63cfc4e08c874f24286c2467e63fc1c981807dfa25b42a9d52124f3096e6.json similarity index 54% rename from db/.sqlx/query-f90aa1fd76ddf0f667fc77f1cbb02b219aff6d73a3ee1e0afeb9eeea7e194f9d.json rename to db/.sqlx/query-996b63cfc4e08c874f24286c2467e63fc1c981807dfa25b42a9d52124f3096e6.json index 525437ca..317799ba 100644 --- a/db/.sqlx/query-f90aa1fd76ddf0f667fc77f1cbb02b219aff6d73a3ee1e0afeb9eeea7e194f9d.json +++ b/db/.sqlx/query-996b63cfc4e08c874f24286c2467e63fc1c981807dfa25b42a9d52124f3096e6.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n availability.id,\n availability.userId,\n availability.startTimestamp,\n availability.endTimestamp,\n availability.comment\n FROM availability\n WHERE availability.userId = $1\n AND availability.starttimestamp::date = $2;\n ", + "query": "SELECT\n availability.id,\n availability.userId,\n availability.startTimestamp,\n availability.endTimestamp,\n availability.comment\nFROM availability\nWHERE\n availability.userId = $1\n AND availability.starttimestamp::date >= $2\n AND availability.endtimestamp::date <= $3\nORDER BY availability.starttimestamp;\n", "describe": { "columns": [ { @@ -32,6 +32,7 @@ "parameters": { "Left": [ "Int4", + "Date", "Date" ] }, @@ -43,5 +44,5 @@ true ] }, - "hash": "f90aa1fd76ddf0f667fc77f1cbb02b219aff6d73a3ee1e0afeb9eeea7e194f9d" + "hash": "996b63cfc4e08c874f24286c2467e63fc1c981807dfa25b42a9d52124f3096e6" } diff --git a/db/.sqlx/query-a55c1e8926f4aa039d8b14a054cb7d4e80387970467bf940c79433c08cb4f879.json b/db/.sqlx/query-a55c1e8926f4aa039d8b14a054cb7d4e80387970467bf940c79433c08cb4f879.json deleted file mode 100644 index dd141389..00000000 --- a/db/.sqlx/query-a55c1e8926f4aa039d8b14a054cb7d4e80387970467bf940c79433c08cb4f879.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO availability (userId, startTimestamp, endTimestamp, comment)\n VALUES ($1, $2, $3, $4);\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Int4", - "Timestamptz", - "Timestamptz", - "Text" - ] - }, - "nullable": [] - }, - "hash": "a55c1e8926f4aa039d8b14a054cb7d4e80387970467bf940c79433c08cb4f879" -} diff --git a/db/.sqlx/query-d2014068ac3b84a3682054e13e20ada311b1c36389b60ce8800d52ba4047730c.json b/db/.sqlx/query-bdcaf04876e24ac0dad5b9733261f474f05dbeb27a3aecc292ef0d2e982349d2.json similarity index 65% rename from db/.sqlx/query-d2014068ac3b84a3682054e13e20ada311b1c36389b60ce8800d52ba4047730c.json rename to db/.sqlx/query-bdcaf04876e24ac0dad5b9733261f474f05dbeb27a3aecc292ef0d2e982349d2.json index b0383635..f6c0a08a 100644 --- a/db/.sqlx/query-d2014068ac3b84a3682054e13e20ada311b1c36389b60ce8800d52ba4047730c.json +++ b/db/.sqlx/query-bdcaf04876e24ac0dad5b9733261f474f05dbeb27a3aecc292ef0d2e982349d2.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n assignment.eventId,\n assignment.availabilityId,\n assignment.function AS \"function: Function\",\n assignment.startTimestamp,\n assignment.endTimestamp\n FROM assignment\n WHERE\n assignment.eventId = $1 AND\n assignment.availabilityId = $2;\n ", + "query": "SELECT\n assignment.eventId,\n assignment.availabilityId,\n assignment.function AS \"function: Function\",\n assignment.startTimestamp,\n assignment.endTimestamp\nFROM assignment\nWHERE\n assignment.eventId = $1\n AND assignment.availabilityId = $2;\n", "describe": { "columns": [ { @@ -54,5 +54,5 @@ false ] }, - "hash": "d2014068ac3b84a3682054e13e20ada311b1c36389b60ce8800d52ba4047730c" + "hash": "bdcaf04876e24ac0dad5b9733261f474f05dbeb27a3aecc292ef0d2e982349d2" } diff --git a/db/.sqlx/query-ec5dfa3b6bcc1cc70d34287e1405c0a6e2c15d92e6e8f259b4d1e06d93ed55e7.json b/db/.sqlx/query-ec5dfa3b6bcc1cc70d34287e1405c0a6e2c15d92e6e8f259b4d1e06d93ed55e7.json new file mode 100644 index 00000000..fe5ea3b2 --- /dev/null +++ b/db/.sqlx/query-ec5dfa3b6bcc1cc70d34287e1405c0a6e2c15d92e6e8f259b4d1e06d93ed55e7.json @@ -0,0 +1,47 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT\n availability.id,\n availability.userId,\n availability.startTimestamp,\n availability.endTimestamp,\n availability.comment\nFROM availability\nWHERE\n availability.userId = $1\n AND availability.starttimestamp::date = $2\nORDER BY availability.starttimestamp;\n", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int4" + }, + { + "ordinal": 1, + "name": "userid", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "starttimestamp", + "type_info": "Timestamptz" + }, + { + "ordinal": 3, + "name": "endtimestamp", + "type_info": "Timestamptz" + }, + { + "ordinal": 4, + "name": "comment", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Int4", + "Date" + ] + }, + "nullable": [ + false, + false, + false, + false, + true + ] + }, + "hash": "ec5dfa3b6bcc1cc70d34287e1405c0a6e2c15d92e6e8f259b4d1e06d93ed55e7" +} diff --git a/db/sql/availability/create.sql b/db/sql/availability/create.sql new file mode 100644 index 00000000..02876387 --- /dev/null +++ b/db/sql/availability/create.sql @@ -0,0 +1,2 @@ +INSERT INTO availability (userId, startTimestamp, endTimestamp, comment) +VALUES ($1, $2, $3, $4); diff --git a/db/sql/availability/read_all_by_date_and_area_including_user.sql b/db/sql/availability/read_all_by_date_and_area_including_user.sql new file mode 100644 index 00000000..fd0e8c70 --- /dev/null +++ b/db/sql/availability/read_all_by_date_and_area_including_user.sql @@ -0,0 +1,22 @@ +SELECT + availability.id, + availability.userId, + availability.startTimestamp, + availability.endTimestamp, + availability.comment, + user_.name, + user_.email, + user_.password, + user_.salt, + user_.role AS "role: Role", + user_.function AS "function: UserFunction", + user_.areaId, + user_.locked, + user_.lastLogin, + user_.receiveNotifications +FROM availability +JOIN + user_ ON availability.userId = user_.id +WHERE + availability.startTimestamp::date = $1 + AND user_.areaId = $2; diff --git a/db/sql/availability/read_all_by_daterange_and_area_including_user_for_event_planning.sql b/db/sql/availability/read_all_by_daterange_and_area_including_user_for_event_planning.sql new file mode 100644 index 00000000..4a929e27 --- /dev/null +++ b/db/sql/availability/read_all_by_daterange_and_area_including_user_for_event_planning.sql @@ -0,0 +1,24 @@ +SELECT + availability.id, + availability.userId, + availability.startTimestamp, + availability.endTimestamp, + availability.comment, + user_.name, + user_.email, + user_.password, + user_.salt, + user_.role AS "role: Role", + user_.function AS "function: UserFunction", + user_.areaId, + user_.locked, + user_.lastLogin, + user_.receiveNotifications +FROM availability +JOIN + user_ ON availability.userId = user_.id +WHERE + availability.starttimestamp::date = $1 + AND user_.areaId = $2 + AND availability.startTimestamp <= $3 + AND availability.endTimestamp >= $4; diff --git a/db/sql/availability/read_all_by_user_and_date.sql b/db/sql/availability/read_all_by_user_and_date.sql new file mode 100644 index 00000000..149f09b5 --- /dev/null +++ b/db/sql/availability/read_all_by_user_and_date.sql @@ -0,0 +1,11 @@ +SELECT + availability.id, + availability.userId, + availability.startTimestamp, + availability.endTimestamp, + availability.comment +FROM availability +WHERE + availability.userId = $1 + AND availability.starttimestamp::date = $2 +ORDER BY availability.starttimestamp; diff --git a/db/sql/availability/read_all_by_user_and_daterange.sql b/db/sql/availability/read_all_by_user_and_daterange.sql new file mode 100644 index 00000000..6cf731b9 --- /dev/null +++ b/db/sql/availability/read_all_by_user_and_daterange.sql @@ -0,0 +1,12 @@ +SELECT + availability.id, + availability.userId, + availability.startTimestamp, + availability.endTimestamp, + availability.comment +FROM availability +WHERE + availability.userId = $1 + AND availability.starttimestamp::date >= $2 + AND availability.endtimestamp::date <= $3 +ORDER BY availability.starttimestamp; diff --git a/db/src/models/availability.rs b/db/src/models/availability.rs index 7fbcb1da..25177c42 100644 --- a/db/src/models/availability.rs +++ b/db/src/models/availability.rs @@ -1,5 +1,5 @@ use chrono::{NaiveDate, NaiveDateTime}; -use sqlx::{PgPool, query}; +use sqlx::{PgPool, query, query_file}; use super::{Area, AvailabilityChangeset, Result, Role, User, UserFunction}; @@ -19,11 +19,8 @@ impl Availability { user_id: i32, changeset: AvailabilityChangeset, ) -> Result<()> { - query!( - r#" - INSERT INTO availability (userId, startTimestamp, endTimestamp, comment) - VALUES ($1, $2, $3, $4); - "#, + query_file!( + "sql/availability/create.sql", user_id, changeset.time.0.and_utc(), changeset.time.1.and_utc(), @@ -35,34 +32,13 @@ impl Availability { Ok(()) } - pub async fn read_by_date_and_area_including_user( + pub async fn read_all_by_date_and_area_including_user( pool: &PgPool, date: NaiveDate, area_id: i32, ) -> Result> { - let records = query!( - r##" - SELECT - availability.id, - availability.userId, - availability.startTimestamp, - availability.endTimestamp, - availability.comment, - user_.name, - user_.email, - user_.password, - user_.salt, - user_.role AS "role: Role", - user_.function AS "function: UserFunction", - user_.areaId, - user_.locked, - user_.lastLogin, - user_.receiveNotifications - FROM availability - JOIN user_ ON availability.userId = user_.id - WHERE availability.startTimestamp::date = $1 - AND user_.areaId = $2; - "##, + let records = query_file!( + "sql/availability/read_all_by_date_and_area_including_user.sql", date, area_id ) @@ -97,40 +73,17 @@ impl Availability { Ok(availabilities) } - pub async fn read_by_date_time_area_including_user( + pub async fn read_all_by_daterange_and_area_including_user_for_event_planning( pool: &PgPool, - date: NaiveDate, - time: (NaiveDateTime, NaiveDateTime), + date_range: (NaiveDateTime, NaiveDateTime), area_id: i32, ) -> Result> { - let records = query!( - r##" - SELECT - availability.id, - availability.userId, - availability.startTimestamp, - availability.endTimestamp, - availability.comment, - user_.name, - user_.email, - user_.password, - user_.salt, - user_.role AS "role: Role", - user_.function AS "function: UserFunction", - user_.areaId, - user_.locked, - user_.lastLogin, - user_.receiveNotifications - FROM availability - JOIN user_ ON availability.userId = user_.id - WHERE availability.starttimestamp::date = $1 - AND user_.areaId = $2 - AND availability.startTimestamp <= $3 AND availability.endTimestamp >= $4; - "##, - date, + let records = query_file!( + "sql/availability/read_all_by_daterange_and_area_including_user_for_event_planning.sql", + date_range.0.date(), area_id, - time.0.and_utc(), - time.1.and_utc() + date_range.0.and_utc(), + date_range.1.and_utc() ) .fetch_all(pool) .await?; @@ -303,23 +256,13 @@ impl Availability { Ok(availabilities) } - pub async fn read_by_user_and_date( + pub async fn read_all_by_user_and_date( pool: &PgPool, user_id: i32, date: &NaiveDate, ) -> Result> { - let records = query!( - r##" - SELECT - availability.id, - availability.userId, - availability.startTimestamp, - availability.endTimestamp, - availability.comment - FROM availability - WHERE availability.userId = $1 - AND availability.starttimestamp::date = $2; - "##, + let records = query_file!( + "sql/availability/read_all_by_user_and_date.sql", user_id, date ) @@ -341,25 +284,13 @@ impl Availability { Ok(availabilities) } - pub async fn read_by_user_and_daterange( + pub async fn read_all_by_user_and_daterange( pool: &PgPool, user_id: i32, date_range: (&NaiveDate, &NaiveDate), ) -> Result> { - let records = query!( - r##" - SELECT - availability.id, - availability.userId, - availability.startTimestamp, - availability.endTimestamp, - availability.comment - FROM availability - WHERE availability.userId = $1 - AND availability.starttimestamp::date >= $2 - AND availability.endtimestamp::date <= $3 - ORDER BY availability.starttimestamp; - "##, + let records = query_file!( + "sql/availability/read_all_by_user_and_daterange.sql", user_id, date_range.0, date_range.1 diff --git a/db/src/models/availability_changeset.rs b/db/src/models/availability_changeset.rs index b5bf027f..55b71a5c 100644 --- a/db/src/models/availability_changeset.rs +++ b/db/src/models/availability_changeset.rs @@ -27,7 +27,7 @@ impl<'a> AsyncValidate<'a> for AvailabilityChangeset { context: &'a Self::Context, ) -> Result<(), AsyncValidateError> { let mut existing_availabilities = - Availability::read_by_user_and_date(context.pool, context.user_id, &self.time.0.date()) + Availability::read_all_by_user_and_date(context.pool, context.user_id, &self.time.0.date()) .await?; start_date_time_lies_before_end_date_time(&self.time.0, &self.time.1)?; diff --git a/doc/design-decisions.md b/doc/design-decisions.md index 2e99bba2..6ce966a6 100644 --- a/doc/design-decisions.md +++ b/doc/design-decisions.md @@ -23,6 +23,15 @@ - all fields are as they are on the model, all field must be supplied; no way for "partial updates" - partial updates for only one or two fields get a special method on the model - validate using garde and custom context with gives access to database pool +- when sql fits into oneline, leave it inline in code; otherwise put it into separate file and use query_file! + +### Naming Scheme for methods +- get single entry -> read / read_by_...(special field) +- get multiple entries -> read_all / read_all_by...(special field) +- create +- update / update_...(single field) +- delete + TODO: diff --git a/web/src/endpoints/availability/get_calendar.rs b/web/src/endpoints/availability/get_calendar.rs index e6e91ad4..46a90b9e 100644 --- a/web/src/endpoints/availability/get_calendar.rs +++ b/web/src/endpoints/availability/get_calendar.rs @@ -65,7 +65,7 @@ async fn get( None => None, }; - let availabilities = Availability::read_by_date_and_area_including_user( + let availabilities = Availability::read_all_by_date_and_area_including_user( pool.get_ref(), date, query.area.unwrap_or(user.area_id), @@ -73,7 +73,7 @@ async fn get( .await?; let availabilities_from_user = - Availability::read_by_user_and_date(pool.get_ref(), user.id, &date).await?; + Availability::read_all_by_user_and_date(pool.get_ref(), user.id, &date).await?; //println!("{availabilities_from_user:#?}"); let user_can_create_availability = availabilities_from_user.is_empty() diff --git a/web/src/endpoints/availability/get_new.rs b/web/src/endpoints/availability/get_new.rs index 55e441a0..dfa552ef 100644 --- a/web/src/endpoints/availability/get_new.rs +++ b/web/src/endpoints/availability/get_new.rs @@ -21,7 +21,7 @@ pub async fn get( query: web::Query, ) -> Result { let availabilities_from_user = - Availability::read_by_user_and_date(pool.get_ref(), user.id, &query.date).await?; + Availability::read_all_by_user_and_date(pool.get_ref(), user.id, &query.date).await?; let slot_suggestions = find_free_date_time_slots(&availabilities_from_user); let user_can_create_availability = diff --git a/web/src/endpoints/availability/get_overview.rs b/web/src/endpoints/availability/get_overview.rs index 1fdac623..53f8e0ef 100644 --- a/web/src/endpoints/availability/get_overview.rs +++ b/web/src/endpoints/availability/get_overview.rs @@ -40,7 +40,7 @@ async fn get( .await?; let availabilities = - Availability::read_by_user_and_daterange(pool.get_ref(), user.id, date_range).await?; + Availability::read_all_by_user_and_daterange(pool.get_ref(), user.id, date_range).await?; let assignments = Assignment::read_all_by_daterange_and_user(pool.get_ref(), date_range, user.id) diff --git a/web/src/endpoints/availability/get_update.rs b/web/src/endpoints/availability/get_update.rs index 1ae31217..e9bcfebe 100644 --- a/web/src/endpoints/availability/get_update.rs +++ b/web/src/endpoints/availability/get_update.rs @@ -23,7 +23,7 @@ pub async fn get( } let availabilities = - Availability::read_by_user_and_date(pool.get_ref(), user.id, &availability.start.date()) + Availability::read_all_by_user_and_date(pool.get_ref(), user.id, &availability.start.date()) .await?; let slot_suggestions = find_free_date_time_slots(&availabilities) diff --git a/web/src/utils/event_planning_template.rs b/web/src/utils/event_planning_template.rs index abece908..833015a4 100644 --- a/web/src/utils/event_planning_template.rs +++ b/web/src/utils/event_planning_template.rs @@ -11,13 +11,13 @@ pub async fn generate_availability_assignment_list( pool: &PgPool, event: &Event, ) -> Result, ApplicationError> { - let availabilities_in_db = Availability::read_by_date_time_area_including_user( - pool, - event.start.date(), - (event.start, event.end), - event.location.as_ref().unwrap().area_id, - ) - .await?; + let availabilities_in_db = + Availability::read_all_by_daterange_and_area_including_user_for_event_planning( + pool, + (event.start, event.end), + event.location.as_ref().unwrap().area_id, + ) + .await?; let mut availabilities = Vec::new(); for availability in availabilities_in_db {