bios_basic/rbum/serv/
rbum_kind_serv.rs

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    /// URL replace
351    ///
352    /// URL替换
353    ///
354    /// Replace ``{key}`` in the URL with the value in values.
355    ///
356    /// 将URL中的 ``{key}`` 替换为values中的值。
357    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    /// Whether the URL contains unreplaced placeholders
370    ///
371    /// URL中是否包含未替换的占位符
372    pub fn url_has_placeholder(uri: &str) -> TardisResult<bool> {
373        Ok(!EXTRACT_R.is_match(uri))
374    }
375}