dogy_backend_api/service/users/
models.rs

1use 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// This struct should only be used when retrieving from the database and not for
113// serializing/deserializing.
114#[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}