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

@@ -206,11 +206,13 @@ impl TaskService {
let task_model = task_model.clone();
Box::pin(async move {
// 更新任务状态
let current_version = task_model.version;
let mut active: task::ActiveModel = task_model.clone().into();
active.status = Set("completed".to_string());
active.outcome = Set(Some(outcome));
active.form_data = Set(form_data);
active.completed_at = Set(Some(now));
active.version = Set(current_version + 1);
active.updated_at = Set(now);
active.updated_by = Set(operator_id);
active
@@ -297,8 +299,10 @@ impl TaskService {
));
}
let current_version = task_model.version;
let mut active: task::ActiveModel = task_model.into();
active.assignee_id = Set(Some(req.delegate_to));
active.version = Set(current_version + 1);
active.updated_at = Set(Utc::now());
active.updated_by = Set(operator_id);
@@ -372,6 +376,7 @@ impl TaskService {
created_at: m.created_at,
definition_name: None,
business_key: None,
version: m.version,
}
}
}