e746b3c9a4
Closes Audit #3 P2 batch (knip dead exports/components, DemoSeeder hygiene, schema header drift). - Remove app/resources/js/views/admin/AdminPlaceholderView.vue (unreferenced placeholder view — confirmed via repo-wide grep, only doc references remain) - npm uninstall concurrently (no script invoked it; --legacy-peer-deps for Histoire 1.0-beta.1 peerDep quirk) - 12 unused exports → internal types (remove `export` keyword): - api/admin.ts: AdminTenantsStats, ApiTenantMetrics, ApiAdminBillingSummary, ApiAdminIncidentsSummary - api/notifications.ts: NotificationEvent - api/reports.ts: ApiReportType, ApiReportFormat, ApiReportParameters, ReportCounts, ReportQuota - composables/mockBilling.ts: TxType - composables/useStatusPill.ts: StatusPillSlug All 12 are used INSIDE their own file (response shapes), just not exported externally — converting to internal types satisfies knip without losing type-checking inside the file. - DatabaseSeeder::run() — DemoSeeder runs only in local+testing envs (`migrate:fresh --seed` in dev now produces demo tenant + admin@demo.local + 3 projects + ~14 demo deals; prod environments skip) - db/schema.sql header line 4: «62 базовые таблицы» → «63 базовые таблицы (61 regular + 2 partitioned parents: deals + supplier_lead_costs)» Closes schema header drift finding from Phase 3. Verification: - vue-tsc --noEmit: 0 errors - ESLint on touched files: 0 errors - Pest --parallel: 742/739/3sk/0 failed (identical to baseline, no regressions) - 2243 assertions / 34.46s Plan: docs/superpowers/plans/2026-05-14-audit3-deferred-fixes.md Task 2. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
117 lines
3.2 KiB
TypeScript
117 lines
3.2 KiB
TypeScript
import { apiClient, ensureCsrfCookie } from './client';
|
|
|
|
/**
|
|
* Reports API (schema §13.5 report_jobs).
|
|
*
|
|
* Все endpoint'ы под Sanctum SPA auth. Mutating-вызовы (POST/DELETE)
|
|
* делают ensureCsrfCookie().
|
|
*
|
|
* Backend status: pending|processing|done|failed (schema-канон).
|
|
* UI mock использует queued|running|done|failed — конверсия в reportsMapper.
|
|
*/
|
|
|
|
export type ApiReportStatus = 'pending' | 'processing' | 'done' | 'failed';
|
|
|
|
type ApiReportType = 'deals_export' | 'managers_summary' | 'sources_summary' | 'billing_summary';
|
|
|
|
type ApiReportFormat = 'csv' | 'xlsx' | 'json' | 'pdf';
|
|
|
|
interface ApiReportParameters {
|
|
format: ApiReportFormat;
|
|
date_from: string;
|
|
date_to: string;
|
|
project_id?: number | null;
|
|
manager_id?: number | null;
|
|
retry_count?: number;
|
|
retry_of?: number;
|
|
}
|
|
|
|
export interface ApiReportJob {
|
|
id: number;
|
|
type: ApiReportType;
|
|
parameters: ApiReportParameters;
|
|
status: ApiReportStatus;
|
|
file_path: string | null;
|
|
file_size: number | null;
|
|
generation_seconds: number | null;
|
|
error_message: string | null;
|
|
created_at: string | null;
|
|
finished_at: string | null;
|
|
expires_at: string | null;
|
|
is_expired: boolean;
|
|
retry_count: number;
|
|
retry_max: number;
|
|
}
|
|
|
|
interface ReportCounts {
|
|
pending: number;
|
|
processing: number;
|
|
done: number;
|
|
failed: number;
|
|
}
|
|
|
|
interface ReportQuota {
|
|
active: number;
|
|
max_active: number;
|
|
}
|
|
|
|
export interface ListReportJobsResponse {
|
|
jobs: ApiReportJob[];
|
|
total: number;
|
|
limit: number;
|
|
offset: number;
|
|
counts: ReportCounts;
|
|
quota: ReportQuota;
|
|
}
|
|
|
|
export interface ListReportJobsParams {
|
|
status?: ApiReportStatus;
|
|
limit?: number;
|
|
offset?: number;
|
|
}
|
|
|
|
export async function listReportJobs(params: ListReportJobsParams = {}): Promise<ListReportJobsResponse> {
|
|
const { data } = await apiClient.get<ListReportJobsResponse>('/api/reports/jobs', {
|
|
params: {
|
|
status: params.status,
|
|
limit: params.limit,
|
|
offset: params.offset,
|
|
},
|
|
});
|
|
return data;
|
|
}
|
|
|
|
export interface CreateReportJobPayload {
|
|
type: ApiReportType;
|
|
format: ApiReportFormat;
|
|
parameters: {
|
|
date_from: string;
|
|
date_to: string;
|
|
project_id?: number | null;
|
|
manager_id?: number | null;
|
|
};
|
|
}
|
|
|
|
export async function createReportJob(payload: CreateReportJobPayload): Promise<ApiReportJob> {
|
|
await ensureCsrfCookie();
|
|
const { data } = await apiClient.post<{ job: ApiReportJob }>('/api/reports/jobs', payload);
|
|
return data.job;
|
|
}
|
|
|
|
export async function retryReportJob(id: number): Promise<ApiReportJob> {
|
|
await ensureCsrfCookie();
|
|
const { data } = await apiClient.post<{ job: ApiReportJob }>(`/api/reports/jobs/${id}/retry`);
|
|
return data.job;
|
|
}
|
|
|
|
export async function cancelReportJob(id: number): Promise<ApiReportJob> {
|
|
await ensureCsrfCookie();
|
|
const { data } = await apiClient.post<{ job: ApiReportJob }>(`/api/reports/jobs/${id}/cancel`);
|
|
return data.job;
|
|
}
|
|
|
|
export async function deleteReportJob(id: number): Promise<void> {
|
|
await ensureCsrfCookie();
|
|
await apiClient.delete(`/api/reports/jobs/${id}`);
|
|
}
|