feat(core): implement optimistic locking across all entities
Add VersionMismatch error variant and check_version() helper to erp-core. All 13 mutable entities now enforce version checking on update/delete: - erp-auth: user, role, organization, department, position - erp-config: dictionary, dictionary_item, menu, setting, numbering_rule - erp-workflow: process_definition, process_instance, task - erp-message: message, message_subscription Update DTOs to expose version in responses and require version in update requests. HTTP 409 Conflict returned on version mismatch.
This commit is contained in:
@@ -14,6 +14,7 @@ pub struct DictionaryItemResp {
|
||||
pub sort_order: i32,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub color: Option<String>,
|
||||
pub version: i32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, ToSchema)]
|
||||
@@ -24,6 +25,7 @@ pub struct DictionaryResp {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub description: Option<String>,
|
||||
pub items: Vec<DictionaryItemResp>,
|
||||
pub version: i32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Validate, ToSchema)]
|
||||
@@ -39,6 +41,7 @@ pub struct CreateDictionaryReq {
|
||||
pub struct UpdateDictionaryReq {
|
||||
pub name: Option<String>,
|
||||
pub description: Option<String>,
|
||||
pub version: i32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Validate, ToSchema)]
|
||||
@@ -57,6 +60,7 @@ pub struct UpdateDictionaryItemReq {
|
||||
pub value: Option<String>,
|
||||
pub sort_order: Option<i32>,
|
||||
pub color: Option<String>,
|
||||
pub version: i32,
|
||||
}
|
||||
|
||||
// --- Menu DTOs ---
|
||||
@@ -77,6 +81,7 @@ pub struct MenuResp {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub permission: Option<String>,
|
||||
pub children: Vec<MenuResp>,
|
||||
pub version: i32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Validate, ToSchema)]
|
||||
@@ -103,6 +108,7 @@ pub struct UpdateMenuReq {
|
||||
pub visible: Option<bool>,
|
||||
pub permission: Option<String>,
|
||||
pub role_ids: Option<Vec<Uuid>>,
|
||||
pub version: i32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Validate, ToSchema)]
|
||||
@@ -124,6 +130,8 @@ pub struct MenuItemReq {
|
||||
pub menu_type: Option<String>,
|
||||
pub permission: Option<String>,
|
||||
pub role_ids: Option<Vec<Uuid>>,
|
||||
/// 乐观锁版本号。更新已有菜单时必填。
|
||||
pub version: Option<i32>,
|
||||
}
|
||||
|
||||
// --- Setting DTOs ---
|
||||
@@ -136,11 +144,14 @@ pub struct SettingResp {
|
||||
pub scope_id: Option<Uuid>,
|
||||
pub setting_key: String,
|
||||
pub setting_value: serde_json::Value,
|
||||
pub version: i32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Validate, ToSchema)]
|
||||
pub struct UpdateSettingReq {
|
||||
pub setting_value: serde_json::Value,
|
||||
/// 乐观锁版本号。更新已有设置时必填,创建新设置时忽略。
|
||||
pub version: Option<i32>,
|
||||
}
|
||||
|
||||
/// 内部参数结构体,用于减少 SettingService::set 的参数数量。
|
||||
@@ -149,6 +160,8 @@ pub struct SetSettingParams {
|
||||
pub scope: String,
|
||||
pub scope_id: Option<Uuid>,
|
||||
pub value: serde_json::Value,
|
||||
/// 乐观锁版本号。更新已有设置时用于校验。
|
||||
pub version: Option<i32>,
|
||||
}
|
||||
|
||||
// --- Numbering Rule DTOs ---
|
||||
@@ -168,6 +181,7 @@ pub struct NumberingRuleResp {
|
||||
pub reset_cycle: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub last_reset_date: Option<String>,
|
||||
pub version: i32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Validate, ToSchema)]
|
||||
@@ -192,6 +206,7 @@ pub struct UpdateNumberingRuleReq {
|
||||
pub seq_length: Option<i32>,
|
||||
pub separator: Option<String>,
|
||||
pub reset_cycle: Option<String>,
|
||||
pub version: i32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, ToSchema)]
|
||||
|
||||
Reference in New Issue
Block a user