1use crate::api::endpoints::PathPart;
3use crate::domain::billing::{Account, AccountUser, AdminSchool, SchoolNameId};
4use crate::domain::user::UserId;
5use crate::domain::{billing::SchoolId, ItemCount, Page, PageLimit};
6use chrono::Utc;
7use macros::make_path_parts;
8use serde::{Deserialize, Serialize};
9use strum_macros::{Display, EnumIter};
10
11make_path_parts!(AdminUserExportPath => "/v1/admin/export/users");
12#[derive(Serialize, Deserialize, Debug, Clone)]
14pub struct AdminUserExportRequest {
15 pub date_filter_type: DateFilterType,
17 pub from_date: Option<chrono::DateTime<Utc>>,
19 pub to_date: Option<chrono::DateTime<Utc>>,
21}
22
23make_path_parts!(AdminJigExportPath => "/v1/admin/export/jigs");
24
25make_path_parts!(AdminPlaylistExportPath => "/v1/admin/export/playlists");
26
27#[derive(Display, EnumIter, Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
29#[serde(rename_all = "lowercase")]
30pub enum DateFilterType {
31 #[strum(serialize = "Only new records")]
33 OnlyNew,
34 #[strum(serialize = "Only updated records")]
36 OnlyUpdated,
37 #[strum(serialize = "New or updated records")]
39 Either,
40}
41
42impl Default for DateFilterType {
43 fn default() -> Self {
44 Self::OnlyNew
45 }
46}
47
48make_path_parts!(AdminSchoolsPath => "/v1/admin/schools");
49
50#[derive(Default, Serialize, Deserialize, Debug, Clone)]
52pub struct SearchSchoolsParams {
53 #[serde(skip_serializing_if = "Option::is_none")]
55 pub q: Option<String>,
56 #[serde(skip_serializing_if = "Option::is_none")]
58 pub verified: Option<bool>,
59 #[serde(default)]
61 pub page: Page,
62 #[serde(default)]
64 pub page_limit: PageLimit,
65}
66
67#[derive(Serialize, Deserialize, Debug, Clone)]
69pub struct SearchSchoolsResponse {
70 pub schools: Vec<AdminSchool>,
72 pub pages: ItemCount,
74 pub total_schools_count: ItemCount,
76}
77
78make_path_parts!(AdminSchoolAccountPath => "/v1/admin/schools/{}" => SchoolId);
79
80#[derive(Debug, Serialize, Deserialize, Clone)]
82pub struct GetAdminSchoolAccountResponse {
83 pub school: AdminSchool,
85 pub account: Account,
87 pub users: Vec<AccountUser>,
89}
90
91make_path_parts!(AdminVerifySchoolPath => "/v1/admin/schools/verify");
92
93#[derive(Serialize, Deserialize, Debug, Clone)]
95pub struct VerifySchoolRequest {
96 pub school_id: SchoolId,
98 pub verified: bool,
100}
101
102make_path_parts!(ImportSchoolNamesPath => "/v1/admin/import-school-names");
103
104make_path_parts!(InviteSchoolUsersPath => "/v1/admin/invite-users");
105
106#[derive(Serialize, Deserialize, Debug, Clone)]
109pub struct InviteSchoolUsersRequest {
110 pub school_id: SchoolId,
112 pub data: String,
114}
115
116#[derive(Serialize, Deserialize, Debug, Clone)]
118pub struct InviteSchoolUsersResponse {
119 pub failures: Vec<InviteSchoolUserFailure>,
121}
122
123#[derive(Serialize, Deserialize, Debug, Clone)]
125pub struct InviteSchoolUserFailure {
126 pub email: String,
128 pub reason: InviteFailedReason,
130}
131
132#[derive(Display, Serialize, Deserialize, Debug, Clone)]
134pub enum InviteFailedReason {
135 #[strum(serialize = "Has individual account")]
137 HasIndividualAccount,
138 #[strum(serialize = "Associated with another school")]
140 AssociatedWithSchool,
141 #[strum(serialize = "Not found")]
143 UserNotFound,
144 #[strum(serialize = "Incomplete profile")]
146 IncompleteProfile,
147}
148
149make_path_parts!(SchoolNamesPath => "/v1/admin/school-names");
150
151make_path_parts!(UpdateSchoolNamePath => "/v1/admin/school-names/{}" => SchoolNameId);
152
153make_path_parts!(SetInternalSchoolNamePath => "/v1/admin/schools/{}/school-name" => SchoolId);
154
155make_path_parts!(SetAccountTierOverridePath => "/v1/admin/users/{}/tier-override" => UserId);
156
157make_path_parts!(DeleteUserAccountPath => "/v1/admin/users/{}/account" => UserId);
158
159make_path_parts!(RemoveUserFromSchoolPath => "/v1/admin/schools/{}/users" => SchoolId);