revert document types
This commit is contained in:
@@ -248,23 +248,6 @@ pub struct Document {
|
||||
pub title: String,
|
||||
pub current_version_id: Uuid,
|
||||
pub tenant_id: Uuid,
|
||||
pub document_type_id: Option<Uuid>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Queryable, Identifiable)]
|
||||
#[diesel(table_name = document_types)]
|
||||
pub struct DocumentType {
|
||||
pub id: Uuid,
|
||||
pub tenant_id: Uuid,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Insertable)]
|
||||
#[diesel(table_name = document_types)]
|
||||
pub struct NewDocumentType {
|
||||
pub id: Uuid,
|
||||
pub tenant_id: Uuid,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Insertable)]
|
||||
@@ -280,7 +263,6 @@ pub struct NewDocument {
|
||||
pub issued_at: Option<NaiveDateTime>,
|
||||
pub title: String,
|
||||
pub tenant_id: Uuid,
|
||||
pub document_type_id: Option<Uuid>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Queryable, Identifiable, Associations)]
|
||||
|
||||
@@ -10,7 +10,6 @@ impl OpenApi for ApiDoc {
|
||||
doc.merge(crate::routes::documents::DocumentsApiDoc::openapi());
|
||||
doc.merge(crate::routes::folders::FoldersApiDoc::openapi());
|
||||
doc.merge(crate::routes::tags::TagsApiDoc::openapi());
|
||||
doc.merge(crate::routes::document_types::DocumentTypesApiDoc::openapi());
|
||||
doc.merge(crate::routes::correspondents::CorrespondentsApiDoc::openapi());
|
||||
doc.merge(crate::routes::profile::ProfileApiDoc::openapi());
|
||||
|
||||
@@ -44,10 +43,6 @@ impl OpenApi for ApiDoc {
|
||||
.name("Tags")
|
||||
.description(Some("Tag catalog"))
|
||||
.build(),
|
||||
TagBuilder::new()
|
||||
.name("DocumentTypes")
|
||||
.description(Some("Document type catalog"))
|
||||
.build(),
|
||||
TagBuilder::new()
|
||||
.name("Correspondents")
|
||||
.description(Some("Correspondent catalog"))
|
||||
@@ -82,16 +77,14 @@ pub mod schemas {
|
||||
CorrespondentSummary, CorrespondentUsage, CreateCorrespondentRequest,
|
||||
UpdateCorrespondentRequest,
|
||||
};
|
||||
pub use crate::routes::document_types::{CreateDocumentTypeRequest, UpdateDocumentTypeRequest};
|
||||
pub use crate::routes::documents::{
|
||||
AssetObjectsQuery, AssetRequestQuery, AssignCorrespondentsRequest, AssignTagsRequest,
|
||||
BulkCorrespondentAction, BulkCorrespondentResponse, BulkCorrespondentsRequest,
|
||||
BulkMoveRequest, BulkMoveResponse, BulkReanalyzeResponse, BulkReanalyzeSelectionRequest,
|
||||
BulkTagAction, BulkTagRequest, BulkTagResponse, CorrespondentAssignmentInput,
|
||||
DocumentCheckQuery, DocumentCheckResponse, DocumentDetailResponse, DocumentListQuery,
|
||||
DocumentMetadataUpdate, DocumentResponse, DocumentStatusFilter, DocumentTypeResponse,
|
||||
MoveDocumentRequest, RestoreDocumentRequest, TagResponse, UpdateDocumentRequest,
|
||||
UploadDocumentForm,
|
||||
DocumentMetadataUpdate, DocumentResponse, DocumentStatusFilter, MoveDocumentRequest,
|
||||
RestoreDocumentRequest, TagResponse, UpdateDocumentRequest, UploadDocumentForm,
|
||||
};
|
||||
pub use crate::routes::folders::{
|
||||
CreateFolderRequest, EnsureFolderPathRequest, FolderContentsQuery, FolderContentsResponse,
|
||||
|
||||
@@ -1,187 +0,0 @@
|
||||
use axum::{
|
||||
extract::{Json, Path},
|
||||
http::StatusCode,
|
||||
};
|
||||
use diesel::prelude::*;
|
||||
use serde::Deserialize;
|
||||
use utoipa::ToSchema;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
auth::TenantScopedConn,
|
||||
error::{AppError, AppResult},
|
||||
models::{DocumentType, NewDocumentType},
|
||||
schema::document_types,
|
||||
utils::named_entity::normalize_name,
|
||||
};
|
||||
|
||||
use super::documents::DocumentTypeResponse;
|
||||
|
||||
#[derive(Deserialize, ToSchema)]
|
||||
pub struct CreateDocumentTypeRequest {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, ToSchema)]
|
||||
pub struct UpdateDocumentTypeRequest {
|
||||
pub name: Option<String>,
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/api/document-types",
|
||||
responses((status = 200, description = "Document types", body = [DocumentTypeResponse])),
|
||||
tag = "DocumentTypes"
|
||||
)]
|
||||
pub async fn list_document_types(
|
||||
TenantScopedConn {
|
||||
mut conn,
|
||||
tenant_id,
|
||||
..
|
||||
}: TenantScopedConn,
|
||||
) -> AppResult<Json<Vec<DocumentTypeResponse>>> {
|
||||
let types: Vec<DocumentType> = document_types::table
|
||||
.filter(document_types::tenant_id.eq(tenant_id))
|
||||
.order(document_types::name.asc())
|
||||
.load(&mut conn)?;
|
||||
|
||||
Ok(Json(
|
||||
types.into_iter().map(DocumentTypeResponse::from).collect(),
|
||||
))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/document-types",
|
||||
request_body = CreateDocumentTypeRequest,
|
||||
responses((status = 201, description = "Document type created", body = DocumentTypeResponse)),
|
||||
tag = "DocumentTypes"
|
||||
)]
|
||||
pub async fn create_document_type(
|
||||
TenantScopedConn {
|
||||
mut conn,
|
||||
tenant_id,
|
||||
..
|
||||
}: TenantScopedConn,
|
||||
Json(payload): Json<CreateDocumentTypeRequest>,
|
||||
) -> AppResult<(StatusCode, Json<DocumentTypeResponse>)> {
|
||||
let name = normalize_name(&payload.name, || {
|
||||
AppError::bad_request("name must not be empty")
|
||||
})?;
|
||||
|
||||
let new_type = NewDocumentType {
|
||||
id: Uuid::new_v4(),
|
||||
tenant_id,
|
||||
name: name.clone(),
|
||||
};
|
||||
|
||||
match diesel::insert_into(document_types::table)
|
||||
.values(&new_type)
|
||||
.get_result::<DocumentType>(&mut conn)
|
||||
{
|
||||
Ok(created) => Ok((
|
||||
StatusCode::CREATED,
|
||||
Json(DocumentTypeResponse::from(created)),
|
||||
)),
|
||||
Err(diesel::result::Error::DatabaseError(
|
||||
diesel::result::DatabaseErrorKind::UniqueViolation,
|
||||
_,
|
||||
)) => Err(
|
||||
AppError::conflict("a document type with that name already exists")
|
||||
.with_code("duplicate_document_type"),
|
||||
),
|
||||
Err(err) => Err(AppError::from(err)),
|
||||
}
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
patch,
|
||||
path = "/api/document-types/{id}",
|
||||
params(("id" = Uuid, Path, description = "Document type ID")),
|
||||
request_body = UpdateDocumentTypeRequest,
|
||||
responses((status = 200, description = "Document type updated", body = DocumentTypeResponse)),
|
||||
tag = "DocumentTypes"
|
||||
)]
|
||||
pub async fn update_document_type(
|
||||
Path(document_type_id): Path<Uuid>,
|
||||
TenantScopedConn {
|
||||
mut conn,
|
||||
tenant_id,
|
||||
..
|
||||
}: TenantScopedConn,
|
||||
Json(payload): Json<UpdateDocumentTypeRequest>,
|
||||
) -> AppResult<Json<DocumentTypeResponse>> {
|
||||
let name_raw = payload
|
||||
.name
|
||||
.as_ref()
|
||||
.ok_or_else(|| AppError::bad_request("name must be provided and not empty"))?;
|
||||
let name = normalize_name(name_raw, || {
|
||||
AppError::bad_request("name must be provided and not empty")
|
||||
})?;
|
||||
|
||||
let target = document_types::table
|
||||
.filter(document_types::tenant_id.eq(tenant_id))
|
||||
.find(document_type_id);
|
||||
|
||||
let update_result = diesel::update(target.clone())
|
||||
.set(document_types::name.eq(&name))
|
||||
.get_result::<DocumentType>(&mut conn);
|
||||
|
||||
match update_result {
|
||||
Ok(updated) => Ok(Json(DocumentTypeResponse::from(updated))),
|
||||
Err(diesel::result::Error::NotFound) => Err(AppError::not_found()),
|
||||
Err(diesel::result::Error::DatabaseError(
|
||||
diesel::result::DatabaseErrorKind::UniqueViolation,
|
||||
_,
|
||||
)) => Err(
|
||||
AppError::conflict("a document type with that name already exists")
|
||||
.with_code("duplicate_document_type"),
|
||||
),
|
||||
Err(err) => Err(AppError::from(err)),
|
||||
}
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
delete,
|
||||
path = "/api/document-types/{id}",
|
||||
params(("id" = Uuid, Path, description = "Document type ID")),
|
||||
responses((status = 204, description = "Document type deleted")),
|
||||
tag = "DocumentTypes"
|
||||
)]
|
||||
pub async fn delete_document_type(
|
||||
Path(document_type_id): Path<Uuid>,
|
||||
TenantScopedConn {
|
||||
mut conn,
|
||||
tenant_id,
|
||||
..
|
||||
}: TenantScopedConn,
|
||||
) -> AppResult<StatusCode> {
|
||||
let affected = diesel::delete(
|
||||
document_types::table
|
||||
.filter(document_types::tenant_id.eq(tenant_id))
|
||||
.find(document_type_id),
|
||||
)
|
||||
.execute(&mut conn)?;
|
||||
|
||||
if affected == 0 {
|
||||
return Err(AppError::not_found());
|
||||
}
|
||||
|
||||
Ok(StatusCode::NO_CONTENT)
|
||||
}
|
||||
|
||||
#[derive(utoipa::OpenApi)]
|
||||
#[openapi(
|
||||
paths(
|
||||
crate::routes::document_types::list_document_types,
|
||||
crate::routes::document_types::create_document_type,
|
||||
crate::routes::document_types::update_document_type,
|
||||
crate::routes::document_types::delete_document_type
|
||||
),
|
||||
components(schemas(
|
||||
crate::routes::document_types::CreateDocumentTypeRequest,
|
||||
crate::routes::document_types::UpdateDocumentTypeRequest,
|
||||
crate::routes::documents::DocumentTypeResponse
|
||||
))
|
||||
)]
|
||||
pub struct DocumentTypesApiDoc;
|
||||
@@ -37,13 +37,12 @@ use crate::documents::{
|
||||
use crate::error::{AppError, AppResult};
|
||||
use crate::jobs::{enqueue_job, JOB_ANALYZE_DOCUMENT, JOB_INDEX_DOCUMENT_TEXT};
|
||||
use crate::models::{
|
||||
Document, DocumentAsset, DocumentAssetObject, DocumentType, DocumentVersion, NewDocument,
|
||||
NewDocumentTag, NewDocumentVersion, Tag,
|
||||
Document, DocumentAsset, DocumentAssetObject, DocumentVersion, NewDocument, NewDocumentTag,
|
||||
NewDocumentVersion, Tag,
|
||||
};
|
||||
use crate::schema::{
|
||||
document_asset_objects, document_assets, document_correspondents, document_tags,
|
||||
document_types, document_versions, documents, folders, refresh_tokens::dsl as refresh_dsl,
|
||||
tags,
|
||||
document_versions, documents, folders, refresh_tokens::dsl as refresh_dsl, tags,
|
||||
};
|
||||
use crate::state::AppState;
|
||||
use crate::utils::{
|
||||
@@ -68,7 +67,6 @@ pub struct DocumentListQuery {
|
||||
pub query: Option<String>,
|
||||
pub tags: Option<String>,
|
||||
pub correspondents: Option<String>,
|
||||
pub document_types: Option<String>,
|
||||
#[serde(default = "default_document_status_filter")]
|
||||
#[schema(default = "active")]
|
||||
pub status: DocumentStatusFilter,
|
||||
@@ -141,21 +139,6 @@ impl From<Tag> for TagResponse {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct DocumentTypeResponse {
|
||||
pub id: Uuid,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
impl From<DocumentType> for DocumentTypeResponse {
|
||||
fn from(value: DocumentType) -> Self {
|
||||
Self {
|
||||
id: value.id,
|
||||
name: value.name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, ToSchema)]
|
||||
pub struct DocumentResponse {
|
||||
pub id: Uuid,
|
||||
@@ -174,12 +157,6 @@ pub struct DocumentResponse {
|
||||
pub issued_at: Option<String>,
|
||||
#[schema(value_type = Object)]
|
||||
pub metadata: Value,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[schema(nullable)]
|
||||
pub document_type_id: Option<Uuid>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[schema(nullable)]
|
||||
pub document_type: Option<DocumentTypeResponse>,
|
||||
pub tags: Vec<TagResponse>,
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub correspondents: Vec<DocumentCorrespondentResponse>,
|
||||
@@ -223,9 +200,6 @@ pub struct UpdateDocumentRequest {
|
||||
#[serde(default)]
|
||||
#[schema(nullable, value_type = Object)]
|
||||
pub metadata: Option<DocumentMetadataUpdate>,
|
||||
#[serde(default)]
|
||||
#[schema(nullable, value_type = Option<Uuid>)]
|
||||
pub document_type_id: Option<Uuid>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, ToSchema)]
|
||||
@@ -280,7 +254,6 @@ struct DocumentUpdateChangeset {
|
||||
issued_at: Option<Option<NaiveDateTime>>,
|
||||
metadata: Option<Value>,
|
||||
updated_at: Option<NaiveDateTime>,
|
||||
document_type_id: Option<Option<Uuid>>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Copy, Clone, PartialEq, Eq, ToSchema)]
|
||||
@@ -325,7 +298,6 @@ struct UploadRequest {
|
||||
correspondents: Vec<CorrespondentAssignmentInput>,
|
||||
issued_at_override: Option<NaiveDateTime>,
|
||||
skip_if_existing: bool,
|
||||
document_type_id: Option<Uuid>,
|
||||
}
|
||||
|
||||
enum UploadOutcome {
|
||||
@@ -402,7 +374,6 @@ pub async fn list_documents(
|
||||
query,
|
||||
tags,
|
||||
correspondents,
|
||||
document_types,
|
||||
status,
|
||||
} = params;
|
||||
|
||||
@@ -435,12 +406,6 @@ pub async fn list_documents(
|
||||
.map(|s| s.trim())
|
||||
.filter(|s| !s.is_empty())
|
||||
.map(|s| s.to_owned());
|
||||
let document_types_param = document_types
|
||||
.as_ref()
|
||||
.map(|s| s.trim())
|
||||
.filter(|s| !s.is_empty())
|
||||
.map(|s| s.to_owned());
|
||||
|
||||
let include_descendants = include_descendants.unwrap_or(true);
|
||||
|
||||
match (folder_id, include_descendants) {
|
||||
@@ -579,20 +544,6 @@ pub async fn list_documents(
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(document_types_param) = document_types_param.as_ref() {
|
||||
let type_ids: Result<Vec<Uuid>, _> = document_types_param
|
||||
.split(',')
|
||||
.map(|s| Uuid::parse_str(s.trim()))
|
||||
.collect();
|
||||
|
||||
if let Ok(ids) = type_ids {
|
||||
if !ids.is_empty() {
|
||||
let filter_values: Vec<Option<Uuid>> = ids.into_iter().map(Some).collect();
|
||||
docs_query = docs_query.filter(documents::document_type_id.eq_any(filter_values));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref set) = filter_ids {
|
||||
if set.is_empty() {
|
||||
return Ok(Json(vec![]));
|
||||
@@ -735,8 +686,6 @@ pub async fn get_document(
|
||||
.find(doc.current_version_id)
|
||||
.first(&mut conn)?;
|
||||
|
||||
let doc_type = load_document_type(&mut conn, tenant_id, doc.document_type_id)?;
|
||||
|
||||
let tags_map = load_tags_for_documents(&mut conn, &[document_id])?;
|
||||
let mut correspondents_map = load_correspondents_for_documents(&mut conn, &[document_id])?;
|
||||
let version_id = current_version.id;
|
||||
@@ -753,7 +702,6 @@ pub async fn get_document(
|
||||
tags_map.get(&document_id).cloned(),
|
||||
correspondents_map.remove(&document_id).unwrap_or_default(),
|
||||
Some((version_response, assets)),
|
||||
doc_type,
|
||||
)?,
|
||||
}))
|
||||
}
|
||||
@@ -786,7 +734,6 @@ pub async fn upload_document(
|
||||
let mut issued_at_override: Option<NaiveDateTime> = None;
|
||||
let mut skip_if_existing = false;
|
||||
let mut title_override: Option<String> = None;
|
||||
let mut document_type_id: Option<Uuid> = None;
|
||||
|
||||
while let Some(field) = multipart.next_field().await.map_err(|err| {
|
||||
let msg = format!("invalid multipart data: {err}");
|
||||
@@ -905,20 +852,6 @@ pub async fn upload_document(
|
||||
"1" | "true" | "yes"
|
||||
);
|
||||
}
|
||||
Some("document_type_id") => {
|
||||
let value = field.text().await.map_err(|err| {
|
||||
let msg = format!("invalid document_type_id: {err}");
|
||||
error!(error = %err, "invalid document_type payload");
|
||||
AppError::bad_request(msg)
|
||||
})?;
|
||||
let trimmed = value.trim();
|
||||
if !trimmed.is_empty() {
|
||||
let parsed = Uuid::parse_str(trimmed).map_err(|_| {
|
||||
AppError::bad_request("document_type_id must be a valid UUID")
|
||||
})?;
|
||||
document_type_id = Some(parsed);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -949,7 +882,6 @@ pub async fn upload_document(
|
||||
correspondents,
|
||||
issued_at_override,
|
||||
skip_if_existing,
|
||||
document_type_id,
|
||||
};
|
||||
|
||||
let outcome = match process_upload(&state, request, tenant_id, user_id).await {
|
||||
@@ -1482,46 +1414,6 @@ pub async fn update_document(
|
||||
}
|
||||
}
|
||||
|
||||
let doc_type_update =
|
||||
classify_nullable(payload_obj.get("document_type_id")).map_err(AppError::bad_request)?;
|
||||
|
||||
match doc_type_update {
|
||||
NullableValue::Omitted => {}
|
||||
NullableValue::Null => {
|
||||
if document.document_type_id.is_some() {
|
||||
changes.document_type_id = Some(None);
|
||||
has_changes = true;
|
||||
}
|
||||
}
|
||||
NullableValue::String(raw) => {
|
||||
let trimmed = raw.trim();
|
||||
if trimmed.is_empty() {
|
||||
return Err(AppError::bad_request(
|
||||
"document_type_id must not be empty when provided",
|
||||
));
|
||||
}
|
||||
let parsed = Uuid::parse_str(trimmed)
|
||||
.map_err(|_| AppError::bad_request("document_type_id must be a valid UUID"))?;
|
||||
|
||||
if document.document_type_id != Some(parsed) {
|
||||
let exists = document_types::table
|
||||
.filter(document_types::tenant_id.eq(tenant_id))
|
||||
.find(parsed)
|
||||
.first::<DocumentType>(&mut conn)
|
||||
.optional()?;
|
||||
|
||||
if exists.is_none() {
|
||||
return Err(AppError::bad_request(
|
||||
"document_type_id does not exist for this tenant",
|
||||
));
|
||||
}
|
||||
|
||||
changes.document_type_id = Some(Some(parsed));
|
||||
has_changes = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !has_changes {
|
||||
return Err(AppError::bad_request("no changes provided"));
|
||||
}
|
||||
@@ -1555,8 +1447,6 @@ pub async fn update_document(
|
||||
.find(document.current_version_id)
|
||||
.first(&mut conn)?;
|
||||
|
||||
let doc_type = load_document_type(&mut conn, tenant_id, document.document_type_id)?;
|
||||
|
||||
if title_changed {
|
||||
if let Err(err) = enqueue_job(
|
||||
&mut conn,
|
||||
@@ -1593,7 +1483,6 @@ pub async fn update_document(
|
||||
tags_map.get(&document_id).cloned(),
|
||||
correspondents_map.remove(&document_id).unwrap_or_default(),
|
||||
Some((version_response, assets)),
|
||||
doc_type,
|
||||
)?,
|
||||
}))
|
||||
}
|
||||
@@ -2195,23 +2084,8 @@ async fn process_upload(
|
||||
correspondents,
|
||||
issued_at_override,
|
||||
skip_if_existing,
|
||||
document_type_id,
|
||||
} = request;
|
||||
|
||||
if let Some(type_id) = document_type_id {
|
||||
let mut conn = state.db_for_tenant(tenant_id)?;
|
||||
let exists = document_types::table
|
||||
.filter(document_types::tenant_id.eq(tenant_id))
|
||||
.find(type_id)
|
||||
.first::<DocumentType>(&mut conn)
|
||||
.optional()?;
|
||||
if exists.is_none() {
|
||||
return Err(AppError::bad_request(
|
||||
"document_type_id does not exist for this tenant",
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(folder) = folder_id {
|
||||
let mut conn = state.db_for_tenant(tenant_id)?;
|
||||
ensure_folder_exists_on_conn(&mut conn, tenant_id, folder)?;
|
||||
@@ -2292,24 +2166,6 @@ async fn process_upload(
|
||||
)?;
|
||||
}
|
||||
|
||||
if let Some(type_id) = document_type_id {
|
||||
if document.document_type_id != Some(type_id) {
|
||||
let now = Utc::now().naive_utc();
|
||||
diesel::update(
|
||||
documents::table
|
||||
.find(document.id)
|
||||
.filter(documents::tenant_id.eq(tenant_id)),
|
||||
)
|
||||
.set((
|
||||
documents::document_type_id.eq(Some(type_id)),
|
||||
documents::updated_at.eq(now),
|
||||
))
|
||||
.execute(&mut conn)?;
|
||||
document.document_type_id = Some(type_id);
|
||||
document.updated_at = now;
|
||||
}
|
||||
}
|
||||
|
||||
if document.deleted_at.is_some() {
|
||||
let now = Utc::now().naive_utc();
|
||||
diesel::update(documents::table.find(document.id))
|
||||
@@ -2322,7 +2178,6 @@ async fn process_upload(
|
||||
document.updated_at = now;
|
||||
}
|
||||
|
||||
let doc_type = load_document_type(&mut conn, tenant_id, document.document_type_id)?;
|
||||
let tags_map = load_tags_for_documents(&mut conn, &[document.id])?;
|
||||
let mut correspondents_map =
|
||||
load_correspondents_for_documents(&mut conn, &[document.id])?;
|
||||
@@ -2346,7 +2201,6 @@ async fn process_upload(
|
||||
tags,
|
||||
correspondents,
|
||||
Some((version_response, assets)),
|
||||
doc_type,
|
||||
)?,
|
||||
}));
|
||||
}
|
||||
@@ -2386,7 +2240,6 @@ async fn process_upload(
|
||||
title: derived_title.clone(),
|
||||
metadata: metadata_value.clone(),
|
||||
tenant_id,
|
||||
document_type_id,
|
||||
};
|
||||
diesel::insert_into(documents::table)
|
||||
.values(&new_document)
|
||||
@@ -2445,7 +2298,6 @@ async fn process_upload(
|
||||
)?;
|
||||
}
|
||||
|
||||
let doc_type = load_document_type(&mut conn, tenant_id, document.document_type_id)?;
|
||||
let tags_map = load_tags_for_documents(&mut conn, &[doc_id])?;
|
||||
let mut correspondents_map = load_correspondents_for_documents(&mut conn, &[doc_id])?;
|
||||
let tags = tags_map.get(&doc_id).cloned();
|
||||
@@ -2460,7 +2312,6 @@ async fn process_upload(
|
||||
tags,
|
||||
correspondents,
|
||||
Some((to_version_response(version.clone()), Vec::new())),
|
||||
doc_type,
|
||||
)?,
|
||||
}
|
||||
};
|
||||
@@ -2493,7 +2344,6 @@ pub(crate) fn to_document_response(
|
||||
tags: Option<Vec<Tag>>,
|
||||
correspondents: Vec<DocumentCorrespondentResponse>,
|
||||
current_version: Option<(DocumentVersionResponse, Vec<DocumentAssetResponse>)>,
|
||||
doc_type: Option<DocumentType>,
|
||||
) -> AppResult<DocumentResponse> {
|
||||
let current_version = if let Some((version, assets)) = current_version {
|
||||
let download_path = build_download_path(state, &doc, user_id)?;
|
||||
@@ -2518,11 +2368,6 @@ pub(crate) fn to_document_response(
|
||||
deleted_at: doc.deleted_at.map(to_iso),
|
||||
issued_at: doc.issued_at.map(to_iso),
|
||||
metadata: doc.metadata,
|
||||
document_type_id: doc.document_type_id,
|
||||
document_type: doc_type.map(|typ| DocumentTypeResponse {
|
||||
id: typ.id,
|
||||
name: typ.name,
|
||||
}),
|
||||
tags: tags
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
@@ -2533,22 +2378,6 @@ pub(crate) fn to_document_response(
|
||||
})
|
||||
}
|
||||
|
||||
fn load_document_type(
|
||||
conn: &mut PgConnection,
|
||||
tenant_id: Uuid,
|
||||
type_id: Option<Uuid>,
|
||||
) -> diesel::QueryResult<Option<DocumentType>> {
|
||||
if let Some(id) = type_id {
|
||||
document_types::table
|
||||
.filter(document_types::tenant_id.eq(tenant_id))
|
||||
.find(id)
|
||||
.first::<DocumentType>(conn)
|
||||
.optional()
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn hydrate_documents(
|
||||
state: &AppState,
|
||||
conn: &mut PgConnection,
|
||||
@@ -2560,20 +2389,6 @@ pub(crate) fn hydrate_documents(
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
|
||||
let type_ids: HashSet<Uuid> = docs.iter().filter_map(|doc| doc.document_type_id).collect();
|
||||
let doc_type_map: HashMap<Uuid, DocumentType> = if type_ids.is_empty() {
|
||||
HashMap::new()
|
||||
} else {
|
||||
let ids: Vec<Uuid> = type_ids.iter().copied().collect();
|
||||
document_types::table
|
||||
.filter(document_types::tenant_id.eq(tenant_id))
|
||||
.filter(document_types::id.eq_any(&ids))
|
||||
.load::<DocumentType>(conn)?
|
||||
.into_iter()
|
||||
.map(|typ| (typ.id, typ))
|
||||
.collect()
|
||||
};
|
||||
|
||||
let doc_ids: Vec<Uuid> = docs.iter().map(|doc| doc.id).collect();
|
||||
let tags_map = load_tags_for_documents(conn, &doc_ids)?;
|
||||
let mut correspondents_map = load_correspondents_for_documents(conn, &doc_ids)?;
|
||||
@@ -2584,9 +2399,6 @@ pub(crate) fn hydrate_documents(
|
||||
let tags = tags_map.get(&doc.id).cloned();
|
||||
let correspondents = correspondents_map.remove(&doc.id).unwrap_or_default();
|
||||
let current_version = primary_versions.get(&doc.id).cloned();
|
||||
let doc_type = doc
|
||||
.document_type_id
|
||||
.and_then(|id| doc_type_map.get(&id).cloned());
|
||||
responses.push(to_document_response(
|
||||
state,
|
||||
user_id,
|
||||
@@ -2594,7 +2406,6 @@ pub(crate) fn hydrate_documents(
|
||||
tags,
|
||||
correspondents,
|
||||
current_version,
|
||||
doc_type,
|
||||
)?);
|
||||
}
|
||||
|
||||
@@ -2636,7 +2447,6 @@ pub(crate) fn hydrate_documents(
|
||||
crate::routes::documents::DocumentResponse,
|
||||
crate::routes::documents::DocumentDetailResponse,
|
||||
crate::routes::documents::DocumentMetadataUpdate,
|
||||
crate::routes::documents::DocumentTypeResponse,
|
||||
crate::routes::documents::TagResponse,
|
||||
crate::routes::documents::CorrespondentAssignmentInput,
|
||||
crate::routes::documents::AssignCorrespondentsRequest,
|
||||
|
||||
@@ -17,7 +17,6 @@ use crate::{auth::AuthenticatedUser, openapi::ApiDoc, state::AppState};
|
||||
|
||||
pub mod auth;
|
||||
pub mod correspondents;
|
||||
pub mod document_types;
|
||||
pub mod documents;
|
||||
pub mod folders;
|
||||
pub mod health;
|
||||
@@ -133,17 +132,6 @@ pub fn create_router(state: AppState) -> Router<()> {
|
||||
.route("/", get(tags::list_tags).post(tags::create_tag))
|
||||
.route("/:id", patch(tags::update_tag).delete(tags::delete_tag));
|
||||
|
||||
let document_types_routes = Router::new()
|
||||
.route(
|
||||
"/",
|
||||
get(document_types::list_document_types).post(document_types::create_document_type),
|
||||
)
|
||||
.route(
|
||||
"/:id",
|
||||
patch(document_types::update_document_type)
|
||||
.delete(document_types::delete_document_type),
|
||||
);
|
||||
|
||||
let correspondents_routes = Router::new()
|
||||
.route(
|
||||
"/",
|
||||
@@ -171,7 +159,6 @@ pub fn create_router(state: AppState) -> Router<()> {
|
||||
.nest("/api/documents", documents_routes)
|
||||
.nest("/api/folders", folders_routes)
|
||||
.nest("/api/tags", tags_routes)
|
||||
.nest("/api/document-types", document_types_routes)
|
||||
.nest("/api/correspondents", correspondents_routes)
|
||||
.nest("/api/profile", profile_routes)
|
||||
.nest("/api/assets", assets_routes)
|
||||
|
||||
@@ -62,15 +62,6 @@ diesel::table! {
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
document_types (id) {
|
||||
id -> Uuid,
|
||||
tenant_id -> Uuid,
|
||||
#[max_length = 100]
|
||||
name -> Varchar,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
document_versions (id) {
|
||||
id -> Uuid,
|
||||
@@ -106,7 +97,6 @@ diesel::table! {
|
||||
title -> Varchar,
|
||||
current_version_id -> Uuid,
|
||||
tenant_id -> Uuid,
|
||||
document_type_id -> Nullable<Uuid>,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,9 +250,7 @@ diesel::joinable!(document_tags -> documents (document_id));
|
||||
diesel::joinable!(document_tags -> tags (tag_id));
|
||||
diesel::joinable!(document_tags -> tenants (tenant_id));
|
||||
diesel::joinable!(document_tags -> users (assigned_by));
|
||||
diesel::joinable!(document_types -> tenants (tenant_id));
|
||||
diesel::joinable!(document_versions -> tenants (tenant_id));
|
||||
diesel::joinable!(documents -> document_types (document_type_id));
|
||||
diesel::joinable!(documents -> folders (folder_id));
|
||||
diesel::joinable!(documents -> tenants (tenant_id));
|
||||
diesel::joinable!(folders -> tenants (tenant_id));
|
||||
@@ -283,7 +271,6 @@ diesel::allow_tables_to_appear_in_same_query!(
|
||||
document_assets,
|
||||
document_correspondents,
|
||||
document_tags,
|
||||
document_types,
|
||||
document_versions,
|
||||
documents,
|
||||
folders,
|
||||
|
||||
Reference in New Issue
Block a user