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:
iven
2026-04-11 23:25:43 +08:00
parent 1fec5e2cf2
commit 5d6e1dc394
32 changed files with 549 additions and 184 deletions

View File

@@ -121,11 +121,13 @@ where
/// DELETE /api/v1/numbering-rules/:id
///
/// 软删除编号规则,设置 deleted_at 时间戳。
/// 需要请求体包含 version 字段用于乐观锁校验。
/// 需要 `numbering.delete` 权限。
pub async fn delete_numbering_rule<S>(
State(state): State<ConfigState>,
Extension(ctx): Extension<TenantContext>,
Path(id): Path<Uuid>,
Json(req): Json<DeleteNumberingVersionReq>,
) -> Result<Json<ApiResponse<()>>, AppError>
where
ConfigState: FromRef<S>,
@@ -133,8 +135,15 @@ where
{
require_permission(&ctx, "numbering.delete")?;
NumberingService::delete(id, ctx.tenant_id, ctx.user_id, &state.db, &state.event_bus)
.await?;
NumberingService::delete(
id,
ctx.tenant_id,
ctx.user_id,
req.version,
&state.db,
&state.event_bus,
)
.await?;
Ok(Json(ApiResponse {
success: true,
@@ -142,3 +151,9 @@ where
message: Some("编号规则已删除".to_string()),
}))
}
/// 删除编号规则的乐观锁版本号请求体。
#[derive(Debug, serde::Deserialize)]
pub struct DeleteNumberingVersionReq {
pub version: i32,
}