diff --git a/.sqlx/query-02438c29c249ce2b446d15a41d07c40ce73946e62744a486cbbac256c4a4cf55.json b/.sqlx/query-02438c29c249ce2b446d15a41d07c40ce73946e62744a486cbbac256c4a4cf55.json new file mode 100644 index 0000000..69bc7e1 --- /dev/null +++ b/.sqlx/query-02438c29c249ce2b446d15a41d07c40ce73946e62744a486cbbac256c4a4cf55.json @@ -0,0 +1,34 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT items.id, items.name, item_classes.name AS \"class_name\"\n FROM items\n JOIN item_classes\n ON items.class = item_classes.id\n WHERE items.original_packaging = $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "name", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "class_name", + "type_info": "Varchar" + } + ], + "parameters": { + "Left": [ + "Uuid" + ] + }, + "nullable": [ + false, + true, + false + ] + }, + "hash": "02438c29c249ce2b446d15a41d07c40ce73946e62744a486cbbac256c4a4cf55" +} diff --git a/.sqlx/query-2e9619ce6db1047e2f5447c4925f28fd05f18706f70220b6ebb7354d2a0a9e3b.json b/.sqlx/query-2e9619ce6db1047e2f5447c4925f28fd05f18706f70220b6ebb7354d2a0a9e3b.json deleted file mode 100644 index bd6f7f3..0000000 --- a/.sqlx/query-2e9619ce6db1047e2f5447c4925f28fd05f18706f70220b6ebb7354d2a0a9e3b.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT * FROM items WHERE parent = $1", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Uuid" - }, - { - "ordinal": 1, - "name": "name", - "type_info": "Varchar" - }, - { - "ordinal": 2, - "name": "parent", - "type_info": "Uuid" - }, - { - "ordinal": 3, - "name": "class", - "type_info": "Uuid" - }, - { - "ordinal": 4, - "name": "created_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 5, - "name": "short_id", - "type_info": "Int4" - }, - { - "ordinal": 6, - "name": "original_packaging", - "type_info": "Uuid" - }, - { - "ordinal": 7, - "name": "description", - "type_info": "Varchar" - } - ], - "parameters": { - "Left": [ - "Uuid" - ] - }, - "nullable": [ - false, - true, - true, - false, - false, - false, - true, - false - ] - }, - "hash": "2e9619ce6db1047e2f5447c4925f28fd05f18706f70220b6ebb7354d2a0a9e3b" -} diff --git a/.sqlx/query-3dedb7b184103c1d418f7b94e26c75aea0c7d22e009299d1b87443e350578171.json b/.sqlx/query-3dedb7b184103c1d418f7b94e26c75aea0c7d22e009299d1b87443e350578171.json new file mode 100644 index 0000000..767fcf1 --- /dev/null +++ b/.sqlx/query-3dedb7b184103c1d418f7b94e26c75aea0c7d22e009299d1b87443e350578171.json @@ -0,0 +1,56 @@ +{ + "db_name": "PostgreSQL", + "query": "\n WITH RECURSIVE cte AS (\n SELECT\n id,\n ARRAY[]::UUID[] AS parents,\n ARRAY[]::VARCHAR[] AS parent_names,\n ARRAY[]::VARCHAR[] AS parent_class_names\n FROM items\n WHERE parent IS NULL\n\n UNION\n\n SELECT\n items.id,\n cte.parents || items.parent,\n cte.parent_names || parent.name,\n cte.parent_class_names || parent_class.name\n FROM cte\n JOIN items\n ON items.parent = cte.id\n JOIN items AS \"parent\"\n ON parent.id = cte.id\n JOIN item_classes AS \"parent_class\"\n ON parent.class = parent_class.id\n )\n SELECT\n cte.id AS \"id!\",\n items.name,\n items.class,\n item_classes.name AS \"class_name\",\n cte.parents AS \"parents!\",\n cte.parent_names AS \"parent_names!: Vec>\",\n cte.parent_class_names AS \"parent_class_names!\"\n FROM cte\n JOIN items\n ON cte.id = items.id\n JOIN item_classes\n ON items.class = item_classes.id\n ORDER BY items.created_at\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id!", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "name", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "class", + "type_info": "Uuid" + }, + { + "ordinal": 3, + "name": "class_name", + "type_info": "Varchar" + }, + { + "ordinal": 4, + "name": "parents!", + "type_info": "UuidArray" + }, + { + "ordinal": 5, + "name": "parent_names!: Vec>", + "type_info": "VarcharArray" + }, + { + "ordinal": 6, + "name": "parent_class_names!", + "type_info": "VarcharArray" + } + ], + "parameters": { + "Left": [] + }, + "nullable": [ + null, + true, + false, + false, + null, + null, + null + ] + }, + "hash": "3dedb7b184103c1d418f7b94e26c75aea0c7d22e009299d1b87443e350578171" +} diff --git a/.sqlx/query-460f15b3c5ec2774c237fc581166bf44ecdb0b6145f8abba155478643a474125.json b/.sqlx/query-460f15b3c5ec2774c237fc581166bf44ecdb0b6145f8abba155478643a474125.json new file mode 100644 index 0000000..25af06d --- /dev/null +++ b/.sqlx/query-460f15b3c5ec2774c237fc581166bf44ecdb0b6145f8abba155478643a474125.json @@ -0,0 +1,28 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT id AS \"id?\", to_char(short_id, '000000') AS \"short_id?\"\n FROM items\n WHERE id = ANY ($1)", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id?", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "short_id?", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "UuidArray" + ] + }, + "nullable": [ + false, + null + ] + }, + "hash": "460f15b3c5ec2774c237fc581166bf44ecdb0b6145f8abba155478643a474125" +} diff --git a/.sqlx/query-482df01f0509cc8ec18ffe1caea8f65f11c170b67424e35697540ae12e577227.json b/.sqlx/query-482df01f0509cc8ec18ffe1caea8f65f11c170b67424e35697540ae12e577227.json new file mode 100644 index 0000000..a35d951 --- /dev/null +++ b/.sqlx/query-482df01f0509cc8ec18ffe1caea8f65f11c170b67424e35697540ae12e577227.json @@ -0,0 +1,34 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT items.id, items.name, item_classes.name AS \"class_name\"\n FROM items\n JOIN item_classes\n ON items.class = item_classes.id\n WHERE items.class = $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "name", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "class_name", + "type_info": "Varchar" + } + ], + "parameters": { + "Left": [ + "Uuid" + ] + }, + "nullable": [ + false, + true, + false + ] + }, + "hash": "482df01f0509cc8ec18ffe1caea8f65f11c170b67424e35697540ae12e577227" +} diff --git a/.sqlx/query-4ed0c3101202abc920d81ee6acdaff9ed698f585df5e798d1f42206042e31a1b.json b/.sqlx/query-4ed0c3101202abc920d81ee6acdaff9ed698f585df5e798d1f42206042e31a1b.json new file mode 100644 index 0000000..9ee3865 --- /dev/null +++ b/.sqlx/query-4ed0c3101202abc920d81ee6acdaff9ed698f585df5e798d1f42206042e31a1b.json @@ -0,0 +1,28 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT id, name FROM item_classes WHERE parent = $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "name", + "type_info": "Varchar" + } + ], + "parameters": { + "Left": [ + "Uuid" + ] + }, + "nullable": [ + false, + false + ] + }, + "hash": "4ed0c3101202abc920d81ee6acdaff9ed698f585df5e798d1f42206042e31a1b" +} diff --git a/.sqlx/query-53be3ef02ba8b3deb3a74b184a4eb93e01fd0983c19aff3fca67bdc0afab4f37.json b/.sqlx/query-53be3ef02ba8b3deb3a74b184a4eb93e01fd0983c19aff3fca67bdc0afab4f37.json new file mode 100644 index 0000000..739ccba --- /dev/null +++ b/.sqlx/query-53be3ef02ba8b3deb3a74b184a4eb93e01fd0983c19aff3fca67bdc0afab4f37.json @@ -0,0 +1,26 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO items (name, parent, class, original_packaging, description)\n VALUES ($1, $2, $3, $4, $5)\n RETURNING id", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Uuid" + } + ], + "parameters": { + "Left": [ + "Varchar", + "Uuid", + "Uuid", + "Uuid", + "Varchar" + ] + }, + "nullable": [ + false + ] + }, + "hash": "53be3ef02ba8b3deb3a74b184a4eb93e01fd0983c19aff3fca67bdc0afab4f37" +} diff --git a/.sqlx/query-58969747bdccae4a2d3ad8d8117aa92283151d67f52fbb22e5d976b1c6a5c367.json b/.sqlx/query-58969747bdccae4a2d3ad8d8117aa92283151d67f52fbb22e5d976b1c6a5c367.json deleted file mode 100644 index eb09468..0000000 --- a/.sqlx/query-58969747bdccae4a2d3ad8d8117aa92283151d67f52fbb22e5d976b1c6a5c367.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT * FROM items ORDER BY created_at", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Uuid" - }, - { - "ordinal": 1, - "name": "name", - "type_info": "Varchar" - }, - { - "ordinal": 2, - "name": "parent", - "type_info": "Uuid" - }, - { - "ordinal": 3, - "name": "class", - "type_info": "Uuid" - }, - { - "ordinal": 4, - "name": "created_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 5, - "name": "short_id", - "type_info": "Int4" - }, - { - "ordinal": 6, - "name": "original_packaging", - "type_info": "Uuid" - }, - { - "ordinal": 7, - "name": "description", - "type_info": "Varchar" - } - ], - "parameters": { - "Left": [] - }, - "nullable": [ - false, - true, - true, - false, - false, - false, - true, - false - ] - }, - "hash": "58969747bdccae4a2d3ad8d8117aa92283151d67f52fbb22e5d976b1c6a5c367" -} diff --git a/.sqlx/query-6737f54ceb18b9b744bac838801edbbdfe2cbf68a6346f93c072d47f5add9e46.json b/.sqlx/query-6737f54ceb18b9b744bac838801edbbdfe2cbf68a6346f93c072d47f5add9e46.json new file mode 100644 index 0000000..9a1b5aa --- /dev/null +++ b/.sqlx/query-6737f54ceb18b9b744bac838801edbbdfe2cbf68a6346f93c072d47f5add9e46.json @@ -0,0 +1,19 @@ +{ + "db_name": "PostgreSQL", + "query": "UPDATE items\n SET name = $2, parent = $3, class = $4, original_packaging = $5, description = $6\n WHERE id = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Varchar", + "Uuid", + "Uuid", + "Uuid", + "Varchar" + ] + }, + "nullable": [] + }, + "hash": "6737f54ceb18b9b744bac838801edbbdfe2cbf68a6346f93c072d47f5add9e46" +} diff --git a/.sqlx/query-68d93c71840f87d5f5bb14b4d7fc34edd6be47cd1706b3612a332bbfd4bb54b4.json b/.sqlx/query-68d93c71840f87d5f5bb14b4d7fc34edd6be47cd1706b3612a332bbfd4bb54b4.json deleted file mode 100644 index 5ae565b..0000000 --- a/.sqlx/query-68d93c71840f87d5f5bb14b4d7fc34edd6be47cd1706b3612a332bbfd4bb54b4.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "INSERT INTO item_classes (name, parent, description) VALUES ($1, $2, $3) RETURNING *", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Uuid" - }, - { - "ordinal": 1, - "name": "name", - "type_info": "Varchar" - }, - { - "ordinal": 2, - "name": "parent", - "type_info": "Uuid" - }, - { - "ordinal": 3, - "name": "created_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 4, - "name": "description", - "type_info": "Varchar" - } - ], - "parameters": { - "Left": [ - "Varchar", - "Uuid", - "Varchar" - ] - }, - "nullable": [ - false, - false, - true, - false, - false - ] - }, - "hash": "68d93c71840f87d5f5bb14b4d7fc34edd6be47cd1706b3612a332bbfd4bb54b4" -} diff --git a/.sqlx/query-6dd8b63f4aaefbc1ab5d5a9bae2338a7275ba56a9b17278fd886175c3a27b0dd.json b/.sqlx/query-6dd8b63f4aaefbc1ab5d5a9bae2338a7275ba56a9b17278fd886175c3a27b0dd.json deleted file mode 100644 index bef38c8..0000000 --- a/.sqlx/query-6dd8b63f4aaefbc1ab5d5a9bae2338a7275ba56a9b17278fd886175c3a27b0dd.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT type as \"type!\" FROM\n (SELECT id, 'item' AS \"type\" FROM items\n UNION ALL\n SELECT id, 'item_class' AS \"type\" FROM item_classes) id_mapping\n WHERE id = $1", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "type!", - "type_info": "Text" - } - ], - "parameters": { - "Left": [ - "Uuid" - ] - }, - "nullable": [ - null - ] - }, - "hash": "6dd8b63f4aaefbc1ab5d5a9bae2338a7275ba56a9b17278fd886175c3a27b0dd" -} diff --git a/.sqlx/query-719aff68ead7ada499158fec5e9f8f3c3841a4424da04aee0136c7e4f8df79e7.json b/.sqlx/query-719aff68ead7ada499158fec5e9f8f3c3841a4424da04aee0136c7e4f8df79e7.json new file mode 100644 index 0000000..ea7e0a5 --- /dev/null +++ b/.sqlx/query-719aff68ead7ada499158fec5e9f8f3c3841a4424da04aee0136c7e4f8df79e7.json @@ -0,0 +1,22 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT type as \"type!\"\n FROM (SELECT id, 'item' AS \"type\" FROM items\n UNION ALL\n SELECT id, 'item_class' AS \"type\" FROM item_classes) id_mapping\n WHERE id = $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "type!", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Uuid" + ] + }, + "nullable": [ + null + ] + }, + "hash": "719aff68ead7ada499158fec5e9f8f3c3841a4424da04aee0136c7e4f8df79e7" +} diff --git a/.sqlx/query-79d8bfe2ed76ee550cdc31f282f598749d931af69a80d24f4575a4bc2c740f3b.json b/.sqlx/query-79d8bfe2ed76ee550cdc31f282f598749d931af69a80d24f4575a4bc2c740f3b.json deleted file mode 100644 index 9e9b102..0000000 --- a/.sqlx/query-79d8bfe2ed76ee550cdc31f282f598749d931af69a80d24f4575a4bc2c740f3b.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT * FROM items WHERE id = ANY ($1)", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Uuid" - }, - { - "ordinal": 1, - "name": "name", - "type_info": "Varchar" - }, - { - "ordinal": 2, - "name": "parent", - "type_info": "Uuid" - }, - { - "ordinal": 3, - "name": "class", - "type_info": "Uuid" - }, - { - "ordinal": 4, - "name": "created_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 5, - "name": "short_id", - "type_info": "Int4" - }, - { - "ordinal": 6, - "name": "original_packaging", - "type_info": "Uuid" - }, - { - "ordinal": 7, - "name": "description", - "type_info": "Varchar" - } - ], - "parameters": { - "Left": [ - "UuidArray" - ] - }, - "nullable": [ - false, - true, - true, - false, - false, - false, - true, - false - ] - }, - "hash": "79d8bfe2ed76ee550cdc31f282f598749d931af69a80d24f4575a4bc2c740f3b" -} diff --git a/.sqlx/query-7b3f478c9b217e09043daeca5dc574381493e559860258f4f6bffb12825b1ed7.json b/.sqlx/query-7b3f478c9b217e09043daeca5dc574381493e559860258f4f6bffb12825b1ed7.json new file mode 100644 index 0000000..a2e25ad --- /dev/null +++ b/.sqlx/query-7b3f478c9b217e09043daeca5dc574381493e559860258f4f6bffb12825b1ed7.json @@ -0,0 +1,32 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT items.id, items.name, item_classes.name AS \"class_name\"\n FROM items\n JOIN item_classes\n ON items.class = item_classes.id", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "name", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "class_name", + "type_info": "Varchar" + } + ], + "parameters": { + "Left": [] + }, + "nullable": [ + false, + true, + false + ] + }, + "hash": "7b3f478c9b217e09043daeca5dc574381493e559860258f4f6bffb12825b1ed7" +} diff --git a/.sqlx/query-7eeb752c8b00ac4000104f0254186f1f9fdb076e8f8b98f10fc1b981cfe8038c.json b/.sqlx/query-7eeb752c8b00ac4000104f0254186f1f9fdb076e8f8b98f10fc1b981cfe8038c.json deleted file mode 100644 index 1fff101..0000000 --- a/.sqlx/query-7eeb752c8b00ac4000104f0254186f1f9fdb076e8f8b98f10fc1b981cfe8038c.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT * FROM items WHERE short_id = $1", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Uuid" - }, - { - "ordinal": 1, - "name": "name", - "type_info": "Varchar" - }, - { - "ordinal": 2, - "name": "parent", - "type_info": "Uuid" - }, - { - "ordinal": 3, - "name": "class", - "type_info": "Uuid" - }, - { - "ordinal": 4, - "name": "created_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 5, - "name": "short_id", - "type_info": "Int4" - }, - { - "ordinal": 6, - "name": "original_packaging", - "type_info": "Uuid" - }, - { - "ordinal": 7, - "name": "description", - "type_info": "Varchar" - } - ], - "parameters": { - "Left": [ - "Int4" - ] - }, - "nullable": [ - false, - true, - true, - false, - false, - false, - true, - false - ] - }, - "hash": "7eeb752c8b00ac4000104f0254186f1f9fdb076e8f8b98f10fc1b981cfe8038c" -} diff --git a/.sqlx/query-82df5c0633a655d376b8a91e9f11981cfee40fd04cb4e3552cc5f4ebf4ed0572.json b/.sqlx/query-82df5c0633a655d376b8a91e9f11981cfee40fd04cb4e3552cc5f4ebf4ed0572.json deleted file mode 100644 index 5593f47..0000000 --- a/.sqlx/query-82df5c0633a655d376b8a91e9f11981cfee40fd04cb4e3552cc5f4ebf4ed0572.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "UPDATE items SET name = $2, parent = $3, class = $4, original_packaging = $5, description = $6 WHERE id = $1 RETURNING *", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Uuid" - }, - { - "ordinal": 1, - "name": "name", - "type_info": "Varchar" - }, - { - "ordinal": 2, - "name": "parent", - "type_info": "Uuid" - }, - { - "ordinal": 3, - "name": "class", - "type_info": "Uuid" - }, - { - "ordinal": 4, - "name": "created_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 5, - "name": "short_id", - "type_info": "Int4" - }, - { - "ordinal": 6, - "name": "original_packaging", - "type_info": "Uuid" - }, - { - "ordinal": 7, - "name": "description", - "type_info": "Varchar" - } - ], - "parameters": { - "Left": [ - "Uuid", - "Varchar", - "Uuid", - "Uuid", - "Uuid", - "Varchar" - ] - }, - "nullable": [ - false, - true, - true, - false, - false, - false, - true, - false - ] - }, - "hash": "82df5c0633a655d376b8a91e9f11981cfee40fd04cb4e3552cc5f4ebf4ed0572" -} diff --git a/.sqlx/query-835261895368c22af5780c4e4b69b518f5cb6936e3e4ea23c200b13787a401e1.json b/.sqlx/query-835261895368c22af5780c4e4b69b518f5cb6936e3e4ea23c200b13787a401e1.json new file mode 100644 index 0000000..8ea7142 --- /dev/null +++ b/.sqlx/query-835261895368c22af5780c4e4b69b518f5cb6936e3e4ea23c200b13787a401e1.json @@ -0,0 +1,17 @@ +{ + "db_name": "PostgreSQL", + "query": "UPDATE item_classes\n SET name = $2, parent = $3, description = $4\n WHERE id = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Varchar", + "Uuid", + "Varchar" + ] + }, + "nullable": [] + }, + "hash": "835261895368c22af5780c4e4b69b518f5cb6936e3e4ea23c200b13787a401e1" +} diff --git a/.sqlx/query-83fe5e57b2c7db1fdfbf05749646ac6ebe71d81057cd865c5f946d6ddb62b552.json b/.sqlx/query-83fe5e57b2c7db1fdfbf05749646ac6ebe71d81057cd865c5f946d6ddb62b552.json new file mode 100644 index 0000000..44a24e0 --- /dev/null +++ b/.sqlx/query-83fe5e57b2c7db1fdfbf05749646ac6ebe71d81057cd865c5f946d6ddb62b552.json @@ -0,0 +1,24 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO item_classes (name, parent, description)\n VALUES ($1, $2, $3)\n RETURNING id", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Uuid" + } + ], + "parameters": { + "Left": [ + "Varchar", + "Uuid", + "Varchar" + ] + }, + "nullable": [ + false + ] + }, + "hash": "83fe5e57b2c7db1fdfbf05749646ac6ebe71d81057cd865c5f946d6ddb62b552" +} diff --git a/.sqlx/query-c552c0a40bc8995cb95726a85f1d0c0b86eb2322035e6a720e2e6d425072a8c1.json b/.sqlx/query-84b4620db57dd9b963e09153c3de5938b3959ae41744098c4e9565404abf09ae.json similarity index 56% rename from .sqlx/query-c552c0a40bc8995cb95726a85f1d0c0b86eb2322035e6a720e2e6d425072a8c1.json rename to .sqlx/query-84b4620db57dd9b963e09153c3de5938b3959ae41744098c4e9565404abf09ae.json index e91dc01..7074e7d 100644 --- a/.sqlx/query-c552c0a40bc8995cb95726a85f1d0c0b86eb2322035e6a720e2e6d425072a8c1.json +++ b/.sqlx/query-84b4620db57dd9b963e09153c3de5938b3959ae41744098c4e9565404abf09ae.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "SELECT * FROM item_classes WHERE parent = $1", + "query": "SELECT\n class.id,\n class.name,\n class.description,\n class.parent,\n parent.name AS \"parent_name?\"\n FROM item_classes AS \"class\"\n LEFT JOIN item_classes AS \"parent\"\n ON class.parent = parent.id\n WHERE class.id = $1", "describe": { "columns": [ { @@ -15,17 +15,17 @@ }, { "ordinal": 2, + "name": "description", + "type_info": "Varchar" + }, + { + "ordinal": 3, "name": "parent", "type_info": "Uuid" }, - { - "ordinal": 3, - "name": "created_at", - "type_info": "Timestamptz" - }, { "ordinal": 4, - "name": "description", + "name": "parent_name?", "type_info": "Varchar" } ], @@ -37,10 +37,10 @@ "nullable": [ false, false, - true, false, + true, false ] }, - "hash": "c552c0a40bc8995cb95726a85f1d0c0b86eb2322035e6a720e2e6d425072a8c1" + "hash": "84b4620db57dd9b963e09153c3de5938b3959ae41744098c4e9565404abf09ae" } diff --git a/.sqlx/query-857bbaea0fa73c37679d927aa627ee841c5b89c86af12f32493ba05c0f0ead91.json b/.sqlx/query-857bbaea0fa73c37679d927aa627ee841c5b89c86af12f32493ba05c0f0ead91.json new file mode 100644 index 0000000..23d3be8 --- /dev/null +++ b/.sqlx/query-857bbaea0fa73c37679d927aa627ee841c5b89c86af12f32493ba05c0f0ead91.json @@ -0,0 +1,26 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO items (name, parent, class, original_packaging, description)\n SELECT * FROM UNNEST($1::VARCHAR[], $2::UUID[], $3::UUID[], $4::UUID[], $5::VARCHAR[])\n RETURNING id", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Uuid" + } + ], + "parameters": { + "Left": [ + "VarcharArray", + "UuidArray", + "UuidArray", + "UuidArray", + "VarcharArray" + ] + }, + "nullable": [ + false + ] + }, + "hash": "857bbaea0fa73c37679d927aa627ee841c5b89c86af12f32493ba05c0f0ead91" +} diff --git a/.sqlx/query-9286b6ee0c08b8446ede68b890b8bf3208b55b51433ec92b4e7a452929a81945.json b/.sqlx/query-9286b6ee0c08b8446ede68b890b8bf3208b55b51433ec92b4e7a452929a81945.json deleted file mode 100644 index c12a41f..0000000 --- a/.sqlx/query-9286b6ee0c08b8446ede68b890b8bf3208b55b51433ec92b4e7a452929a81945.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT items.*\n FROM items\n INNER JOIN\n unnest((SELECT parents FROM item_tree WHERE id = $1))\n WITH ORDINALITY AS parents(id, n)\n ON items.id = parents.id\n ORDER BY parents.n;", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Uuid" - }, - { - "ordinal": 1, - "name": "name", - "type_info": "Varchar" - }, - { - "ordinal": 2, - "name": "parent", - "type_info": "Uuid" - }, - { - "ordinal": 3, - "name": "class", - "type_info": "Uuid" - }, - { - "ordinal": 4, - "name": "created_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 5, - "name": "short_id", - "type_info": "Int4" - }, - { - "ordinal": 6, - "name": "original_packaging", - "type_info": "Uuid" - }, - { - "ordinal": 7, - "name": "description", - "type_info": "Varchar" - } - ], - "parameters": { - "Left": [ - "Uuid" - ] - }, - "nullable": [ - false, - true, - true, - false, - false, - false, - true, - false - ] - }, - "hash": "9286b6ee0c08b8446ede68b890b8bf3208b55b51433ec92b4e7a452929a81945" -} diff --git a/.sqlx/query-94958a3a57c3178e6b0de5723b1fbc5433e972b5522b367098afe6cb90a30bf2.json b/.sqlx/query-94958a3a57c3178e6b0de5723b1fbc5433e972b5522b367098afe6cb90a30bf2.json deleted file mode 100644 index 904cff3..0000000 --- a/.sqlx/query-94958a3a57c3178e6b0de5723b1fbc5433e972b5522b367098afe6cb90a30bf2.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT * FROM items WHERE class = $1", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Uuid" - }, - { - "ordinal": 1, - "name": "name", - "type_info": "Varchar" - }, - { - "ordinal": 2, - "name": "parent", - "type_info": "Uuid" - }, - { - "ordinal": 3, - "name": "class", - "type_info": "Uuid" - }, - { - "ordinal": 4, - "name": "created_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 5, - "name": "short_id", - "type_info": "Int4" - }, - { - "ordinal": 6, - "name": "original_packaging", - "type_info": "Uuid" - }, - { - "ordinal": 7, - "name": "description", - "type_info": "Varchar" - } - ], - "parameters": { - "Left": [ - "Uuid" - ] - }, - "nullable": [ - false, - true, - true, - false, - false, - false, - true, - false - ] - }, - "hash": "94958a3a57c3178e6b0de5723b1fbc5433e972b5522b367098afe6cb90a30bf2" -} diff --git a/.sqlx/query-97d6a7ee24e75dc5a9dc41a581e1013767fe36575c28574733c5ab5cbf557fb5.json b/.sqlx/query-97d6a7ee24e75dc5a9dc41a581e1013767fe36575c28574733c5ab5cbf557fb5.json deleted file mode 100644 index cfbdff0..0000000 --- a/.sqlx/query-97d6a7ee24e75dc5a9dc41a581e1013767fe36575c28574733c5ab5cbf557fb5.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT unnest(parents) as \"parents!\" FROM item_tree WHERE id = $1", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "parents!", - "type_info": "Uuid" - } - ], - "parameters": { - "Left": [ - "Uuid" - ] - }, - "nullable": [ - null - ] - }, - "hash": "97d6a7ee24e75dc5a9dc41a581e1013767fe36575c28574733c5ab5cbf557fb5" -} diff --git a/.sqlx/query-9c1a1e9c33539f6ec4800c9e8fc8ce3b65f49c34ad848321dc1b151c21cb0043.json b/.sqlx/query-9c1a1e9c33539f6ec4800c9e8fc8ce3b65f49c34ad848321dc1b151c21cb0043.json new file mode 100644 index 0000000..893c114 --- /dev/null +++ b/.sqlx/query-9c1a1e9c33539f6ec4800c9e8fc8ce3b65f49c34ad848321dc1b151c21cb0043.json @@ -0,0 +1,70 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT\n items.id,\n items.short_id,\n items.name,\n items.class,\n item_classes.name AS \"class_name\",\n items.original_packaging,\n op.name AS \"original_packaging_name?\",\n op_class.name AS \"original_packaging_class_name?\",\n items.description\n FROM items\n JOIN item_classes\n ON items.class = item_classes.id\n LEFT JOIN items AS \"op\"\n ON items.original_packaging = op.id\n LEFT JOIN item_classes AS \"op_class\"\n ON op.class = op_class.id\n WHERE items.id = $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "short_id", + "type_info": "Int4" + }, + { + "ordinal": 2, + "name": "name", + "type_info": "Varchar" + }, + { + "ordinal": 3, + "name": "class", + "type_info": "Uuid" + }, + { + "ordinal": 4, + "name": "class_name", + "type_info": "Varchar" + }, + { + "ordinal": 5, + "name": "original_packaging", + "type_info": "Uuid" + }, + { + "ordinal": 6, + "name": "original_packaging_name?", + "type_info": "Varchar" + }, + { + "ordinal": 7, + "name": "original_packaging_class_name?", + "type_info": "Varchar" + }, + { + "ordinal": 8, + "name": "description", + "type_info": "Varchar" + } + ], + "parameters": { + "Left": [ + "Uuid" + ] + }, + "nullable": [ + false, + false, + true, + false, + false, + true, + true, + false, + false + ] + }, + "hash": "9c1a1e9c33539f6ec4800c9e8fc8ce3b65f49c34ad848321dc1b151c21cb0043" +} diff --git a/.sqlx/query-9e1704d0b60906061460e2c972fccf5d87b053857c161651360e5a8fdd80e397.json b/.sqlx/query-9e1704d0b60906061460e2c972fccf5d87b053857c161651360e5a8fdd80e397.json new file mode 100644 index 0000000..33de83f --- /dev/null +++ b/.sqlx/query-9e1704d0b60906061460e2c972fccf5d87b053857c161651360e5a8fdd80e397.json @@ -0,0 +1,34 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT items.id, items.name, item_classes.name AS \"class_name\"\n FROM items\n JOIN item_classes\n ON items.class = item_classes.id\n WHERE items.parent = $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "name", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "class_name", + "type_info": "Varchar" + } + ], + "parameters": { + "Left": [ + "Uuid" + ] + }, + "nullable": [ + false, + true, + false + ] + }, + "hash": "9e1704d0b60906061460e2c972fccf5d87b053857c161651360e5a8fdd80e397" +} diff --git a/.sqlx/query-a6f646089b4424deffc0b1a454bcfa2f2a497180e2517a937471f81a1f9c5538.json b/.sqlx/query-a6f646089b4424deffc0b1a454bcfa2f2a497180e2517a937471f81a1f9c5538.json deleted file mode 100644 index 666377d..0000000 --- a/.sqlx/query-a6f646089b4424deffc0b1a454bcfa2f2a497180e2517a937471f81a1f9c5538.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT id as \"id!\", parents as \"parents!\" FROM item_tree", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id!", - "type_info": "Uuid" - }, - { - "ordinal": 1, - "name": "parents!", - "type_info": "UuidArray" - } - ], - "parameters": { - "Left": [] - }, - "nullable": [ - true, - true - ] - }, - "hash": "a6f646089b4424deffc0b1a454bcfa2f2a497180e2517a937471f81a1f9c5538" -} diff --git a/.sqlx/query-b54d323092a1dc2e34d3882a06b3cd119362d0baf5effbbd09f969ee31f385ef.json b/.sqlx/query-b54d323092a1dc2e34d3882a06b3cd119362d0baf5effbbd09f969ee31f385ef.json deleted file mode 100644 index 7a3a4db..0000000 --- a/.sqlx/query-b54d323092a1dc2e34d3882a06b3cd119362d0baf5effbbd09f969ee31f385ef.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "INSERT INTO items (name, parent, class, original_packaging, description)\n SELECT * FROM UNNEST($1::VARCHAR[], $2::UUID[], $3::UUID[], $4::UUID[], $5::VARCHAR[])\n RETURNING *", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Uuid" - }, - { - "ordinal": 1, - "name": "name", - "type_info": "Varchar" - }, - { - "ordinal": 2, - "name": "parent", - "type_info": "Uuid" - }, - { - "ordinal": 3, - "name": "class", - "type_info": "Uuid" - }, - { - "ordinal": 4, - "name": "created_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 5, - "name": "short_id", - "type_info": "Int4" - }, - { - "ordinal": 6, - "name": "original_packaging", - "type_info": "Uuid" - }, - { - "ordinal": 7, - "name": "description", - "type_info": "Varchar" - } - ], - "parameters": { - "Left": [ - "VarcharArray", - "UuidArray", - "UuidArray", - "UuidArray", - "VarcharArray" - ] - }, - "nullable": [ - false, - true, - true, - false, - false, - false, - true, - false - ] - }, - "hash": "b54d323092a1dc2e34d3882a06b3cd119362d0baf5effbbd09f969ee31f385ef" -} diff --git a/.sqlx/query-b80bb07ab582b0705b5c0370066730edf887d66a4196a0834c59f0df9f9314d3.json b/.sqlx/query-b80bb07ab582b0705b5c0370066730edf887d66a4196a0834c59f0df9f9314d3.json deleted file mode 100644 index 9a7c965..0000000 --- a/.sqlx/query-b80bb07ab582b0705b5c0370066730edf887d66a4196a0834c59f0df9f9314d3.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "INSERT INTO items (name, parent, class, original_packaging, description) VALUES ($1, $2, $3, $4, $5) RETURNING *", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Uuid" - }, - { - "ordinal": 1, - "name": "name", - "type_info": "Varchar" - }, - { - "ordinal": 2, - "name": "parent", - "type_info": "Uuid" - }, - { - "ordinal": 3, - "name": "class", - "type_info": "Uuid" - }, - { - "ordinal": 4, - "name": "created_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 5, - "name": "short_id", - "type_info": "Int4" - }, - { - "ordinal": 6, - "name": "original_packaging", - "type_info": "Uuid" - }, - { - "ordinal": 7, - "name": "description", - "type_info": "Varchar" - } - ], - "parameters": { - "Left": [ - "Varchar", - "Uuid", - "Uuid", - "Uuid", - "Varchar" - ] - }, - "nullable": [ - false, - true, - true, - false, - false, - false, - true, - false - ] - }, - "hash": "b80bb07ab582b0705b5c0370066730edf887d66a4196a0834c59f0df9f9314d3" -} diff --git a/.sqlx/query-1e9045f52c002a19b815351fee1c7ee7520478ff4f5886b4523fb0dc4df0e204.json b/.sqlx/query-c49b88eda9a62743783bc894f01bb6198594f94a3e0856abde0efdb4e49dbab8.json similarity index 59% rename from .sqlx/query-1e9045f52c002a19b815351fee1c7ee7520478ff4f5886b4523fb0dc4df0e204.json rename to .sqlx/query-c49b88eda9a62743783bc894f01bb6198594f94a3e0856abde0efdb4e49dbab8.json index 7d5a7be..9b27b4a 100644 --- a/.sqlx/query-1e9045f52c002a19b815351fee1c7ee7520478ff4f5886b4523fb0dc4df0e204.json +++ b/.sqlx/query-c49b88eda9a62743783bc894f01bb6198594f94a3e0856abde0efdb4e49dbab8.json @@ -1,45 +1,35 @@ { "db_name": "PostgreSQL", - "query": "SELECT * FROM items WHERE id = $1", + "query": "SELECT\n items.name,\n items.parent,\n items.class,\n item_classes.name AS \"class_name\",\n items.original_packaging,\n items.description\n FROM items\n JOIN item_classes\n ON items.class = item_classes.id\n WHERE items.id = $1", "describe": { "columns": [ { "ordinal": 0, - "name": "id", - "type_info": "Uuid" - }, - { - "ordinal": 1, "name": "name", "type_info": "Varchar" }, { - "ordinal": 2, + "ordinal": 1, "name": "parent", "type_info": "Uuid" }, { - "ordinal": 3, + "ordinal": 2, "name": "class", "type_info": "Uuid" }, + { + "ordinal": 3, + "name": "class_name", + "type_info": "Varchar" + }, { "ordinal": 4, - "name": "created_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 5, - "name": "short_id", - "type_info": "Int4" - }, - { - "ordinal": 6, "name": "original_packaging", "type_info": "Uuid" }, { - "ordinal": 7, + "ordinal": 5, "name": "description", "type_info": "Varchar" } @@ -50,15 +40,13 @@ ] }, "nullable": [ - false, true, true, false, false, - false, true, false ] }, - "hash": "1e9045f52c002a19b815351fee1c7ee7520478ff4f5886b4523fb0dc4df0e204" + "hash": "c49b88eda9a62743783bc894f01bb6198594f94a3e0856abde0efdb4e49dbab8" } diff --git a/.sqlx/query-6e7b3389c47091d9fc8c7638b401b413f804c6f3e082a818b67ebab0938acb39.json b/.sqlx/query-c7e35dee5f56da8da3c083e191f396b95917b15768ebe0250ce7840391036616.json similarity index 58% rename from .sqlx/query-6e7b3389c47091d9fc8c7638b401b413f804c6f3e082a818b67ebab0938acb39.json rename to .sqlx/query-c7e35dee5f56da8da3c083e191f396b95917b15768ebe0250ce7840391036616.json index 147b301..1745408 100644 --- a/.sqlx/query-6e7b3389c47091d9fc8c7638b401b413f804c6f3e082a818b67ebab0938acb39.json +++ b/.sqlx/query-c7e35dee5f56da8da3c083e191f396b95917b15768ebe0250ce7840391036616.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "SELECT * FROM item_classes ORDER BY created_at", + "query": "SELECT class.id, class.name, class.parent, parent.name AS \"parent_name?\"\n FROM item_classes AS \"class\"\n LEFT JOIN item_classes AS \"parent\"\n ON class.parent = parent.id\n ORDER BY class.created_at\n ", "describe": { "columns": [ { @@ -20,12 +20,7 @@ }, { "ordinal": 3, - "name": "created_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 4, - "name": "description", + "name": "parent_name?", "type_info": "Varchar" } ], @@ -36,9 +31,8 @@ false, false, true, - false, false ] }, - "hash": "6e7b3389c47091d9fc8c7638b401b413f804c6f3e082a818b67ebab0938acb39" + "hash": "c7e35dee5f56da8da3c083e191f396b95917b15768ebe0250ce7840391036616" } diff --git a/.sqlx/query-5cf503740d71431d8b9d256960c0ce194ede48a1c46326315cae9f07347597f6.json b/.sqlx/query-cfce4ef19a3e0a3a0582d3c7d266b952397a017b33c351c5a33f1daa78ab908a.json similarity index 57% rename from .sqlx/query-5cf503740d71431d8b9d256960c0ce194ede48a1c46326315cae9f07347597f6.json rename to .sqlx/query-cfce4ef19a3e0a3a0582d3c7d266b952397a017b33c351c5a33f1daa78ab908a.json index 5f22e6d..0c4b0cf 100644 --- a/.sqlx/query-5cf503740d71431d8b9d256960c0ce194ede48a1c46326315cae9f07347597f6.json +++ b/.sqlx/query-cfce4ef19a3e0a3a0582d3c7d266b952397a017b33c351c5a33f1daa78ab908a.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "SELECT id FROM item_classes ORDER BY created_at", + "query": "SELECT id FROM items WHERE short_id = $1", "describe": { "columns": [ { @@ -10,11 +10,13 @@ } ], "parameters": { - "Left": [] + "Left": [ + "Int4" + ] }, "nullable": [ false ] }, - "hash": "5cf503740d71431d8b9d256960c0ce194ede48a1c46326315cae9f07347597f6" + "hash": "cfce4ef19a3e0a3a0582d3c7d266b952397a017b33c351c5a33f1daa78ab908a" } diff --git a/.sqlx/query-e0129afa95f896d79f772fb177a8f9229dfbbfd289039db7b733c7d1d050f4bf.json b/.sqlx/query-e0129afa95f896d79f772fb177a8f9229dfbbfd289039db7b733c7d1d050f4bf.json deleted file mode 100644 index 0635a6d..0000000 --- a/.sqlx/query-e0129afa95f896d79f772fb177a8f9229dfbbfd289039db7b733c7d1d050f4bf.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "UPDATE item_classes SET name = $2, parent = $3, description = $4 WHERE id = $1 RETURNING *", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Uuid" - }, - { - "ordinal": 1, - "name": "name", - "type_info": "Varchar" - }, - { - "ordinal": 2, - "name": "parent", - "type_info": "Uuid" - }, - { - "ordinal": 3, - "name": "created_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 4, - "name": "description", - "type_info": "Varchar" - } - ], - "parameters": { - "Left": [ - "Uuid", - "Varchar", - "Uuid", - "Varchar" - ] - }, - "nullable": [ - false, - false, - true, - false, - false - ] - }, - "hash": "e0129afa95f896d79f772fb177a8f9229dfbbfd289039db7b733c7d1d050f4bf" -} diff --git a/.sqlx/query-efe2258db42b60f732d562d106842b19308d9a558703b02e758f60e7d8644d00.json b/.sqlx/query-efe2258db42b60f732d562d106842b19308d9a558703b02e758f60e7d8644d00.json deleted file mode 100644 index 40f8a6c..0000000 --- a/.sqlx/query-efe2258db42b60f732d562d106842b19308d9a558703b02e758f60e7d8644d00.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "SELECT * FROM items WHERE original_packaging = $1", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Uuid" - }, - { - "ordinal": 1, - "name": "name", - "type_info": "Varchar" - }, - { - "ordinal": 2, - "name": "parent", - "type_info": "Uuid" - }, - { - "ordinal": 3, - "name": "class", - "type_info": "Uuid" - }, - { - "ordinal": 4, - "name": "created_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 5, - "name": "short_id", - "type_info": "Int4" - }, - { - "ordinal": 6, - "name": "original_packaging", - "type_info": "Uuid" - }, - { - "ordinal": 7, - "name": "description", - "type_info": "Varchar" - } - ], - "parameters": { - "Left": [ - "Uuid" - ] - }, - "nullable": [ - false, - true, - true, - false, - false, - false, - true, - false - ] - }, - "hash": "efe2258db42b60f732d562d106842b19308d9a558703b02e758f60e7d8644d00" -} diff --git a/.sqlx/query-308962c26250f9312287a3f2f21e5da76e4cf488eedd4704019b4f14b6fbafb2.json b/.sqlx/query-f446c6ab881c166102f3b20056e0709be6fbcfc596063878c0bad9df00037dbe.json similarity index 58% rename from .sqlx/query-308962c26250f9312287a3f2f21e5da76e4cf488eedd4704019b4f14b6fbafb2.json rename to .sqlx/query-f446c6ab881c166102f3b20056e0709be6fbcfc596063878c0bad9df00037dbe.json index d9eb78e..4c5d1f4 100644 --- a/.sqlx/query-308962c26250f9312287a3f2f21e5da76e4cf488eedd4704019b4f14b6fbafb2.json +++ b/.sqlx/query-f446c6ab881c166102f3b20056e0709be6fbcfc596063878c0bad9df00037dbe.json @@ -1,30 +1,20 @@ { "db_name": "PostgreSQL", - "query": "SELECT * FROM item_classes WHERE id = $1", + "query": "SELECT name, parent, description FROM item_classes WHERE id = $1", "describe": { "columns": [ { "ordinal": 0, - "name": "id", - "type_info": "Uuid" - }, - { - "ordinal": 1, "name": "name", "type_info": "Varchar" }, { - "ordinal": 2, + "ordinal": 1, "name": "parent", "type_info": "Uuid" }, { - "ordinal": 3, - "name": "created_at", - "type_info": "Timestamptz" - }, - { - "ordinal": 4, + "ordinal": 2, "name": "description", "type_info": "Varchar" } @@ -35,12 +25,10 @@ ] }, "nullable": [ - false, false, true, - false, false ] }, - "hash": "308962c26250f9312287a3f2f21e5da76e4cf488eedd4704019b4f14b6fbafb2" + "hash": "f446c6ab881c166102f3b20056e0709be6fbcfc596063878c0bad9df00037dbe" } diff --git a/.sqlx/query-fc5e536bddb5d76021164ae4f5a6b0ad52d1ae047fd004f1359be7122facf8e7.json b/.sqlx/query-fc5e536bddb5d76021164ae4f5a6b0ad52d1ae047fd004f1359be7122facf8e7.json new file mode 100644 index 0000000..933db4d --- /dev/null +++ b/.sqlx/query-fc5e536bddb5d76021164ae4f5a6b0ad52d1ae047fd004f1359be7122facf8e7.json @@ -0,0 +1,26 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT id, name FROM item_classes", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "name", + "type_info": "Varchar" + } + ], + "parameters": { + "Left": [] + }, + "nullable": [ + false, + false + ] + }, + "hash": "fc5e536bddb5d76021164ae4f5a6b0ad52d1ae047fd004f1359be7122facf8e7" +} diff --git a/.sqlx/query-ff39480d9395b357d71e9af3eb37fa308f4df6a0ca6442fa7f9bbda1e34ffbbe.json b/.sqlx/query-ff39480d9395b357d71e9af3eb37fa308f4df6a0ca6442fa7f9bbda1e34ffbbe.json new file mode 100644 index 0000000..36cc7c5 --- /dev/null +++ b/.sqlx/query-ff39480d9395b357d71e9af3eb37fa308f4df6a0ca6442fa7f9bbda1e34ffbbe.json @@ -0,0 +1,34 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT items.id, items.name, item_classes.name AS \"class_name\"\n FROM items\n JOIN unnest((SELECT parents FROM item_tree WHERE id = $1))\n WITH ORDINALITY AS parents(id, n)\n ON items.id = parents.id\n JOIN item_classes\n ON items.class = item_classes.id\n ORDER BY parents.n", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Uuid" + }, + { + "ordinal": 1, + "name": "name", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "class_name", + "type_info": "Varchar" + } + ], + "parameters": { + "Left": [ + "Uuid" + ] + }, + "nullable": [ + false, + true, + false + ] + }, + "hash": "ff39480d9395b357d71e9af3eb37fa308f4df6a0ca6442fa7f9bbda1e34ffbbe" +} diff --git a/Cargo.lock b/Cargo.lock index c1243ca..99c9ad8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1113,6 +1113,15 @@ version = "1.70.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -1165,6 +1174,7 @@ dependencies = [ "enum-iterator", "env_logger", "futures-util", + "itertools", "log", "maud", "mime", diff --git a/Cargo.toml b/Cargo.toml index a087601..b2ed5d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ datamatrix = "0.3.1" enum-iterator = "2.1.0" env_logger = "0.11.3" futures-util = "0.3.30" +itertools = "0.13.0" log = "0.4.21" maud = { version = "0.26.0", features = ["actix-web"] } mime = "0.3.17" diff --git a/src/frontend/item/add.rs b/src/frontend/item/add.rs index d1d035c..f5eff99 100644 --- a/src/frontend/item/add.rs +++ b/src/frontend/item/add.rs @@ -8,12 +8,10 @@ use actix_identity::Identity; use actix_web::{error, get, post, web, HttpRequest, Responder}; use maud::html; use serde::Deserialize; -use sqlx::PgPool; +use sqlx::{query_scalar, PgPool}; use uuid::Uuid; use crate::frontend::templates::{self, datalist, forms, helpers::PageActionGroup, TemplateConfig}; -use crate::manage; -use crate::models::*; pub fn config(cfg: &mut web::ServiceConfig) { cfg.service(get).service(post); @@ -130,51 +128,64 @@ async fn post( user: Identity, ) -> actix_web::Result { let data = data.into_inner(); - let new_item = NewItem { - name: data.name, - class: data.class, - parent: data.parent, - original_packaging: data.original_packaging, - description: data.description, - }; if data.quantity == 1 { - let item = manage::item::add(&pool, new_item) - .await - .map_err(error::ErrorInternalServerError)?; - Ok( - web::Redirect::to("/item/".to_owned() + &item.id.to_string()) + query_scalar!( + "INSERT INTO items (name, parent, class, original_packaging, description) + VALUES ($1, $2, $3, $4, $5) + RETURNING id", + data.name, + data.parent, + data.class, + data.original_packaging, + data.description + ) + .fetch_one(pool.as_ref()) + .await + .map_err(error::ErrorInternalServerError) + .map(|id| { + web::Redirect::to("/item/".to_owned() + &id.to_string()) .see_other() .respond_to(&req) - .map_into_boxed_body(), - ) + .map_into_boxed_body() + }) } else { - let items = manage::item::add_multiple(&pool, new_item, data.quantity) - .await - .map_err(error::ErrorInternalServerError)?; - Ok(templates::base( - TemplateConfig { - path: "/items/add", - title: Some("Added Items"), - page_title: Some(Box::new("Added Items")), - page_actions: vec![PageActionGroup::generate_labels( - &items.iter().map(|i| i.id).collect::>(), - )], - user: Some(user), - ..Default::default() - }, - html! { - ul { - @for item in items { - li { - a href={ "/item/" (item.id) } { (item.id) } + query_scalar!( + "INSERT INTO items (name, parent, class, original_packaging, description) + SELECT * FROM UNNEST($1::VARCHAR[], $2::UUID[], $3::UUID[], $4::UUID[], $5::VARCHAR[]) + RETURNING id", + &vec![data.name; data.quantity] as &[Option], + &vec![data.parent; data.quantity] as &[Option], + &vec![data.class; data.quantity], + &vec![data.original_packaging; data.quantity] as &[Option], + &vec![data.description; data.quantity] + ) + .fetch_all(pool.as_ref()) + .await + .map_err(error::ErrorInternalServerError) + .map(|ids| { + templates::base( + TemplateConfig { + path: "/items/add", + title: Some("Added Items"), + page_title: Some(Box::new("Added Items")), + page_actions: vec![PageActionGroup::generate_labels(&ids)], + user: Some(user), + ..Default::default() + }, + html! { + ul { + @for id in &ids { + li { + a href={ "/item/" (id) } { (id) } + } } } - } - a href="/items" { "Back to all items" } - }, - ) - .respond_to(&req) - .map_into_boxed_body()) + a href="/items" { "Back to all items" } + }, + ) + .respond_to(&req) + .map_into_boxed_body() + }) } } diff --git a/src/frontend/item/delete.rs b/src/frontend/item/delete.rs index f7f548b..7da12b2 100644 --- a/src/frontend/item/delete.rs +++ b/src/frontend/item/delete.rs @@ -4,11 +4,9 @@ use actix_identity::Identity; use actix_web::{error, post, web, Responder}; -use sqlx::PgPool; +use sqlx::{query, PgPool}; use uuid::Uuid; -use crate::manage; - pub fn config(cfg: &mut web::ServiceConfig) { cfg.service(post); } @@ -21,7 +19,8 @@ async fn post( ) -> actix_web::Result { let id = path.into_inner(); - manage::item::delete(&pool, id) + query!("DELETE FROM items WHERE id = $1", id) + .execute(pool.as_ref()) .await .map_err(error::ErrorInternalServerError)?; diff --git a/src/frontend/item/edit.rs b/src/frontend/item/edit.rs index 69a0054..cf90bd0 100644 --- a/src/frontend/item/edit.rs +++ b/src/frontend/item/edit.rs @@ -7,17 +7,25 @@ use std::fmt::Display; use actix_identity::Identity; use actix_web::{error, get, post, web, Responder}; use maud::html; -use sqlx::PgPool; +use serde::Deserialize; +use sqlx::{query, PgPool}; use uuid::Uuid; use crate::frontend::templates::{self, datalist, forms, helpers::ItemName, TemplateConfig}; -use crate::manage; -use crate::models::*; pub fn config(cfg: &mut web::ServiceConfig) { cfg.service(get).service(post); } +#[derive(Deserialize)] +struct ItemEditForm { + name: Option, + parent: Option, + class: Uuid, + original_packaging: Option, + description: String, +} + #[get("/item/{id}/edit")] async fn get( pool: web::Data, @@ -26,13 +34,35 @@ async fn get( ) -> actix_web::Result { let id = path.into_inner(); - let item = manage::item::get(&pool, id) - .await - .map_err(error::ErrorInternalServerError)?; - - let item_class = manage::item_class::get(&pool, item.class) - .await - .map_err(error::ErrorInternalServerError)?; + let (item_name, form) = query!( + r#"SELECT + items.name, + items.parent, + items.class, + item_classes.name AS "class_name", + items.original_packaging, + items.description + FROM items + JOIN item_classes + ON items.class = item_classes.id + WHERE items.id = $1"#, + id + ) + .map(|row| { + ( + ItemName::new(row.name.as_ref(), &row.class_name), + ItemEditForm { + name: row.name, + parent: row.parent, + class: row.class, + original_packaging: row.original_packaging, + description: row.description, + }, + ) + }) + .fetch_one(pool.as_ref()) + .await + .map_err(error::ErrorInternalServerError)?; let datalist_items = datalist::items(&pool) .await @@ -42,13 +72,12 @@ async fn get( .await .map_err(error::ErrorInternalServerError)?; - let item_name = ItemName::new(item.name.as_ref(), &item_class.name); let mut title = item_name.to_string(); title.push_str(" – Edit Item"); Ok(templates::base( TemplateConfig { - path: &format!("/item/{}/edit", item.id), + path: &format!("/item/{}/edit", id), title: Some(&title), page_title: Some(Box::new(item_name.clone())), datalists: vec![&datalist_items, &datalist_item_classes], @@ -63,7 +92,7 @@ async fn get( title: "UUID", required: true, disabled: true, - value: Some(&item.id), + value: Some(&id), ..Default::default() }) (forms::InputGroup { @@ -71,8 +100,8 @@ async fn get( name: "name", title: "Name", optional: true, - disabled: item.name.is_none(), - value: item.name.as_ref().map(|s| s as &dyn Display), + disabled: form.name.is_none(), + value: form.name.as_ref().map(|s| s as &dyn Display), ..Default::default() }) (forms::InputGroup { @@ -80,7 +109,7 @@ async fn get( name: "class", title: "Class", required: true, - value: Some(&item.class), + value: Some(&form.class), datalist: Some(&datalist_item_classes), ..Default::default() }) @@ -89,8 +118,8 @@ async fn get( name: "parent", title: "Parent", optional: true, - value: item.parent.as_ref().map(|id| id as &dyn Display), - disabled: item.parent.is_none(), + value: form.parent.as_ref().map(|id| id as &dyn Display), + disabled: form.parent.is_none(), datalist: Some(&datalist_items), ..Default::default() }) @@ -99,8 +128,8 @@ async fn get( name: "original_packaging", title: "Original Packaging", optional: true, - value: item.original_packaging.as_ref().map(|id| id as &dyn Display), - disabled: item.original_packaging.is_none(), + value: form.original_packaging.as_ref().map(|id| id as &dyn Display), + disabled: form.original_packaging.is_none(), datalist: Some(&datalist_items), ..Default::default() }) @@ -108,7 +137,7 @@ async fn get( r#type: forms::InputType::Textarea, name: "description", title: "Description ", - value: Some(&item.description), + value: Some(&form.description), ..Default::default() }) @@ -122,14 +151,25 @@ async fn get( async fn post( pool: web::Data, path: web::Path, - data: web::Form, + data: web::Form, _user: Identity, ) -> actix_web::Result { let id = path.into_inner(); - let item = manage::item::update(&pool, id, data.into_inner()) - .await - .map_err(error::ErrorInternalServerError)?; + query!( + "UPDATE items + SET name = $2, parent = $3, class = $4, original_packaging = $5, description = $6 + WHERE id = $1", + id, + data.name, + data.parent, + data.class, + data.original_packaging, + data.description + ) + .execute(pool.as_ref()) + .await + .map_err(error::ErrorInternalServerError)?; - Ok(web::Redirect::to("/item/".to_owned() + &item.id.to_string()).see_other()) + Ok(web::Redirect::to("/item/".to_owned() + &id.to_string()).see_other()) } diff --git a/src/frontend/item/list.rs b/src/frontend/item/list.rs index 622ec9e..0af11a1 100644 --- a/src/frontend/item/list.rs +++ b/src/frontend/item/list.rs @@ -2,12 +2,10 @@ // // SPDX-License-Identifier: AGPL-3.0-or-later -use std::collections::HashMap; - use actix_identity::Identity; use actix_web::{error, get, web, Responder}; use maud::html; -use sqlx::PgPool; +use sqlx::{query, PgPool}; use uuid::Uuid; use crate::frontend::templates::{ @@ -15,44 +13,75 @@ use crate::frontend::templates::{ helpers::{Colour, ItemName, ItemPreview, PageAction, PageActionGroup, PageActionMethod}, TemplateConfig, }; -use crate::manage; -use crate::models::*; pub fn config(cfg: &mut web::ServiceConfig) { cfg.service(get); } +struct ItemListEntry { + id: Uuid, + name: ItemName, + class: Uuid, + class_name: String, + parents: Vec, +} + #[get("/items")] async fn get(pool: web::Data, user: Identity) -> actix_web::Result { - let item_list = manage::item::get_all(&pool) - .await - .map_err(error::ErrorInternalServerError)?; + let items = query!( + r#" + WITH RECURSIVE cte AS ( + SELECT + id, + ARRAY[]::UUID[] AS parents, + ARRAY[]::VARCHAR[] AS parent_names, + ARRAY[]::VARCHAR[] AS parent_class_names + FROM items + WHERE parent IS NULL - let items = manage::item::get_all_as_map(&pool) - .await - .map_err(error::ErrorInternalServerError)?; + UNION - let item_classes = manage::item_class::get_all_as_map(&pool) - .await - .map_err(error::ErrorInternalServerError)?; - - let item_tree = manage::item::get_all_parents(&pool) - .await - .map_err(error::ErrorInternalServerError)?; - - // TODO: remove clone (should be possible without it) - let item_parents: HashMap> = item_tree - .iter() - .map(|(id, parent_ids)| { - ( - *id, - parent_ids - .iter() - .map(|parent_id| items.get(parent_id).unwrap().clone()) - .collect(), - ) - }) - .collect(); + SELECT + items.id, + cte.parents || items.parent, + cte.parent_names || parent.name, + cte.parent_class_names || parent_class.name + FROM cte + JOIN items + ON items.parent = cte.id + JOIN items AS "parent" + ON parent.id = cte.id + JOIN item_classes AS "parent_class" + ON parent.class = parent_class.id + ) + SELECT + cte.id AS "id!", + items.name, + items.class, + item_classes.name AS "class_name", + cte.parents AS "parents!", + cte.parent_names AS "parent_names!: Vec>", + cte.parent_class_names AS "parent_class_names!" + FROM cte + JOIN items + ON cte.id = items.id + JOIN item_classes + ON items.class = item_classes.id + ORDER BY items.created_at + "# + ) + .map(|row| ItemListEntry { + id: row.id, + name: ItemName::new(row.name.as_ref(), &row.class_name), + class: row.class, + class_name: row.class_name, + parents: itertools::izip!(row.parents, row.parent_names, row.parent_class_names) + .map(|(id, name, class_name)| ItemPreview::from_parts(id, name.as_ref(), &class_name)) + .collect(), + }) + .fetch_all(pool.as_ref()) + .await + .map_err(error::ErrorInternalServerError)?; Ok(templates::base( TemplateConfig { @@ -82,24 +111,11 @@ async fn get(pool: web::Data, user: Identity) -> actix_web::Result>(), - false - )) - } + td { (ItemPreview::new(item.id, item.name.clone().terse())) } + td { a href={ "/item-class/" (item.class) } { (item.class_name) } } + td { (templates::helpers::parents_breadcrumb(item.name, &item.parents, false)) } } } } diff --git a/src/frontend/item/show.rs b/src/frontend/item/show.rs index 569a43c..a45da76 100644 --- a/src/frontend/item/show.rs +++ b/src/frontend/item/show.rs @@ -5,7 +5,7 @@ use actix_identity::Identity; use actix_web::{error, get, web, Responder}; use maud::html; -use sqlx::PgPool; +use sqlx::{query, PgPool}; use uuid::Uuid; use crate::frontend::templates::{ @@ -13,12 +13,21 @@ use crate::frontend::templates::{ helpers::{Colour, ItemName, ItemPreview, PageAction, PageActionGroup, PageActionMethod}, TemplateConfig, }; -use crate::manage; pub fn config(cfg: &mut web::ServiceConfig) { cfg.service(get); } +struct ItemDetails { + id: Uuid, + short_id: i32, + name: ItemName, + class: Uuid, + class_name: String, + original_packaging: Option, + description: String, +} + #[get("/item/{id}")] async fn get( pool: web::Data, @@ -27,46 +36,96 @@ async fn get( ) -> actix_web::Result { let id = path.into_inner(); - let item = manage::item::get(&pool, id) - .await - .map_err(error::ErrorInternalServerError)?; + let item = query!( + r#"SELECT + items.id, + items.short_id, + items.name, + items.class, + item_classes.name AS "class_name", + items.original_packaging, + op.name AS "original_packaging_name?", + op_class.name AS "original_packaging_class_name?", + items.description + FROM items + JOIN item_classes + ON items.class = item_classes.id + LEFT JOIN items AS "op" + ON items.original_packaging = op.id + LEFT JOIN item_classes AS "op_class" + ON op.class = op_class.id + WHERE items.id = $1"#, + id + ) + .map(|row| ItemDetails { + id: row.id, + short_id: row.short_id, + name: ItemName::new(row.name.as_ref(), &row.class_name), + class: row.class, + class_name: row.class_name, + original_packaging: row.original_packaging.map(|id| { + ItemPreview::from_parts( + id, + row.original_packaging_name.as_ref(), + &row.original_packaging_class_name.unwrap(), + ) + }), + description: row.description, + }) + .fetch_one(pool.as_ref()) + .await + .map_err(error::ErrorInternalServerError)?; - let item_classes = manage::item_class::get_all_as_map(&pool) - .await - .map_err(error::ErrorInternalServerError)?; + let parents = query!( + r#"SELECT items.id, items.name, item_classes.name AS "class_name" + FROM items + JOIN unnest((SELECT parents FROM item_tree WHERE id = $1)) + WITH ORDINALITY AS parents(id, n) + ON items.id = parents.id + JOIN item_classes + ON items.class = item_classes.id + ORDER BY parents.n"#, + id + ) + .map(|row| ItemPreview::from_parts(row.id, row.name.as_ref(), &row.class_name)) + .fetch_all(pool.as_ref()) + .await + .map_err(error::ErrorInternalServerError)?; - let parents = manage::item::get_parents_details(&pool, item.id) - .await - .map_err(error::ErrorInternalServerError)?; + let children = query!( + r#"SELECT items.id, items.name, item_classes.name AS "class_name" + FROM items + JOIN item_classes + ON items.class = item_classes.id + WHERE items.parent = $1"#, + id + ) + .map(|row| ItemPreview::from_parts(row.id, row.name.as_ref(), &row.class_name)) + .fetch_all(pool.as_ref()) + .await + .map_err(error::ErrorInternalServerError)?; - let children = manage::item::get_children(&pool, item.id) - .await - .map_err(error::ErrorInternalServerError)?; + let original_packaging_of = query!( + r#"SELECT items.id, items.name, item_classes.name AS "class_name" + FROM items + JOIN item_classes + ON items.class = item_classes.id + WHERE items.original_packaging = $1"#, + id + ) + .map(|row| ItemPreview::from_parts(row.id, row.name.as_ref(), &row.class_name)) + .fetch_all(pool.as_ref()) + .await + .map_err(error::ErrorInternalServerError)?; - let original_packaging = match item.original_packaging { - Some(id) => Some( - manage::item::get(&pool, id) - .await - .map_err(error::ErrorInternalServerError)?, - ), - None => None, - }; - - let original_packaging_of = manage::item::original_packaging_contents(&pool, id) - .await - .map_err(error::ErrorInternalServerError)?; - - let item_class = item_classes.get(&item.class).unwrap(); - - let item_name = ItemName::new(item.name.as_ref(), &item_class.name); - let mut title = item_name.to_string(); + let mut title = item.name.to_string(); title.push_str(" – Item Details"); Ok(templates::base( TemplateConfig { path: &format!("/item/{}", item.id), title: Some(&title), - page_title: Some(Box::new(item_name.clone())), + page_title: Some(Box::new(item.name.clone())), page_actions: vec![ (PageActionGroup::Button { action: PageAction { @@ -109,32 +168,21 @@ async fn get( } tr { th { "Name" } - td { (item_name.clone().terse()) } + td { (item.name.clone().terse()) } } tr { th { "Class" } - td { a href={ "/item-class/" (item.class) } { (item_class.name) } } + td { a href={ "/item-class/" (item.class) } { (item.class_name) } } } tr { th { "Parents" } - td { - (templates::helpers::parents_breadcrumb( - ItemName::new( - item.name.as_ref(), - &item_class.name - ), - &parents.iter().map(|parent| ItemPreview::from_parts(parent.id, parent.name.as_ref(), &item_classes.get(&parent.class).unwrap().name)).collect::>(), - true - )) - } + td { (templates::helpers::parents_breadcrumb(item.name, &parents, true)) } } tr { th { "Original Packaging" } td { - @if let Some(original_packaging) = original_packaging { - a - href={ "/item/" (original_packaging.id) } - { (ItemName::new(original_packaging.name.as_ref(), &item_classes.get(&original_packaging.class).unwrap().name)) } + @if let Some(original_packaging) = item.original_packaging { + (original_packaging) } @else { "-" } @@ -153,16 +201,14 @@ async fn get( } div { (PageActionGroup::generate_labels( - &children.iter().map(|i| i.id).collect::>(), + &children.iter().map(|ip| ip.id).collect::>(), )) } } ul { @for child in children { - li { - (ItemPreview::from_parts(child.id, child.name.as_ref(), &item_classes.get(&child.class).unwrap().name)) - } + li { (child) } } } } @@ -172,9 +218,7 @@ async fn get( ul { @for item in original_packaging_of { - li { - (ItemPreview::from_parts(item.id, item.name.as_ref(), &item_classes.get(&item.class).unwrap().name)) - } + li { (item) } } } } diff --git a/src/frontend/item_class/add.rs b/src/frontend/item_class/add.rs index 1e6860c..356e678 100644 --- a/src/frontend/item_class/add.rs +++ b/src/frontend/item_class/add.rs @@ -8,12 +8,10 @@ use actix_identity::Identity; use actix_web::{error, get, post, web, Responder}; use maud::html; use serde::Deserialize; -use sqlx::PgPool; +use sqlx::{query_scalar, PgPool}; use uuid::Uuid; use crate::frontend::templates::{self, datalist, forms, TemplateConfig}; -use crate::manage; -use crate::models::*; pub fn config(cfg: &mut web::ServiceConfig) { cfg.service(get).service(post); @@ -93,15 +91,18 @@ async fn post( _user: Identity, ) -> actix_web::Result { let data = data.into_inner(); - let item = manage::item_class::add( - &pool, - NewItemClass { - name: data.name, - parent: data.parent, - description: data.description, - }, + + let id = query_scalar!( + "INSERT INTO item_classes (name, parent, description) + VALUES ($1, $2, $3) + RETURNING id", + data.name, + data.parent, + data.description ) + .fetch_one(pool.as_ref()) .await .map_err(error::ErrorInternalServerError)?; - Ok(web::Redirect::to("/item-class/".to_owned() + &item.id.to_string()).see_other()) + + Ok(web::Redirect::to("/item-class/".to_owned() + &id.to_string()).see_other()) } diff --git a/src/frontend/item_class/delete.rs b/src/frontend/item_class/delete.rs index 4c5aa3e..cc4cb57 100644 --- a/src/frontend/item_class/delete.rs +++ b/src/frontend/item_class/delete.rs @@ -4,11 +4,9 @@ use actix_identity::Identity; use actix_web::{error, post, web, Responder}; -use sqlx::PgPool; +use sqlx::{query, PgPool}; use uuid::Uuid; -use crate::manage; - pub fn config(cfg: &mut web::ServiceConfig) { cfg.service(post); } @@ -21,7 +19,8 @@ async fn post( ) -> actix_web::Result { let id = path.into_inner(); - manage::item_class::delete(&pool, id) + query!("DELETE FROM item_classes WHERE id = $1", id) + .execute(pool.as_ref()) .await .map_err(error::ErrorInternalServerError)?; diff --git a/src/frontend/item_class/edit.rs b/src/frontend/item_class/edit.rs index 4c0b7ac..ee1473d 100644 --- a/src/frontend/item_class/edit.rs +++ b/src/frontend/item_class/edit.rs @@ -7,17 +7,23 @@ use std::fmt::Display; use actix_identity::Identity; use actix_web::{error, get, post, web, Responder}; use maud::html; -use sqlx::PgPool; +use serde::Deserialize; +use sqlx::{query, query_as, PgPool}; use uuid::Uuid; use crate::frontend::templates::{self, datalist, forms, TemplateConfig}; -use crate::manage; -use crate::models::*; pub fn config(cfg: &mut web::ServiceConfig) { cfg.service(get).service(post); } +#[derive(Deserialize)] +struct ItemClassEditForm { + name: String, + parent: Option, + description: String, +} + #[get("/item-class/{id}/edit")] async fn get( pool: web::Data, @@ -26,22 +32,27 @@ async fn get( ) -> actix_web::Result { let id = path.into_inner(); - let item_class = manage::item_class::get(&pool, id) - .await - .map_err(error::ErrorInternalServerError)?; + let form = query_as!( + ItemClassEditForm, + "SELECT name, parent, description FROM item_classes WHERE id = $1", + id + ) + .fetch_one(pool.as_ref()) + .await + .map_err(error::ErrorInternalServerError)?; let datalist_item_classes = datalist::item_classes(&pool) .await .map_err(error::ErrorInternalServerError)?; - let mut title = item_class.name.clone(); + let mut title = form.name.clone(); title.push_str(" – Item Details"); Ok(templates::base( TemplateConfig { path: &format!("/items-class/{}/add", id), title: Some(&title), - page_title: Some(Box::new(item_class.name.clone())), + page_title: Some(Box::new(form.name.clone())), datalists: vec![&datalist_item_classes], user: Some(user), ..Default::default() @@ -54,7 +65,7 @@ async fn get( title: "UUID", disabled: true, required: true, - value: Some(&item_class.id), + value: Some(&id), ..Default::default() }) (forms::InputGroup { @@ -62,7 +73,7 @@ async fn get( name: "name", title: "Name", required: true, - value: Some(&item_class.name), + value: Some(&form.name), ..Default::default() }) (forms::InputGroup { @@ -70,8 +81,8 @@ async fn get( name: "parent", title: "Parent", optional: true, - disabled: item_class.parent.is_none(), - value: item_class.parent.as_ref().map(|id| id as &dyn Display), + disabled: form.parent.is_none(), + value: form.parent.as_ref().map(|id| id as &dyn Display), datalist: Some(&datalist_item_classes), ..Default::default() }) @@ -79,7 +90,7 @@ async fn get( r#type: forms::InputType::Textarea, name: "description", title: "Description ", - value: Some(&item_class.description), + value: Some(&form.description), ..Default::default() }) @@ -93,14 +104,23 @@ async fn get( async fn post( pool: web::Data, path: web::Path, - data: web::Form, + data: web::Form, _user: Identity, ) -> actix_web::Result { let id = path.into_inner(); - let item_class = manage::item_class::update(&pool, id, data.into_inner()) - .await - .map_err(error::ErrorInternalServerError)?; + query!( + "UPDATE item_classes + SET name = $2, parent = $3, description = $4 + WHERE id = $1", + id, + data.name, + data.parent, + data.description + ) + .execute(pool.as_ref()) + .await + .map_err(error::ErrorInternalServerError)?; - Ok(web::Redirect::to("/item-class/".to_owned() + &item_class.id.to_string()).see_other()) + Ok(web::Redirect::to("/item-class/".to_owned() + &id.to_string()).see_other()) } diff --git a/src/frontend/item_class/list.rs b/src/frontend/item_class/list.rs index 9c9212c..498c397 100644 --- a/src/frontend/item_class/list.rs +++ b/src/frontend/item_class/list.rs @@ -5,29 +5,45 @@ use actix_identity::Identity; use actix_web::{error, get, web, Responder}; use maud::html; -use sqlx::PgPool; +use sqlx::{query, PgPool}; +use uuid::Uuid; use crate::frontend::templates::{ self, - helpers::{Colour, PageAction, PageActionGroup, PageActionMethod}, + helpers::{Colour, ItemClassPreview, PageAction, PageActionGroup, PageActionMethod}, TemplateConfig, }; -use crate::manage; pub fn config(cfg: &mut web::ServiceConfig) { cfg.service(get); } +struct ItemClassListEntry { + id: Uuid, + name: String, + parent: Option, +} + #[get("/item-classes")] async fn get(pool: web::Data, user: Identity) -> actix_web::Result { - let item_classes_ids = sqlx::query_scalar!("SELECT id FROM item_classes ORDER BY created_at") - .fetch_all(pool.as_ref()) - .await - .map_err(error::ErrorInternalServerError)?; - - let item_classes = manage::item_class::get_all_as_map(&pool) - .await - .map_err(error::ErrorInternalServerError)?; + let item_classes = query!( + r#"SELECT class.id, class.name, class.parent, parent.name AS "parent_name?" + FROM item_classes AS "class" + LEFT JOIN item_classes AS "parent" + ON class.parent = parent.id + ORDER BY class.created_at + "# + ) + .map(|row| ItemClassListEntry { + id: row.id, + name: row.name, + parent: row + .parent + .map(|id| ItemClassPreview::new(id, row.parent_name.unwrap())), + }) + .fetch_all(pool.as_ref()) + .await + .map_err(error::ErrorInternalServerError)?; Ok(templates::base( TemplateConfig { @@ -56,14 +72,12 @@ async fn get(pool: web::Data, user: Identity) -> actix_web::Result, +} + #[get("/item-class/{id}")] async fn get( pool: web::Data, @@ -27,26 +35,52 @@ async fn get( ) -> actix_web::Result { let id = path.into_inner(); - let item_class = manage::item_class::get(&pool, id) - .await - .map_err(error::ErrorInternalServerError)?; + let item_class = query!( + r#"SELECT + class.id, + class.name, + class.description, + class.parent, + parent.name AS "parent_name?" + FROM item_classes AS "class" + LEFT JOIN item_classes AS "parent" + ON class.parent = parent.id + WHERE class.id = $1"#, + id + ) + .map(|row| ItemClassDetails { + id: row.id, + name: row.name, + description: row.description, + parent: row + .parent + .map(|id| ItemClassPreview::new(id, row.parent_name.unwrap())), + }) + .fetch_one(pool.as_ref()) + .await + .map_err(error::ErrorInternalServerError)?; - // TODO: Once async closures are stable, use map_or on item_class.parent instead - let parent = match item_class.parent { - Some(id) => manage::item_class::get(&pool, id) - .await - .map(Some) - .map_err(error::ErrorInternalServerError)?, - None => None, - }; + let children = query_as!( + ItemClassPreview, + "SELECT id, name FROM item_classes WHERE parent = $1", + id + ) + .fetch_all(pool.as_ref()) + .await + .map_err(error::ErrorInternalServerError)?; - let children = manage::item_class::children(&pool, id) - .await - .map_err(error::ErrorInternalServerError)?; - - let items = manage::item_class::items(&pool, id) - .await - .map_err(error::ErrorInternalServerError)?; + let items = query!( + r#"SELECT items.id, items.name, item_classes.name AS "class_name" + FROM items + JOIN item_classes + ON items.class = item_classes.id + WHERE items.class = $1"#, + id + ) + .map(|row| ItemPreview::from_parts(row.id, row.name.as_ref(), &row.class_name)) + .fetch_all(pool.as_ref()) + .await + .map_err(error::ErrorInternalServerError)?; let mut title = item_class.name.clone(); title.push_str(" – Item Details"); @@ -107,10 +141,10 @@ async fn get( th { "Name" } td { (item_class.name) } } - @if let Some(parent) = parent { + @if let Some(parent) = item_class.parent { tr { th { "Parent" } - td { a href={ "/item-class/" (parent.id) } { (parent.name) } } + td { (parent) } } } tr { @@ -124,9 +158,7 @@ async fn get( ul { @for child in children { - li { - a href={ "/item-class/" (child.id) } { (child.name) } - } + li { (child) } } } } @@ -145,9 +177,7 @@ async fn get( ul { @for item in items { - li { - (ItemPreview::new(item.id, ItemName::new(item.name.as_ref(), &item_class.name).terse())) - } + li { (item) } } } } diff --git a/src/frontend/jump.rs b/src/frontend/jump.rs index a803f08..2f8ab13 100644 --- a/src/frontend/jump.rs +++ b/src/frontend/jump.rs @@ -5,16 +5,19 @@ use actix_identity::Identity; use actix_web::{error, get, web, Responder}; use serde::Deserialize; -use sqlx::PgPool; +use sqlx::{query, query_scalar, PgPool}; use uuid::Uuid; -use crate::manage; -use crate::models::EntityType; - pub fn config(cfg: &mut web::ServiceConfig) { cfg.service(get); } +#[derive(Deserialize)] +pub enum EntityType { + Item, + ItemClass, +} + #[derive(Deserialize)] struct JumpData { id: String, @@ -29,15 +32,29 @@ async fn get( let mut id = data.id.clone(); let entity_type = if let Ok(id) = Uuid::parse_str(&id) { - manage::query_entity_type(&pool, id) - .await - .map_err(error::ErrorInternalServerError)? + query!( + r#"SELECT type as "type!" + FROM (SELECT id, 'item' AS "type" FROM items + UNION ALL + SELECT id, 'item_class' AS "type" FROM item_classes) id_mapping + WHERE id = $1"#, + id + ) + .map(|row| match row.r#type.as_str() { + "item" => EntityType::Item, + "item_class" => EntityType::ItemClass, + _ => unreachable!("database returned impossible type"), + }) + .fetch_optional(pool.as_ref()) + .await + .map_err(error::ErrorInternalServerError)? } else if let Ok(short_id) = id.parse::() { - if let Ok(item) = manage::item::get_by_short_id(&pool, short_id) + if let Ok(id_) = query_scalar!("SELECT id FROM items WHERE short_id = $1", short_id) + .fetch_one(pool.as_ref()) .await .map_err(error::ErrorInternalServerError) { - id = item.id.to_string(); + id = id_.to_string(); Some(EntityType::Item) } else { None diff --git a/src/frontend/labels.rs b/src/frontend/labels.rs index 7b02acc..e0d9796 100644 --- a/src/frontend/labels.rs +++ b/src/frontend/labels.rs @@ -7,12 +7,12 @@ use actix_web::{error, get, post, web, Responder}; use maud::html; use serde::Deserialize; use serde_variant::to_variant_name; -use sqlx::PgPool; +use sqlx::{query, PgPool}; use uuid::Uuid; -use super::templates::{self, datalist, helpers::ItemName, TemplateConfig}; +use super::templates::{self, datalist, TemplateConfig}; +use crate::frontend::templates::helpers::ItemPreview; use crate::label::{Label, LabelPreset}; -use crate::manage; pub fn config(cfg: &mut web::ServiceConfig) { cfg.service(generate_post) @@ -35,11 +35,9 @@ async fn generate(pool: &PgPool, params: GenerateParams) -> actix_web::Result, uuid::Error>>() .map_err(error::ErrorInternalServerError)?; - let items = manage::item::get_multiple(pool, &ids) + Label::for_items(pool, &ids, params.preset.clone().into()) .await - .map_err(error::ErrorInternalServerError)?; - - Ok(Label::for_items(&items, params.preset.clone().into())) + .map_err(error::ErrorInternalServerError) } #[post("/labels/generate")] @@ -62,13 +60,16 @@ async fn generate_get( #[get("/labels")] async fn form(pool: web::Data, user: Identity) -> actix_web::Result { - let items = manage::item::get_all(&pool) - .await - .map_err(error::ErrorInternalServerError)?; - - let item_classes = manage::item_class::get_all_as_map(&pool) - .await - .map_err(error::ErrorInternalServerError)?; + let items = query!( + r#"SELECT items.id, items.name, item_classes.name AS "class_name" + FROM items + JOIN item_classes + ON items.class = item_classes.id"# + ) + .map(|row| ItemPreview::from_parts(row.id, row.name.as_ref(), &row.class_name)) + .fetch_all(pool.as_ref()) + .await + .map_err(error::ErrorInternalServerError)?; let datalist_items = datalist::items(&pool) .await @@ -120,8 +121,7 @@ async fn form(pool: web::Data, user: Identity) -> actix_web::Result Result { - let items = manage::item::get_all(pool).await?; - - let item_classes = manage::item_class::get_all_as_map(pool).await?; - Ok(Datalist { name: "items".to_string(), link_prefix: Some("/item/".to_string()), - options: items - .iter() - .map(|i| DatalistOption { - value: i.id.to_string(), - text: Box::new(ItemName::new( - i.name.as_ref(), - &item_classes.get(&i.class).unwrap().name, - )), - }) - .collect(), + options: query!( + r#"SELECT items.id, items.name, item_classes.name AS "class_name" + FROM items + JOIN item_classes + ON items.class = item_classes.id"# + ) + .fetch_all(pool) + .await? + .into_iter() + .map(|row| DatalistOption { + value: row.id.to_string(), + text: Box::new(ItemName::new(row.name.as_ref(), &row.class_name)), + }) + .collect(), }) } @@ -68,12 +67,13 @@ pub async fn item_classes(pool: &PgPool) -> Result { Ok(Datalist { name: "item-classes".to_string(), link_prefix: Some("/item-class/".to_string()), - options: manage::item_class::get_all(pool) + options: query!("SELECT id, name FROM item_classes") + .fetch_all(pool) .await? .into_iter() - .map(|ic| DatalistOption { - value: ic.id.to_string(), - text: Box::new(ic.name), + .map(|row| DatalistOption { + value: row.id.to_string(), + text: Box::new(row.name), }) .collect(), }) diff --git a/src/frontend/templates/helpers.rs b/src/frontend/templates/helpers.rs index 378bb3d..5462aeb 100644 --- a/src/frontend/templates/helpers.rs +++ b/src/frontend/templates/helpers.rs @@ -157,6 +157,25 @@ impl Render for ItemPreview { } } +pub struct ItemClassPreview { + pub id: Uuid, + pub name: String, +} + +impl ItemClassPreview { + pub fn new(id: Uuid, name: String) -> Self { + Self { id, name } + } +} + +impl Render for ItemClassPreview { + fn render(&self) -> Markup { + html! { + a href={ "/item-class/" (self.id) } { (self.name) } + } + } +} + pub enum PageActionMethod { Get, Post, diff --git a/src/label/mod.rs b/src/label/mod.rs index 941451c..3aae2d7 100644 --- a/src/label/mod.rs +++ b/src/label/mod.rs @@ -12,10 +12,10 @@ use barcode::{encode_code128, encode_data_matrix}; use pdf::{IndirectFontRef, PdfLayerReference}; use printpdf as pdf; use printpdf::{ImageTransform, Mm, PdfDocument, PdfDocumentReference, Pt, Px}; +use sqlx::{query_as, PgPool}; use thiserror::Error; use uuid::Uuid; -use crate::models::Item; pub use preset::LabelPreset; const FONT: Cursor<&[u8]> = Cursor::new(include_bytes!( @@ -247,16 +247,18 @@ impl Label { Ok(doc.ok_or(Error::NoPages)?.save_to_bytes()?) } - pub fn for_items(items: &[Item], config: LabelConfig) -> Self { - Label { - pages: items - .iter() - .map(|item| LabelPage { - id: Some(item.id), - short_id: Some(format!("{:06}", item.short_id)), - }) - .collect(), + pub async fn for_items(pool: &PgPool, ids: &[Uuid], config: LabelConfig) -> sqlx::Result { + Ok(Label { + pages: query_as!( + LabelPage, + r#"SELECT id AS "id?", to_char(short_id, '000000') AS "short_id?" + FROM items + WHERE id = ANY ($1)"#, + ids + ) + .fetch_all(pool) + .await?, config, - } + }) } } diff --git a/src/lib.rs b/src/lib.rs index 606f212..d9ec056 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,4 @@ pub mod frontend; pub mod label; -pub mod manage; pub mod middleware; -pub mod models; diff --git a/src/manage/item.rs b/src/manage/item.rs deleted file mode 100644 index 7bb35a2..0000000 --- a/src/manage/item.rs +++ /dev/null @@ -1,155 +0,0 @@ -// SPDX-FileCopyrightText: 2024 Simon Bruder -// -// SPDX-License-Identifier: AGPL-3.0-or-later - -use std::collections::HashMap; - -use sqlx::{query, query_as, query_scalar, PgPool}; -use uuid::Uuid; - -use crate::models::{Item, NewItem}; - -pub async fn add(pool: &PgPool, new_item: NewItem) -> Result { - query_as!( - Item, - "INSERT INTO items (name, parent, class, original_packaging, description) VALUES ($1, $2, $3, $4, $5) RETURNING *", - new_item.name, - new_item.parent, - new_item.class, - new_item.original_packaging, - new_item.description - ) - .fetch_one(pool) - .await -} - -pub async fn add_multiple( - pool: &PgPool, - new_item: NewItem, - quantity: usize, -) -> Result, sqlx::Error> { - query_as!( - Item, - r#"INSERT INTO items (name, parent, class, original_packaging, description) - SELECT * FROM UNNEST($1::VARCHAR[], $2::UUID[], $3::UUID[], $4::UUID[], $5::VARCHAR[]) - RETURNING *"#, - &vec![new_item.name; quantity] as &[Option], - &vec![new_item.parent; quantity] as &[Option], - &vec![new_item.class; quantity], - &vec![new_item.original_packaging; quantity] as &[Option], - &vec![new_item.description; quantity] - ) - .fetch_all(pool) - .await -} - -pub async fn get(pool: &PgPool, id: Uuid) -> Result { - query_as!(Item, "SELECT * FROM items WHERE id = $1", id) - .fetch_one(pool) - .await -} - -pub async fn get_by_short_id(pool: &PgPool, short_id: i32) -> Result { - query_as!(Item, "SELECT * FROM items WHERE short_id = $1", short_id) - .fetch_one(pool) - .await -} - -pub async fn get_all(pool: &PgPool) -> Result, sqlx::Error> { - query_as!(Item, "SELECT * FROM items ORDER BY created_at") - .fetch_all(pool) - .await -} - -pub async fn get_multiple(pool: &PgPool, ids: &[Uuid]) -> Result, sqlx::Error> { - query_as!(Item, "SELECT * FROM items WHERE id = ANY ($1)", ids) - .fetch_all(pool) - .await -} - -pub async fn get_all_as_map(pool: &PgPool) -> Result, sqlx::Error> { - Ok(get_all(pool) - .await? - .into_iter() - .map(|i| (i.id, i)) - .collect()) -} - -pub async fn update(pool: &PgPool, id: Uuid, modified_item: NewItem) -> Result { - query_as!( - Item, - "UPDATE items SET name = $2, parent = $3, class = $4, original_packaging = $5, description = $6 WHERE id = $1 RETURNING *", - id, - modified_item.name, - modified_item.parent, - modified_item.class, - modified_item.original_packaging, - modified_item.description - ) - .fetch_one(pool) - .await -} - -pub async fn delete(pool: &PgPool, id: Uuid) -> Result<(), sqlx::Error> { - let res = query!("DELETE FROM items WHERE id = $1", id) - .execute(pool) - .await?; - assert_eq!(res.rows_affected(), 1); - Ok(()) -} - -pub async fn get_parents(pool: &PgPool, id: Uuid) -> Result, sqlx::Error> { - // force nullable is required for all columns in views - query_scalar!( - r#"SELECT unnest(parents) as "parents!" FROM item_tree WHERE id = $1"#, - id - ) - .fetch_all(pool) - .await -} - -pub async fn get_all_parents(pool: &PgPool) -> Result>, sqlx::Error> { - let mut parents = HashMap::new(); - for row in query!(r#"SELECT id as "id!", parents as "parents!" FROM item_tree"#) - .fetch_all(pool) - .await? - { - parents.insert(row.id, row.parents); - } - Ok(parents) -} - -pub async fn get_parents_details(pool: &PgPool, id: Uuid) -> Result, sqlx::Error> { - query_as!( - Item, - "SELECT items.* - FROM items - INNER JOIN - unnest((SELECT parents FROM item_tree WHERE id = $1)) - WITH ORDINALITY AS parents(id, n) - ON items.id = parents.id - ORDER BY parents.n;", - id - ) - .fetch_all(pool) - .await -} - -pub async fn get_children(pool: &PgPool, id: Uuid) -> Result, sqlx::Error> { - query_as!(Item, "SELECT * FROM items WHERE parent = $1", id) - .fetch_all(pool) - .await -} - -pub async fn original_packaging_contents( - pool: &PgPool, - id: Uuid, -) -> Result, sqlx::Error> { - query_as!( - Item, - "SELECT * FROM items WHERE original_packaging = $1", - id - ) - .fetch_all(pool) - .await -} diff --git a/src/manage/item_class.rs b/src/manage/item_class.rs deleted file mode 100644 index c8505c9..0000000 --- a/src/manage/item_class.rs +++ /dev/null @@ -1,83 +0,0 @@ -// SPDX-FileCopyrightText: 2024 Simon Bruder -// -// SPDX-License-Identifier: AGPL-3.0-or-later - -use std::collections::HashMap; - -use sqlx::{query, query_as, PgPool}; -use uuid::Uuid; - -use crate::models::{Item, ItemClass, NewItemClass}; - -pub async fn add(pool: &PgPool, new_item_class: NewItemClass) -> Result { - query_as!( - ItemClass, - "INSERT INTO item_classes (name, parent, description) VALUES ($1, $2, $3) RETURNING *", - new_item_class.name, - new_item_class.parent, - new_item_class.description - ) - .fetch_one(pool) - .await -} - -pub async fn get(pool: &PgPool, id: Uuid) -> Result { - query_as!(ItemClass, "SELECT * FROM item_classes WHERE id = $1", id) - .fetch_one(pool) - .await -} - -pub async fn get_all(pool: &PgPool) -> Result, sqlx::Error> { - query_as!(ItemClass, "SELECT * FROM item_classes ORDER BY created_at") - .fetch_all(pool) - .await -} - -pub async fn get_all_as_map(pool: &PgPool) -> Result, sqlx::Error> { - Ok(get_all(pool) - .await? - .into_iter() - .map(|ic| (ic.id, ic)) - .collect()) -} - -pub async fn update( - pool: &PgPool, - id: Uuid, - modified_item_class: NewItemClass, -) -> Result { - query_as!( - ItemClass, - "UPDATE item_classes SET name = $2, parent = $3, description = $4 WHERE id = $1 RETURNING *", - id, - modified_item_class.name, - modified_item_class.parent, - modified_item_class.description - ) - .fetch_one(pool) - .await -} - -pub async fn items(pool: &PgPool, id: Uuid) -> Result, sqlx::Error> { - query_as!(Item, "SELECT * FROM items WHERE class = $1", id) - .fetch_all(pool) - .await -} - -pub async fn delete(pool: &PgPool, id: Uuid) -> Result<(), sqlx::Error> { - let res = query!("DELETE FROM item_classes WHERE id = $1", id) - .execute(pool) - .await?; - assert_eq!(res.rows_affected(), 1); - Ok(()) -} - -pub async fn children(pool: &PgPool, id: Uuid) -> Result, sqlx::Error> { - query_as!( - ItemClass, - "SELECT * FROM item_classes WHERE parent = $1", - id - ) - .fetch_all(pool) - .await -} diff --git a/src/manage/mod.rs b/src/manage/mod.rs deleted file mode 100644 index 35c0b31..0000000 --- a/src/manage/mod.rs +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-FileCopyrightText: 2024 Simon Bruder -// -// SPDX-License-Identifier: AGPL-3.0-or-later - -pub mod item; -pub mod item_class; - -use sqlx::{query, PgPool}; -use uuid::Uuid; - -use crate::models::EntityType; - -pub async fn query_entity_type(pool: &PgPool, id: Uuid) -> Result, sqlx::Error> { - Ok(query!( - r#"SELECT type as "type!" FROM - (SELECT id, 'item' AS "type" FROM items - UNION ALL - SELECT id, 'item_class' AS "type" FROM item_classes) id_mapping - WHERE id = $1"#, - id - ) - .fetch_optional(pool) - .await? - .map(|row| match row.r#type.as_str() { - "item" => EntityType::Item, - "item_class" => EntityType::ItemClass, - _ => unreachable!("database returned impossible type"), - })) -} diff --git a/src/models.rs b/src/models.rs deleted file mode 100644 index 9a0272c..0000000 --- a/src/models.rs +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-FileCopyrightText: 2024 Simon Bruder -// -// SPDX-License-Identifier: AGPL-3.0-or-later - -use serde::{Deserialize, Serialize}; -use time::OffsetDateTime; -use uuid::Uuid; - -#[derive(Deserialize)] -pub enum EntityType { - Item, - ItemClass, -} - -#[derive(Clone, Debug, Serialize, sqlx::FromRow)] -pub struct Item { - pub id: Uuid, - pub name: Option, - pub parent: Option, - pub class: Uuid, - #[serde(with = "time::serde::iso8601")] - pub created_at: OffsetDateTime, - pub short_id: i32, - pub original_packaging: Option, - pub description: String, -} - -#[derive(Debug, Deserialize)] -pub struct NewItem { - #[serde(default)] - pub name: Option, - #[serde(default)] - pub parent: Option, - pub class: Uuid, - pub original_packaging: Option, - pub description: String, -} - -#[derive(Clone, Debug, Serialize)] -pub struct ItemClass { - pub id: Uuid, - pub name: String, - #[serde(skip_serializing_if = "Option::is_none")] - pub parent: Option, - #[serde(with = "time::serde::iso8601")] - pub created_at: OffsetDateTime, - pub description: String, -} - -#[derive(Debug, Deserialize)] -pub struct NewItemClass { - pub name: String, - #[serde(default)] - pub parent: Option, - pub description: String, -}