dogy_backend_api/service/users/
models.rs1use chrono::{NaiveDate, NaiveDateTime};
2use serde::{Deserialize, Deserializer, Serialize};
3use sqlx::{FromRow, Type};
4use uuid::Uuid;
5
6#[derive(Serialize, Type, Deserialize)]
7#[serde(rename_all = "lowercase")]
8#[sqlx(type_name = "user_gender", rename_all = "lowercase")]
9pub enum Gender {
10 Male,
11 Female,
12 Other,
13}
14
15#[derive(Serialize, Type, Deserialize)]
16#[serde(rename_all = "lowercase")]
17#[sqlx(type_name = "subscription_type", rename_all = "lowercase")]
18pub enum SubscriptionType {
19 Active,
20 Inactive,
21 Unknown,
22}
23
24#[allow(dead_code)]
25#[derive(Serialize, Deserialize, Type)]
26#[serde(rename_all = "camelCase")]
27pub struct User {
28 #[serde(rename = "externalID", skip_deserializing)]
29 pub external_id: String,
30 pub name: String,
31 pub timezone: String,
32 pub gender: Gender,
33 pub has_onboarded: bool,
34}
35
36#[derive(Serialize, Deserialize, Type, FromRow)]
37#[serde(rename_all = "camelCase")]
38pub struct UserUpdate {
39 #[serde(skip_serializing_if = "Option::is_none")]
40 pub name: Option<String>,
41 #[serde(skip_serializing_if = "Option::is_none")]
42 pub timezone: Option<String>,
43 #[serde(skip_serializing_if = "Option::is_none")]
44 pub gender: Option<Gender>,
45 #[serde(skip_serializing_if = "Option::is_none")]
46 pub has_onboarded: Option<bool>,
47}
48
49#[allow(dead_code)]
50#[derive(Serialize, Deserialize, Type)]
51#[serde(rename_all = "camelCase")]
52pub struct UserNotification {
53 pub enabled: bool,
54 pub is_registered: bool,
55 pub daily_enabled: bool,
56 pub playtime_enabled: bool,
57}
58
59#[derive(Serialize, Deserialize, Type, FromRow)]
60#[serde(rename_all = "camelCase")]
61pub struct UserNotificationUpdate {
62 #[serde(skip_serializing_if = "Option::is_none")]
63 pub enabled: Option<bool>,
64 #[serde(skip_serializing_if = "Option::is_none")]
65 pub is_registered: Option<bool>,
66 #[serde(skip_serializing_if = "Option::is_none")]
67 pub daily_enabled: Option<bool>,
68 #[serde(skip_serializing_if = "Option::is_none")]
69 pub playtime_enabled: Option<bool>,
70}
71
72#[allow(dead_code)]
73#[derive(Serialize, Deserialize, Type)]
74#[serde(rename_all = "camelCase")]
75pub struct UserSubscription {
76 pub trial_start_date: Option<NaiveDate>,
77 pub subscription_type: SubscriptionType,
78 pub is_trial_mode: bool,
79}
80
81#[derive(Serialize, Deserialize, Type, FromRow)]
82#[serde(rename_all = "camelCase")]
83pub struct UserSubscriptionUpdate {
84 #[serde(
85 skip_serializing_if = "Option::is_none",
86 default,
87 deserialize_with = "deserialize_some"
88 )]
89 pub trial_start_date: Option<Option<NaiveDate>>,
90 #[serde(skip_serializing_if = "Option::is_none")]
91 pub subscription_type: Option<SubscriptionType>,
92 #[serde(skip_serializing_if = "Option::is_none")]
93 pub is_trial_mode: Option<bool>,
94}
95
96fn deserialize_some<'de, T, D>(deserializer: D) -> std::result::Result<Option<T>, D::Error>
97where
98 T: Deserialize<'de>,
99 D: Deserializer<'de>,
100{
101 Deserialize::deserialize(deserializer).map(Some)
102}
103
104#[derive(Serialize, Deserialize)]
105pub struct FullUser {
106 #[serde(flatten)]
107 pub base: User,
108 pub subscription: UserSubscription,
109 pub notifications: UserNotification,
110}
111
112#[derive(Type, FromRow)]
115pub struct JoinedFullUser {
116 pub id: Uuid,
117 pub created_at: NaiveDateTime,
118 pub updated_at: NaiveDateTime,
119 pub name: String,
120 pub external_id: String,
121 pub timezone: String,
122 pub gender: Gender,
123 pub has_onboarded: bool,
124 pub trial_start_date: Option<NaiveDate>,
125 pub subscription_type: SubscriptionType,
126 pub is_trial_mode: bool,
127 pub enabled: bool,
128 pub is_registered: bool,
129 pub daily_enabled: bool,
130 pub playtime_enabled: bool,
131}