实现业务附件受控入库 V1(05-28-business-attachment-governance-v1)
这个提交包含在:
@@ -1,4 +1,5 @@
|
||||
import { apiRequestBlob, apiRequestData, type ApiBlobResponse } from "./http";
|
||||
import { buildAttachmentFileUrl, type AttachmentGovernanceFields } from "../lib/attachmentGovernance";
|
||||
import type { RiskFlag } from "./feeControl";
|
||||
|
||||
export type PaymentBatchEntityType = "reimbursement" | "travel_order";
|
||||
@@ -64,6 +65,7 @@ export type PaymentBatchReceiptAttachment = {
|
||||
mimeType: string;
|
||||
fileSize: number;
|
||||
fileSha256: string;
|
||||
} & AttachmentGovernanceFields & {
|
||||
uploadedBy: {
|
||||
id: string;
|
||||
employeeNo: string;
|
||||
@@ -162,8 +164,9 @@ export function paymentBatchReceiptAttachmentFileUrl(batchId: string, attachment
|
||||
export async function downloadPaymentBatchReceiptAttachment(
|
||||
batchId: string,
|
||||
attachmentId: string,
|
||||
reason?: string,
|
||||
): Promise<ApiBlobResponse> {
|
||||
return apiRequestBlob(paymentBatchReceiptAttachmentFileUrl(batchId, attachmentId));
|
||||
return apiRequestBlob(buildAttachmentFileUrl(paymentBatchReceiptAttachmentFileUrl(batchId, attachmentId), reason));
|
||||
}
|
||||
|
||||
export async function deletePaymentBatchReceiptAttachment(batchId: string, attachmentId: string) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { apiRequestData } from "./http";
|
||||
import type { AttachmentGovernanceFields } from "../lib/attachmentGovernance";
|
||||
import type { PrecheckResponse, RiskFlag } from "./feeControl";
|
||||
|
||||
export type PurchaseRequestStatus = "draft" | "reviewing" | "approved" | "rejected" | "cancelled";
|
||||
@@ -89,6 +90,8 @@ export type PurchaseAttachment = {
|
||||
originalName: string;
|
||||
mimeType: string;
|
||||
fileSize: number;
|
||||
fileSha256: string | null;
|
||||
} & AttachmentGovernanceFields & {
|
||||
uploadedBy: string;
|
||||
createdAt: string | null;
|
||||
uploader: {
|
||||
@@ -383,12 +386,12 @@ export async function deletePurchaseAttachment(purchaseRequestId: string, attach
|
||||
);
|
||||
}
|
||||
|
||||
export async function issuePurchaseAttachmentSignedUrl(purchaseRequestId: string, attachmentId: string) {
|
||||
export async function issuePurchaseAttachmentSignedUrl(purchaseRequestId: string, attachmentId: string, reason?: string) {
|
||||
return apiRequestData<{ signedUrl: string; expiresAt: string }>(
|
||||
`/api/purchase-requests/${purchaseRequestId}/attachments/${attachmentId}/signed-url`,
|
||||
{
|
||||
method: "POST",
|
||||
body: JSON.stringify({}),
|
||||
body: JSON.stringify(reason ? { reason } : {}),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { apiRequestBlob, apiRequestData } from "./http";
|
||||
import type { ExpenseStandardCheck, PrecheckResponse, RiskFlag } from "./feeControl";
|
||||
import { buildAttachmentFileUrl, type AttachmentGovernanceFields } from "../lib/attachmentGovernance";
|
||||
|
||||
export type ReimbursementStatus =
|
||||
| "draft"
|
||||
@@ -182,6 +183,7 @@ export type ReimbursementDetail = {
|
||||
mimeType: string;
|
||||
fileSize: number;
|
||||
fileSha256: string;
|
||||
} & AttachmentGovernanceFields & {
|
||||
uploadedBy: {
|
||||
id: string;
|
||||
name: string;
|
||||
@@ -516,8 +518,8 @@ export function reimbursementAttachmentFileUrl(reimbursementId: string, attachme
|
||||
return `/api/reimbursements/${reimbursementId}/attachments/${attachmentId}/file`;
|
||||
}
|
||||
|
||||
export async function downloadReimbursementAttachment(reimbursementId: string, attachmentId: string) {
|
||||
return apiRequestBlob(reimbursementAttachmentFileUrl(reimbursementId, attachmentId));
|
||||
export async function downloadReimbursementAttachment(reimbursementId: string, attachmentId: string, reason?: string) {
|
||||
return apiRequestBlob(buildAttachmentFileUrl(reimbursementAttachmentFileUrl(reimbursementId, attachmentId), reason));
|
||||
}
|
||||
|
||||
|
||||
|
||||
在新工单中引用
屏蔽一个用户