koprogo_api/infrastructure/web/handlers/
charge_distribution_handlers.rs

1use crate::infrastructure::web::{AppState, AuthenticatedUser};
2use actix_web::{get, post, web, HttpResponse, Responder};
3use uuid::Uuid;
4
5/// POST /invoices/{id}/calculate-distribution - Calculate and save charge distribution
6/// Automatically called after invoice approval, or can be triggered manually
7/// Only accountant, syndic, or superadmin can calculate distribution
8#[post("/invoices/{expense_id}/calculate-distribution")]
9pub async fn calculate_and_save_distribution(
10    state: web::Data<AppState>,
11    user: AuthenticatedUser,
12    expense_id: web::Path<Uuid>,
13) -> impl Responder {
14    // Check permissions
15    if user.role != "accountant" && user.role != "syndic" && user.role != "superadmin" {
16        return HttpResponse::Forbidden().json(serde_json::json!({
17            "error": "Only accountant, syndic, or superadmin can calculate charge distributions"
18        }));
19    }
20
21    match state
22        .charge_distribution_use_cases
23        .calculate_and_save_distribution(*expense_id)
24        .await
25    {
26        Ok(distributions) => HttpResponse::Ok().json(serde_json::json!({
27            "message": "Charge distribution calculated successfully",
28            "count": distributions.len(),
29            "distributions": distributions
30        })),
31        Err(err) => HttpResponse::BadRequest().json(serde_json::json!({
32            "error": err
33        })),
34    }
35}
36
37/// GET /invoices/{id}/distribution - Get charge distribution for an invoice
38#[get("/invoices/{expense_id}/distribution")]
39pub async fn get_distribution_by_expense(
40    state: web::Data<AppState>,
41    expense_id: web::Path<Uuid>,
42) -> impl Responder {
43    match state
44        .charge_distribution_use_cases
45        .get_distribution_by_expense(*expense_id)
46        .await
47    {
48        Ok(distributions) => HttpResponse::Ok().json(distributions),
49        Err(err) => HttpResponse::InternalServerError().json(serde_json::json!({
50            "error": err
51        })),
52    }
53}
54
55/// GET /owners/{id}/distributions - Get all charge distributions for an owner
56#[get("/owners/{owner_id}/distributions")]
57pub async fn get_distributions_by_owner(
58    state: web::Data<AppState>,
59    owner_id: web::Path<Uuid>,
60) -> impl Responder {
61    match state
62        .charge_distribution_use_cases
63        .get_distributions_by_owner(*owner_id)
64        .await
65    {
66        Ok(distributions) => HttpResponse::Ok().json(distributions),
67        Err(err) => HttpResponse::InternalServerError().json(serde_json::json!({
68            "error": err
69        })),
70    }
71}
72
73/// GET /owners/{id}/total-due - Get total amount due for an owner
74#[get("/owners/{owner_id}/total-due")]
75pub async fn get_total_due_by_owner(
76    state: web::Data<AppState>,
77    owner_id: web::Path<Uuid>,
78) -> impl Responder {
79    match state
80        .charge_distribution_use_cases
81        .get_total_due_by_owner(*owner_id)
82        .await
83    {
84        Ok(total_due) => HttpResponse::Ok().json(serde_json::json!({
85            "owner_id": owner_id.to_string(),
86            "total_due": total_due
87        })),
88        Err(err) => HttpResponse::InternalServerError().json(serde_json::json!({
89            "error": err
90        })),
91    }
92}