1use qm_mongodb::bson::oid::ObjectId;
2
3use crate::ids::InfraContext;
4
5use super::{CustomerId, InstitutionId, OrganizationId};
6
7pub type ID = ObjectId;
8
9#[derive(
10 Debug,
11 Clone,
12 Copy,
13 PartialEq,
14 Eq,
15 PartialOrd,
16 Ord,
17 Hash,
18 Default,
19 serde::Serialize,
20 serde::Deserialize,
21)]
22pub struct OwnerId {
23 #[serde(skip_serializing_if = "Option::is_none")]
24 pub cid: Option<i64>,
25 #[serde(skip_serializing_if = "Option::is_none")]
26 pub oid: Option<i64>,
27 #[serde(skip_serializing_if = "Option::is_none")]
28 pub iid: Option<i64>,
29}
30
31impl From<CustomerId> for OwnerId {
32 fn from(value: CustomerId) -> Self {
33 Self {
34 cid: Some(value.unzip()),
35 ..Default::default()
36 }
37 }
38}
39
40impl From<OrganizationId> for OwnerId {
41 fn from(value: OrganizationId) -> Self {
42 let (cid, oid) = value.unzip();
43 Self {
44 cid: Some(cid),
45 oid: Some(oid),
46 ..Default::default()
47 }
48 }
49}
50
51impl From<InstitutionId> for OwnerId {
52 fn from(value: InstitutionId) -> Self {
53 let (cid, oid, iid) = value.unzip();
54 Self {
55 cid: Some(cid),
56 oid: Some(oid),
57 iid: Some(iid),
58 }
59 }
60}
61
62impl From<InfraContext> for OwnerId {
63 fn from(value: InfraContext) -> Self {
64 match value {
65 InfraContext::Customer(v) => v.into(),
66 InfraContext::Organization(v) => v.into(),
67 InfraContext::Institution(v) => v.into(),
68 }
69 }
70}
71
72impl<'a> TryFrom<&'a OwnerId> for InfraContext {
73 type Error = anyhow::Error;
74
75 fn try_from(value: &'a OwnerId) -> Result<Self, Self::Error> {
76 match value {
77 OwnerId {
78 cid: Some(cid),
79 oid: Some(oid),
80 iid: Some(iid),
81 } => Ok(InfraContext::Institution((*cid, *oid, *iid).into())),
82 OwnerId {
83 cid: Some(cid),
84 oid: Some(oid),
85 iid: None,
86 } => Ok(InfraContext::Organization((*cid, *oid).into())),
87 OwnerId {
88 cid: Some(cid),
89 oid: None,
90 iid: None,
91 } => Ok(InfraContext::Customer((*cid).into())),
92 _ => anyhow::bail!("invalid owner id"),
93 }
94 }
95}
96
97#[derive(Default, serde::Deserialize, serde::Serialize, Debug, Clone)]
98#[serde(transparent)]
99pub struct Owner {
100 #[serde(skip_serializing_if = "Owner::is_none")]
101 o: OwnerType,
102}
103
104impl Owner {
105 pub fn new(o: OwnerType) -> Self {
106 Self { o }
107 }
108
109 pub fn as_owner_id(&self) -> Option<&OwnerId> {
110 self.o.as_owner_id()
111 }
112}
113
114impl From<InfraContext> for Owner {
115 fn from(value: InfraContext) -> Self {
116 Self { o: value.into() }
117 }
118}
119
120#[derive(Default, serde::Deserialize, serde::Serialize, Debug, Clone)]
121#[serde(tag = "ty", content = "id")]
122pub enum OwnerType {
123 #[default]
124 None,
125 Customer(OwnerId),
126 Organization(OwnerId),
127 Institution(OwnerId),
128}
129
130impl OwnerType {
131 pub fn is_none(&self) -> bool {
132 matches!(self, Self::None)
133 }
134
135 pub fn as_owner_id(&self) -> Option<&OwnerId> {
136 match self {
137 OwnerType::None => None,
138 OwnerType::Customer(id) | OwnerType::Organization(id) | OwnerType::Institution(id) => {
139 Some(id)
140 }
141 }
142 }
143}
144
145impl From<InfraContext> for OwnerType {
146 fn from(value: InfraContext) -> Self {
147 match value {
148 InfraContext::Customer(v) => OwnerType::Customer(v.into()),
149 InfraContext::Organization(v) => OwnerType::Organization(v.into()),
150 InfraContext::Institution(v) => OwnerType::Institution(v.into()),
151 }
152 }
153}