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    _user: AuthenticatedUser,
42    expense_id: web::Path<Uuid>,
43) -> impl Responder {
44    match state
45        .charge_distribution_use_cases
46        .get_distribution_by_expense(*expense_id)
47        .await
48    {
49        Ok(distributions) => HttpResponse::Ok().json(distributions),
50        Err(err) => HttpResponse::InternalServerError().json(serde_json::json!({
51            "error": err
52        })),
53    }
54}
55
56/// GET /owners/{id}/distributions - Get all charge distributions for an owner
57#[get("/owners/{owner_id}/distributions")]
58pub async fn get_distributions_by_owner(
59    state: web::Data<AppState>,
60    owner_id: web::Path<Uuid>,
61) -> impl Responder {
62    match state
63        .charge_distribution_use_cases
64        .get_distributions_by_owner(*owner_id)
65        .await
66    {
67        Ok(distributions) => HttpResponse::Ok().json(distributions),
68        Err(err) => HttpResponse::InternalServerError().json(serde_json::json!({
69            "error": err
70        })),
71    }
72}
73
74/// GET /owners/{id}/total-due - Get total amount due for an owner
75#[get("/owners/{owner_id}/total-due")]
76pub async fn get_total_due_by_owner(
77    state: web::Data<AppState>,
78    owner_id: web::Path<Uuid>,
79) -> impl Responder {
80    match state
81        .charge_distribution_use_cases
82        .get_total_due_by_owner(*owner_id)
83        .await
84    {
85        Ok(total_due) => HttpResponse::Ok().json(serde_json::json!({
86            "owner_id": owner_id.to_string(),
87            "total_due": total_due
88        })),
89        Err(err) => HttpResponse::InternalServerError().json(serde_json::json!({
90            "error": err
91        })),
92    }
93}