1use lazy_static::lazy_static;
2use std::collections::HashMap;
3use std::vec;
4use tardis::db::sea_orm::IdenStatic;
5use tardis::regex::Regex;
6
7use async_trait::async_trait;
8use tardis::basic::dto::TardisContext;
9use tardis::basic::field::TrimString;
10use tardis::basic::result::TardisResult;
11use tardis::db::reldb_client::IdResp;
12use tardis::db::sea_orm::sea_query::*;
13use tardis::db::sea_orm::*;
14use tardis::TardisFuns;
15use tardis::TardisFunsInst;
16
17use crate::rbum::domain::{rbum_item, rbum_item_attr, rbum_kind, rbum_kind_attr, rbum_rel_attr};
18use crate::rbum::dto::rbum_filer_dto::RbumKindAttrFilterReq;
19use crate::rbum::dto::rbum_filer_dto::RbumKindFilterReq;
20use crate::rbum::dto::rbum_kind_attr_dto::{RbumKindAttrAddReq, RbumKindAttrDetailResp, RbumKindAttrModifyReq, RbumKindAttrSummaryResp};
21use crate::rbum::dto::rbum_kind_dto::{RbumKindAddReq, RbumKindDetailResp, RbumKindModifyReq, RbumKindSummaryResp};
22use crate::rbum::rbum_enumeration::RbumScopeLevelKind;
23use crate::rbum::serv::rbum_crud_serv::{RbumCrudOperation, RbumCrudQueryPackage, R_URL_PART_CODE};
24use crate::rbum::serv::rbum_item_serv::{RbumItemAttrServ, RbumItemServ};
25use crate::rbum::serv::rbum_rel_serv::RbumRelAttrServ;
26
27pub struct RbumKindServ;
28pub struct RbumKindAttrServ;
29
30lazy_static! {
31 pub static ref EXTRACT_R: Regex = Regex::new(r"\{(.+?)\}").expect("extract {} error");
32}
33
34#[async_trait]
35impl RbumCrudOperation<rbum_kind::ActiveModel, RbumKindAddReq, RbumKindModifyReq, RbumKindSummaryResp, RbumKindDetailResp, RbumKindFilterReq> for RbumKindServ {
36 fn get_table_name() -> &'static str {
37 rbum_kind::Entity.table_name()
38 }
39
40 async fn before_add_rbum(add_req: &mut RbumKindAddReq, funs: &TardisFunsInst, _: &TardisContext) -> TardisResult<()> {
41 if !R_URL_PART_CODE.is_match(&add_req.code) {
42 return Err(funs.err().bad_request(&Self::get_obj_name(), "add", &format!("code {} is invalid", add_req.code), "400-rbum-*-code-illegal"));
43 }
44 if funs.db().count(Query::select().column(rbum_kind::Column::Id).from(rbum_kind::Entity).and_where(Expr::col(rbum_kind::Column::Code).eq(add_req.code.to_string()))).await?
45 > 0
46 {
47 return Err(funs.err().conflict(&Self::get_obj_name(), "add", &format!("code {} already exists", add_req.code), "409-rbum-*-code-exist"));
48 }
49 Ok(())
50 }
51
52 async fn package_add(add_req: &RbumKindAddReq, _: &TardisFunsInst, _: &TardisContext) -> TardisResult<rbum_kind::ActiveModel> {
53 Ok(rbum_kind::ActiveModel {
54 id: Set(TardisFuns::field.nanoid()),
55 module: Set(add_req.module.as_ref().unwrap_or(&"".to_string()).to_string()),
56 code: Set(add_req.code.to_string()),
57 name: Set(add_req.name.to_string()),
58 note: Set(add_req.note.as_ref().unwrap_or(&"".to_string()).to_string()),
59 icon: Set(add_req.icon.as_ref().unwrap_or(&"".to_string()).to_string()),
60 sort: Set(add_req.sort.unwrap_or(0)),
61 ext_table_name: Set(add_req.ext_table_name.as_ref().unwrap_or(&"".to_string()).to_string()),
62 scope_level: Set(add_req.scope_level.as_ref().unwrap_or(&RbumScopeLevelKind::Private).to_int()),
63 ..Default::default()
64 })
65 }
66
67 async fn package_modify(id: &str, modify_req: &RbumKindModifyReq, _: &TardisFunsInst, _: &TardisContext) -> TardisResult<rbum_kind::ActiveModel> {
68 let mut rbum_kind = rbum_kind::ActiveModel {
69 id: Set(id.to_string()),
70 ..Default::default()
71 };
72 if let Some(module) = &modify_req.module {
73 rbum_kind.module = Set(module.to_string());
74 }
75 if let Some(name) = &modify_req.name {
76 rbum_kind.name = Set(name.to_string());
77 }
78 if let Some(note) = &modify_req.note {
79 rbum_kind.note = Set(note.to_string());
80 }
81 if let Some(icon) = &modify_req.icon {
82 rbum_kind.icon = Set(icon.to_string());
83 }
84 if let Some(sort) = modify_req.sort {
85 rbum_kind.sort = Set(sort);
86 }
87 if let Some(ext_table_name) = &modify_req.ext_table_name {
88 rbum_kind.ext_table_name = Set(ext_table_name.to_string());
89 }
90 if let Some(scope_level) = &modify_req.scope_level {
91 rbum_kind.scope_level = Set(scope_level.to_int());
92 }
93 Ok(rbum_kind)
94 }
95
96 async fn before_delete_rbum(id: &str, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<Option<RbumKindDetailResp>> {
97 Self::check_ownership(id, funs, ctx).await?;
98 Self::check_exist_before_delete(id, RbumKindAttrServ::get_table_name(), rbum_kind_attr::Column::RelRbumKindId.as_str(), funs).await?;
99 Self::check_exist_before_delete(id, RbumItemServ::get_table_name(), rbum_item::Column::RelRbumKindId.as_str(), funs).await?;
100 Ok(None)
101 }
102
103 async fn package_query(is_detail: bool, filter: &RbumKindFilterReq, _: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<SelectStatement> {
104 let mut query = Query::select();
105 query.columns(vec![
106 (rbum_kind::Entity, rbum_kind::Column::Id),
107 (rbum_kind::Entity, rbum_kind::Column::Module),
108 (rbum_kind::Entity, rbum_kind::Column::Code),
109 (rbum_kind::Entity, rbum_kind::Column::Name),
110 (rbum_kind::Entity, rbum_kind::Column::Note),
111 (rbum_kind::Entity, rbum_kind::Column::Icon),
112 (rbum_kind::Entity, rbum_kind::Column::Sort),
113 (rbum_kind::Entity, rbum_kind::Column::ExtTableName),
114 (rbum_kind::Entity, rbum_kind::Column::OwnPaths),
115 (rbum_kind::Entity, rbum_kind::Column::Owner),
116 (rbum_kind::Entity, rbum_kind::Column::CreateTime),
117 (rbum_kind::Entity, rbum_kind::Column::UpdateTime),
118 (rbum_kind::Entity, rbum_kind::Column::ScopeLevel),
119 ]);
120 if let Some(module) = &filter.module {
121 query.and_where(Expr::col((rbum_kind::Entity, rbum_kind::Column::Module)).eq(module.to_string()));
122 }
123 query.from(rbum_kind::Entity).with_filter(Self::get_table_name(), &filter.basic, is_detail, true, ctx);
124 Ok(query)
125 }
126}
127
128impl RbumKindServ {
129 pub async fn get_rbum_kind_id_by_code(code: &str, funs: &TardisFunsInst) -> TardisResult<Option<String>> {
130 let resp = funs
131 .db()
132 .get_dto::<IdResp>(Query::select().column(rbum_kind::Column::Id).from(rbum_kind::Entity).and_where(Expr::col(rbum_kind::Column::Code).eq(code)))
133 .await?
134 .map(|r| r.id);
135 Ok(resp)
136 }
137}
138
139#[async_trait]
140impl RbumCrudOperation<rbum_kind_attr::ActiveModel, RbumKindAttrAddReq, RbumKindAttrModifyReq, RbumKindAttrSummaryResp, RbumKindAttrDetailResp, RbumKindAttrFilterReq>
141 for RbumKindAttrServ
142{
143 fn get_table_name() -> &'static str {
144 rbum_kind_attr::Entity.table_name()
145 }
146
147 async fn before_add_rbum(add_req: &mut RbumKindAttrAddReq, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> {
148 Self::check_scope(&add_req.rel_rbum_kind_id, RbumKindServ::get_table_name(), funs, ctx).await?;
149 if funs
150 .db()
151 .count(
152 Query::select()
153 .column(rbum_kind_attr::Column::Id)
154 .from(rbum_kind_attr::Entity)
155 .and_where(Expr::col(rbum_kind_attr::Column::Name).eq(add_req.name.to_string()))
156 .and_where(Expr::col(rbum_kind_attr::Column::Module).eq(add_req.module.as_ref().unwrap_or(&TrimString("".to_string())).to_string()))
157 .and_where(Expr::col(rbum_kind_attr::Column::RelRbumKindId).eq(add_req.rel_rbum_kind_id.as_str()))
158 .and_where(Expr::col(rbum_kind_attr::Column::OwnPaths).like(format!("{}%", ctx.own_paths).as_str())),
159 )
160 .await?
161 > 0
162 {
163 return Err(funs.err().conflict(&Self::get_obj_name(), "add", &format!("name {} already exists", add_req.name), "409-rbum-*-name-exist"));
164 }
165 Ok(())
166 }
167
168 async fn package_add(add_req: &RbumKindAttrAddReq, _: &TardisFunsInst, _: &TardisContext) -> TardisResult<rbum_kind_attr::ActiveModel> {
169 Ok(rbum_kind_attr::ActiveModel {
170 id: Set(TardisFuns::field.nanoid()),
171 module: Set(add_req.module.as_ref().unwrap_or(&TrimString("".to_string())).to_string()),
172 name: Set(add_req.name.to_string()),
173 label: Set(add_req.label.to_string()),
174 note: Set(add_req.note.as_ref().unwrap_or(&"".to_string()).to_string()),
175 sort: Set(add_req.sort.unwrap_or(0)),
176 position: Set(add_req.position.unwrap_or(false)),
177 capacity: Set(add_req.capacity.unwrap_or(false)),
178 overload: Set(add_req.overload.unwrap_or(false)),
179 secret: Set(add_req.secret.unwrap_or(false)),
180 main_column: Set(add_req.main_column.unwrap_or(false)),
181 idx: Set(add_req.idx.unwrap_or(false)),
182 data_type: Set(add_req.data_type.to_string()),
183 widget_type: Set(add_req.widget_type.to_string()),
184 widget_columns: Set(add_req.widget_columns.unwrap_or(0)),
185 hide: Set(add_req.hide.unwrap_or(false)),
186 show_by_conds: Set(add_req.show_by_conds.as_ref().unwrap_or(&"".to_string()).to_string()),
187 default_value: Set(add_req.default_value.as_ref().unwrap_or(&"".to_string()).to_string()),
188 dyn_default_value: Set(add_req.dyn_default_value.as_ref().unwrap_or(&"".to_string()).to_string()),
189 options: Set(add_req.options.as_ref().unwrap_or(&"".to_string()).to_string()),
190 dyn_options: Set(add_req.dyn_options.as_ref().unwrap_or(&"".to_string()).to_string()),
191 required: Set(add_req.required.unwrap_or(false)),
192 min_length: Set(add_req.min_length.unwrap_or(0)),
193 max_length: Set(add_req.max_length.unwrap_or(0)),
194 action: Set(add_req.action.as_ref().unwrap_or(&"".to_string()).to_string()),
195 ext: Set(add_req.ext.as_ref().unwrap_or(&"".to_string()).to_string()),
196 parent_attr_name: Set(add_req.parent_attr_name.as_ref().unwrap_or(&TrimString("".to_string())).to_string()),
197 rel_rbum_kind_id: Set(add_req.rel_rbum_kind_id.to_string()),
198 scope_level: Set(add_req.scope_level.as_ref().unwrap_or(&RbumScopeLevelKind::Private).to_int()),
199 ..Default::default()
200 })
201 }
202
203 async fn package_modify(id: &str, modify_req: &RbumKindAttrModifyReq, _: &TardisFunsInst, _: &TardisContext) -> TardisResult<rbum_kind_attr::ActiveModel> {
204 let mut rbum_kind_attr = rbum_kind_attr::ActiveModel {
205 id: Set(id.to_string()),
206 ..Default::default()
207 };
208 if let Some(label) = &modify_req.label {
209 rbum_kind_attr.label = Set(label.to_string());
210 }
211 if let Some(note) = &modify_req.note {
212 rbum_kind_attr.note = Set(note.to_string());
213 }
214 if let Some(sort) = modify_req.sort {
215 rbum_kind_attr.sort = Set(sort);
216 }
217 if let Some(position) = modify_req.position {
218 rbum_kind_attr.position = Set(position);
219 }
220 if let Some(capacity) = modify_req.capacity {
221 rbum_kind_attr.capacity = Set(capacity);
222 }
223 if let Some(overload) = modify_req.overload {
224 rbum_kind_attr.overload = Set(overload);
225 }
226 if let Some(secret) = modify_req.secret {
227 rbum_kind_attr.secret = Set(secret);
228 }
229 if let Some(main_column) = modify_req.main_column {
230 rbum_kind_attr.main_column = Set(main_column);
231 }
232 if let Some(idx) = modify_req.idx {
233 rbum_kind_attr.idx = Set(idx);
234 }
235 if let Some(data_type) = &modify_req.data_type {
236 rbum_kind_attr.data_type = Set(data_type.to_string());
237 }
238 if let Some(widget_type) = &modify_req.widget_type {
239 rbum_kind_attr.widget_type = Set(widget_type.to_string());
240 }
241 if let Some(widget_columns) = modify_req.widget_columns {
242 rbum_kind_attr.widget_columns = Set(widget_columns);
243 }
244 if let Some(hide) = modify_req.hide {
245 rbum_kind_attr.hide = Set(hide);
246 }
247 if let Some(show_by_conds) = &modify_req.show_by_conds {
248 rbum_kind_attr.show_by_conds = Set(show_by_conds.to_string());
249 }
250 if let Some(default_value) = &modify_req.default_value {
251 rbum_kind_attr.default_value = Set(default_value.to_string());
252 }
253 if let Some(dyn_default_value) = &modify_req.dyn_default_value {
254 rbum_kind_attr.dyn_default_value = Set(dyn_default_value.to_string());
255 }
256 if let Some(options) = &modify_req.options {
257 rbum_kind_attr.options = Set(options.to_string());
258 }
259 if let Some(dyn_options) = &modify_req.dyn_options {
260 rbum_kind_attr.dyn_options = Set(dyn_options.to_string());
261 }
262 if let Some(required) = modify_req.required {
263 rbum_kind_attr.required = Set(required);
264 }
265 if let Some(min_length) = modify_req.min_length {
266 rbum_kind_attr.min_length = Set(min_length);
267 }
268 if let Some(max_length) = modify_req.max_length {
269 rbum_kind_attr.max_length = Set(max_length);
270 }
271 if let Some(action) = &modify_req.action {
272 rbum_kind_attr.action = Set(action.to_string());
273 }
274 if let Some(ext) = &modify_req.ext {
275 rbum_kind_attr.ext = Set(ext.to_string());
276 }
277 if let Some(parent_attr_name) = &modify_req.parent_attr_name {
278 rbum_kind_attr.parent_attr_name = Set(parent_attr_name.to_string());
279 }
280 if let Some(scope_level) = &modify_req.scope_level {
281 rbum_kind_attr.scope_level = Set(scope_level.to_int());
282 }
283 Ok(rbum_kind_attr)
284 }
285
286 async fn before_delete_rbum(id: &str, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<Option<RbumKindAttrDetailResp>> {
287 Self::check_ownership(id, funs, ctx).await?;
288 Self::check_exist_before_delete(id, RbumItemAttrServ::get_table_name(), rbum_item_attr::Column::RelRbumKindAttrId.as_str(), funs).await?;
289 Self::check_exist_before_delete(id, RbumRelAttrServ::get_table_name(), rbum_rel_attr::Column::RelRbumKindAttrId.as_str(), funs).await?;
290 Ok(None)
291 }
292
293 async fn package_query(is_detail: bool, filter: &RbumKindAttrFilterReq, _: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<SelectStatement> {
294 let mut query = Query::select();
295 query
296 .columns(vec![
297 (rbum_kind_attr::Entity, rbum_kind_attr::Column::Id),
298 (rbum_kind_attr::Entity, rbum_kind_attr::Column::Module),
299 (rbum_kind_attr::Entity, rbum_kind_attr::Column::Name),
300 (rbum_kind_attr::Entity, rbum_kind_attr::Column::Label),
301 (rbum_kind_attr::Entity, rbum_kind_attr::Column::Note),
302 (rbum_kind_attr::Entity, rbum_kind_attr::Column::Sort),
303 (rbum_kind_attr::Entity, rbum_kind_attr::Column::Position),
304 (rbum_kind_attr::Entity, rbum_kind_attr::Column::Capacity),
305 (rbum_kind_attr::Entity, rbum_kind_attr::Column::Overload),
306 (rbum_kind_attr::Entity, rbum_kind_attr::Column::Secret),
307 (rbum_kind_attr::Entity, rbum_kind_attr::Column::Idx),
308 (rbum_kind_attr::Entity, rbum_kind_attr::Column::DataType),
309 (rbum_kind_attr::Entity, rbum_kind_attr::Column::WidgetType),
310 (rbum_kind_attr::Entity, rbum_kind_attr::Column::WidgetColumns),
311 (rbum_kind_attr::Entity, rbum_kind_attr::Column::MainColumn),
312 (rbum_kind_attr::Entity, rbum_kind_attr::Column::Hide),
313 (rbum_kind_attr::Entity, rbum_kind_attr::Column::ShowByConds),
314 (rbum_kind_attr::Entity, rbum_kind_attr::Column::DefaultValue),
315 (rbum_kind_attr::Entity, rbum_kind_attr::Column::DynDefaultValue),
316 (rbum_kind_attr::Entity, rbum_kind_attr::Column::Options),
317 (rbum_kind_attr::Entity, rbum_kind_attr::Column::DynOptions),
318 (rbum_kind_attr::Entity, rbum_kind_attr::Column::Required),
319 (rbum_kind_attr::Entity, rbum_kind_attr::Column::MinLength),
320 (rbum_kind_attr::Entity, rbum_kind_attr::Column::MaxLength),
321 (rbum_kind_attr::Entity, rbum_kind_attr::Column::Action),
322 (rbum_kind_attr::Entity, rbum_kind_attr::Column::Ext),
323 (rbum_kind_attr::Entity, rbum_kind_attr::Column::ParentAttrName),
324 (rbum_kind_attr::Entity, rbum_kind_attr::Column::RelRbumKindId),
325 (rbum_kind_attr::Entity, rbum_kind_attr::Column::OwnPaths),
326 (rbum_kind_attr::Entity, rbum_kind_attr::Column::Owner),
327 (rbum_kind_attr::Entity, rbum_kind_attr::Column::CreateTime),
328 (rbum_kind_attr::Entity, rbum_kind_attr::Column::UpdateTime),
329 (rbum_kind_attr::Entity, rbum_kind_attr::Column::ScopeLevel),
330 ])
331 .from(rbum_kind_attr::Entity);
332 if let Some(secret) = filter.secret {
333 query.and_where(Expr::col(rbum_kind_attr::Column::Secret).eq(secret));
334 }
335 if let Some(parent_attr_name) = &filter.parent_attr_name {
336 query.and_where(Expr::col(rbum_kind_attr::Column::ParentAttrName).eq(parent_attr_name.to_string()));
337 }
338 if is_detail {
339 query.expr_as(Expr::col((rbum_kind::Entity, rbum_kind::Column::Name)), Alias::new("rel_rbum_kind_name")).inner_join(
340 rbum_kind::Entity,
341 Expr::col((rbum_kind::Entity, rbum_kind::Column::Id)).equals((rbum_kind_attr::Entity, rbum_kind_attr::Column::RelRbumKindId)),
342 );
343 }
344 query.with_filter(Self::get_table_name(), &filter.basic, is_detail, true, ctx);
345 Ok(query)
346 }
347}
348
349impl RbumKindAttrServ {
350 pub fn url_replace(uri: &str, values: &HashMap<String, String>) -> TardisResult<String> {
358 let mut new_uri = uri.to_string();
359 for mat in EXTRACT_R.captures_iter(uri) {
360 let old_key = mat.get(0).expect("ignore").as_str();
361 let key = &old_key[1..old_key.len() - 1];
362 if let Some(value) = values.get(key) {
363 new_uri = new_uri.replace(old_key, value);
364 }
365 }
366 Ok(new_uri)
367 }
368
369 pub fn url_has_placeholder(uri: &str) -> TardisResult<bool> {
373 Ok(!EXTRACT_R.is_match(uri))
374 }
375}