teamcraft/services/
requests.rs1use chrono::NaiveDate;
23use serde::Serialize;
24use serde_json::json;
25use sqlx::{PgConnection, PgPool};
26use uuid::Uuid;
27
28use crate::{
29 auth::Actor,
30 domain::{
31 self, NotificationKind, Priority, RequestDecision, RequestReason, RequestStatus, Role,
32 WebhookEvent,
33 },
34 error::{AppError, AppResult},
35 models::{Change, ChangeRequest, RequestAttachment, RequestComment, RequestItem},
36 services::{
37 access, audit, changes, next_counter,
38 notifications::{self, Notice},
39 users, webhooks, Page,
40 },
41 vault::Vault,
42};
43
44mod attachment_files;
45mod implementation;
46mod notices;
47mod permissions;
48mod queries;
49mod raising;
50#[cfg(test)]
51mod tests;
52mod triage;
53
54pub use attachment_files::*;
55pub use implementation::*;
56use notices::*;
57pub use permissions::*;
58pub use queries::*;
59pub use raising::*;
60pub use triage::*;
61
62pub const MAX_ATTACHMENT_BYTES: usize = 10 * 1024 * 1024;
64pub const MAX_ATTACHMENTS: i64 = 20;
66pub const MAX_ITEMS: i64 = 100;
68
69const REQUEST_SELECT: &str = "
70 SELECT cr.id, cr.number, cr.title, cr.description, cr.reason, cr.priority, cr.status,
71 cr.requested_by, rq.display_name AS requested_by_name,
72 cr.assignee, asg.display_name AS assignee_name, asg.username AS assignee_username,
73 cr.decision_comment, cr.decided_by, dby.display_name AS decided_by_name, cr.decided_at,
74 cr.due_date, cr.created_at, cr.updated_at, cr.closed_at,
75 (SELECT COUNT(*) FROM change_request_items x WHERE x.request_id = cr.id) AS item_count
76 FROM change_requests cr
77 JOIN users rq ON rq.id = cr.requested_by
78 LEFT JOIN users asg ON asg.id = cr.assignee
79 LEFT JOIN users dby ON dby.id = cr.decided_by";
80
81const OPEN_STATES: &str = "('new', 'in_triage', 'accepted', 'deferred')";
82
83pub fn status_of(request: &ChangeRequest) -> RequestStatus {
84 RequestStatus::parse(&request.status).unwrap_or(RequestStatus::Withdrawn)
85}