init feature

This commit is contained in:
arrelin
2025-12-24 15:38:36 +03:00
parent 0fdc20e750
commit fcd4199cbd
15 changed files with 994 additions and 2 deletions

View File

@@ -0,0 +1,225 @@
use axum::{
extract::{Path, State},
http::StatusCode,
Json,
};
use sea_orm::DatabaseConnection;
use serde::{Deserialize, Serialize};
#[allow(unused_imports)] // че за хуйня раст?
use serde_json::json;
use utoipa::ToSchema;
use crate::models::shopping_item::Model as ShoppingItemModel;
use crate::services::ShoppingItemService;
#[derive(Debug, Deserialize, ToSchema)]
#[schema(example = json!({"name": "Milk"}))]
pub struct CreateShoppingItemRequest {
pub name: String,
}
#[derive(Debug, Deserialize, ToSchema)]
#[schema(example = json!({"name": "Updated item name"}))]
pub struct UpdateShoppingItemRequest {
pub name: String,
}
#[derive(Debug, Deserialize, ToSchema)]
#[schema(example = json!({"is_purchased": true}))]
pub struct MarkAsPurchasedRequest {
pub is_purchased: bool,
}
#[derive(Debug, Serialize, ToSchema)]
#[schema(example = json!({"affected_rows": 5}))]
pub struct BulkOperationResponse {
pub affected_rows: u64,
}
#[utoipa::path(
post,
path = "/families/{family_id}/shopping-items",
tag = "shopping-items",
params(
("family_id" = i32, Path, description = "Family ID")
),
request_body = CreateShoppingItemRequest,
responses(
(status = 200, description = "Shopping item created successfully", body = ShoppingItemModel),
(status = 500, description = "Internal server error")
)
)]
pub async fn create_shopping_item(
State(db): State<DatabaseConnection>,
Path(family_id): Path<i32>,
Json(payload): Json<CreateShoppingItemRequest>,
) -> Result<Json<ShoppingItemModel>, StatusCode> {
ShoppingItemService::create(&db, family_id, payload.name)
.await
.map(Json)
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
}
#[utoipa::path(
get,
path = "/families/{family_id}/shopping-items",
tag = "shopping-items",
params(
("family_id" = i32, Path, description = "Family ID")
),
responses(
(status = 200, description = "List of shopping items", body = Vec<ShoppingItemModel>),
(status = 500, description = "Internal server error")
)
)]
pub async fn get_shopping_items_by_family(
State(db): State<DatabaseConnection>,
Path(family_id): Path<i32>,
) -> Result<Json<Vec<ShoppingItemModel>>, StatusCode> {
ShoppingItemService::find_by_family(&db, family_id)
.await
.map(Json)
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
}
#[utoipa::path(
get,
path = "/families/{family_id}/shopping-items/{id}",
tag = "shopping-items",
params(
("family_id" = i32, Path, description = "Family ID"),
("id" = i32, Path, description = "Shopping item ID")
),
responses(
(status = 200, description = "Shopping item found", body = ShoppingItemModel),
(status = 404, description = "Shopping item not found"),
(status = 500, description = "Internal server error")
)
)]
pub async fn get_shopping_item(
State(db): State<DatabaseConnection>,
Path((_family_id, id)): Path<(i32, i32)>,
) -> Result<Json<ShoppingItemModel>, StatusCode> {
ShoppingItemService::find_by_id(&db, id)
.await
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?
.map(Json)
.ok_or(StatusCode::NOT_FOUND)
}
#[utoipa::path(
put,
path = "/families/{family_id}/shopping-items/{id}",
tag = "shopping-items",
params(
("family_id" = i32, Path, description = "Family ID"),
("id" = i32, Path, description = "Shopping item ID")
),
request_body = UpdateShoppingItemRequest,
responses(
(status = 200, description = "Shopping item updated successfully", body = ShoppingItemModel),
(status = 500, description = "Internal server error")
)
)]
pub async fn update_shopping_item(
State(db): State<DatabaseConnection>,
Path((_family_id, id)): Path<(i32, i32)>,
Json(payload): Json<UpdateShoppingItemRequest>,
) -> Result<Json<ShoppingItemModel>, StatusCode> {
ShoppingItemService::update(&db, id, payload.name)
.await
.map(Json)
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
}
#[utoipa::path(
delete,
path = "/families/{family_id}/shopping-items/{id}",
tag = "shopping-items",
params(
("family_id" = i32, Path, description = "Family ID"),
("id" = i32, Path, description = "Shopping item ID")
),
responses(
(status = 204, description = "Shopping item deleted successfully"),
(status = 500, description = "Internal server error")
)
)]
pub async fn delete_shopping_item(
State(db): State<DatabaseConnection>,
Path((_family_id, id)): Path<(i32, i32)>,
) -> Result<StatusCode, StatusCode> {
ShoppingItemService::delete(&db, id)
.await
.map(|_| StatusCode::NO_CONTENT)
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
}
#[utoipa::path(
patch,
path = "/families/{family_id}/shopping-items/{id}/purchased",
tag = "shopping-items",
params(
("family_id" = i32, Path, description = "Family ID"),
("id" = i32, Path, description = "Shopping item ID")
),
request_body = MarkAsPurchasedRequest,
responses(
(status = 200, description = "Shopping item marked as purchased", body = ShoppingItemModel),
(status = 500, description = "Internal server error")
)
)]
pub async fn mark_as_purchased(
State(db): State<DatabaseConnection>,
Path((_family_id, id)): Path<(i32, i32)>,
Json(payload): Json<MarkAsPurchasedRequest>,
) -> Result<Json<ShoppingItemModel>, StatusCode> {
ShoppingItemService::mark_as_purchased(&db, id, payload.is_purchased)
.await
.map(Json)
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
}
#[utoipa::path(
post,
path = "/families/{family_id}/shopping-items/mark-all-purchased",
tag = "shopping-items",
params(
("family_id" = i32, Path, description = "Family ID")
),
responses(
(status = 200, description = "All shopping items marked as purchased", body = BulkOperationResponse),
(status = 500, description = "Internal server error")
)
)]
pub async fn mark_all_as_purchased(
State(db): State<DatabaseConnection>,
Path(family_id): Path<i32>,
) -> Result<Json<BulkOperationResponse>, StatusCode> {
ShoppingItemService::mark_all_as_purchased(&db, family_id)
.await
.map(|affected_rows| Json(BulkOperationResponse { affected_rows }))
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
}
#[utoipa::path(
delete,
path = "/families/{family_id}/shopping-items/clear-all",
tag = "shopping-items",
params(
("family_id" = i32, Path, description = "Family ID")
),
responses(
(status = 200, description = "All shopping items cleared", body = BulkOperationResponse),
(status = 500, description = "Internal server error")
)
)]
pub async fn clear_all(
State(db): State<DatabaseConnection>,
Path(family_id): Path<i32>,
) -> Result<Json<BulkOperationResponse>, StatusCode> {
ShoppingItemService::clear_all(&db, family_id)
.await
.map(|result| Json(BulkOperationResponse { affected_rows: result.rows_affected }))
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
}