feature/api-cove-integration
This commit is contained in:
53
frontend/src/lib/api/dashboard/a76/audit_files.ts
Normal file
53
frontend/src/lib/api/dashboard/a76/audit_files.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { api } from '$lib/api';
|
||||
|
||||
const BASE_PATH = '/v1/a76/audit-log/files';
|
||||
|
||||
export interface AuditFileBreadcrumb {
|
||||
path: string;
|
||||
display_name: string;
|
||||
}
|
||||
|
||||
export interface AuditFolderItem {
|
||||
path: string;
|
||||
display_name: string;
|
||||
}
|
||||
|
||||
export interface AuditFileItem {
|
||||
path: string;
|
||||
display_name: string;
|
||||
size: number;
|
||||
last_modified?: string | null;
|
||||
}
|
||||
|
||||
export interface AuditFileListResponse {
|
||||
current_path: string;
|
||||
display_path: string;
|
||||
breadcrumbs: AuditFileBreadcrumb[];
|
||||
folders: AuditFolderItem[];
|
||||
files: AuditFileItem[];
|
||||
next_token?: string | null;
|
||||
}
|
||||
|
||||
export const AuditFilesAPI = {
|
||||
list: async (params?: {
|
||||
path?: string;
|
||||
continuation_token?: string;
|
||||
max_keys?: number;
|
||||
}): Promise<AuditFileListResponse> => {
|
||||
const query = new URLSearchParams();
|
||||
if (params?.path) query.set('path', params.path);
|
||||
if (params?.continuation_token) query.set('continuation_token', params.continuation_token);
|
||||
if (params?.max_keys) query.set('max_keys', String(params.max_keys));
|
||||
|
||||
const qs = query.toString();
|
||||
const endpoint = qs ? `${BASE_PATH}?${qs}` : BASE_PATH;
|
||||
const response = await api.get<AuditFileListResponse>(endpoint);
|
||||
if (response.error || !response.data) {
|
||||
throw new Error(response.error || 'Failed to list tenant files');
|
||||
}
|
||||
return response.data;
|
||||
},
|
||||
|
||||
downloadBlob: (path: string) =>
|
||||
api.getBlob(`${BASE_PATH}/download?path=${encodeURIComponent(path)}`)
|
||||
};
|
||||
@@ -1,6 +1,24 @@
|
||||
import { api } from '$lib/api';
|
||||
import { companyStore } from '$lib/stores/company.svelte'; // <--- NUEVO: Importamos el store para el fallback
|
||||
import type { ApiResponse } from '$lib/api';
|
||||
import { getToken } from '$lib/auth';
|
||||
|
||||
export type VuUploadFileKind =
|
||||
| 'certificate'
|
||||
| 'key'
|
||||
| 'cove'
|
||||
| 'doda_certificate'
|
||||
| 'doda_key'
|
||||
| 'doda_cove';
|
||||
|
||||
export interface CustomsBrokerVuUploadResult {
|
||||
message: string;
|
||||
file_kind: string;
|
||||
field: string;
|
||||
path: string;
|
||||
broker_key: string;
|
||||
company_id: number;
|
||||
}
|
||||
|
||||
export interface CustomsBroker {
|
||||
id: number;
|
||||
@@ -165,4 +183,40 @@ export const customsBrokersApi = {
|
||||
data
|
||||
);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Sube CER, KEY o COVE del VU al bucket (MinIO: tenants/.../customs_brokers/...).
|
||||
*/
|
||||
export async function uploadCustomsBrokerVuFile(
|
||||
brokerKey: string,
|
||||
companyId: string,
|
||||
fileKind: VuUploadFileKind,
|
||||
file: File
|
||||
): Promise<ApiResponse<CustomsBrokerVuUploadResult>> {
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
const token = getToken();
|
||||
const API_BASE_URL = (import.meta.env.VITE_API_URL || '').replace(/\/+$/, '');
|
||||
const q = new URLSearchParams({
|
||||
company_id: companyId,
|
||||
file_kind: fileKind
|
||||
});
|
||||
const response = await fetch(
|
||||
`${API_BASE_URL}/v1/a76/customs-brokers/${encodeURIComponent(brokerKey)}/vu/upload?${q.toString()}`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: token ? { Authorization: `Bearer ${token}` } : {},
|
||||
body: formData,
|
||||
credentials: 'include'
|
||||
}
|
||||
);
|
||||
const data = await response.json().catch(() => ({}));
|
||||
if (!response.ok) {
|
||||
return {
|
||||
error: (data as { detail?: string }).detail || (data as { message?: string }).message || 'Error al subir el archivo VU',
|
||||
status: response.status
|
||||
};
|
||||
}
|
||||
return { data: data as CustomsBrokerVuUploadResult, status: response.status };
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { api } from '$lib/api';
|
||||
import type { ApiResponse } from '$lib/api';
|
||||
import { getToken } from '$lib/auth';
|
||||
|
||||
export interface CompanyAddress {
|
||||
id?: number;
|
||||
@@ -450,14 +451,12 @@ export async function uploadCompanyLogo(id: number, file: File): Promise<ApiResp
|
||||
|
||||
// Para FormData, usamos fetch directamente ya que necesitamos omitir Content-Type
|
||||
// para que el navegador establezca el boundary automáticamente
|
||||
const token = localStorage.getItem('access_token');
|
||||
const token = getToken();
|
||||
const API_BASE_URL = (import.meta.env.VITE_API_URL || '').replace(/\/+$/, '');
|
||||
|
||||
const response = await fetch(`${API_BASE_URL}/v1/a76/company/${id}/upload-logo`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
},
|
||||
headers: token ? { Authorization: `Bearer ${token}` } : {},
|
||||
body: formData,
|
||||
credentials: 'include'
|
||||
});
|
||||
@@ -484,14 +483,12 @@ export async function uploadCompanyCertificate(id: number, type: string, file: F
|
||||
formData.append('password', password);
|
||||
}
|
||||
|
||||
const token = localStorage.getItem('access_token');
|
||||
const token = getToken();
|
||||
const API_BASE_URL = (import.meta.env.VITE_API_URL || '').replace(/\/+$/, '');
|
||||
|
||||
const response = await fetch(`${API_BASE_URL}/v1/a76/company/${id}/upload-certificate?certificate_type=${type}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`,
|
||||
},
|
||||
headers: token ? { Authorization: `Bearer ${token}` } : {},
|
||||
body: formData,
|
||||
credentials: 'include'
|
||||
});
|
||||
|
||||
@@ -543,5 +543,42 @@ export const invoicesApi = {
|
||||
sql_errors?: Array<{ consecutive: number; error: string }>;
|
||||
};
|
||||
}>(`/v1/a76/invoices/revert/${taskId}/status`);
|
||||
},
|
||||
|
||||
generateCove: (invoiceId: number, companyId: number) => {
|
||||
const params = new URLSearchParams({
|
||||
company_id: companyId.toString()
|
||||
});
|
||||
return api.post<{ task_id: string }>(
|
||||
`/v1/a76/factura-cove/invoices/${invoiceId}/cove?${params.toString()}`,
|
||||
{
|
||||
company_id: companyId
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
getCoveStatus: (taskId: string) => {
|
||||
return api.get<{
|
||||
state: 'PROCESSING' | 'SUCCESS' | 'FAILURE';
|
||||
info?: { current: number; status: string };
|
||||
result?: {
|
||||
status: 'success' | 'validation_error' | 'error';
|
||||
invoice_id?: number;
|
||||
cove_number?: string;
|
||||
vucem_operation_num?: string;
|
||||
message?: string;
|
||||
errors?: Array<{ field: string; message: string; code?: string; solution?: string[] }>;
|
||||
};
|
||||
}>(`/v1/a76/factura-cove/invoices/cove/${taskId}/status`);
|
||||
},
|
||||
|
||||
checkCoveEligibility: (invoiceId: number, companyId: number) => {
|
||||
const params = new URLSearchParams({
|
||||
company_id: companyId.toString()
|
||||
});
|
||||
return api.get<{
|
||||
can_generate: boolean;
|
||||
reasons: Array<{ field: string; message: string }>;
|
||||
}>(`/v1/a76/factura-cove/invoices/${invoiceId}/cove/eligibility?${params.toString()}`);
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user