Add POS service
This commit is contained in:
337
frontend/src/api/hooks/usePOS.ts
Normal file
337
frontend/src/api/hooks/usePOS.ts
Normal file
@@ -0,0 +1,337 @@
|
||||
// frontend/src/api/hooks/usePOS.ts
|
||||
/**
|
||||
* React hooks for POS Integration functionality
|
||||
*/
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import {
|
||||
posService,
|
||||
POSConfiguration,
|
||||
CreatePOSConfigurationRequest,
|
||||
UpdatePOSConfigurationRequest,
|
||||
POSTransaction,
|
||||
POSSyncLog,
|
||||
POSAnalytics,
|
||||
SyncRequest
|
||||
} from '../services/pos.service';
|
||||
import { useTenantId } from './useTenant';
|
||||
|
||||
// ============================================================================
|
||||
// CONFIGURATION HOOKS
|
||||
// ============================================================================
|
||||
|
||||
export const usePOSConfigurations = (params?: {
|
||||
pos_system?: string;
|
||||
is_active?: boolean;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
}) => {
|
||||
const tenantId = useTenantId();
|
||||
|
||||
return useQuery({
|
||||
queryKey: ['pos-configurations', tenantId, params],
|
||||
queryFn: () => posService.getConfigurations(tenantId, params),
|
||||
enabled: !!tenantId,
|
||||
staleTime: 5 * 60 * 1000, // 5 minutes
|
||||
});
|
||||
};
|
||||
|
||||
export const usePOSConfiguration = (configId?: string) => {
|
||||
const tenantId = useTenantId();
|
||||
|
||||
return useQuery({
|
||||
queryKey: ['pos-configuration', tenantId, configId],
|
||||
queryFn: () => posService.getConfiguration(tenantId, configId!),
|
||||
enabled: !!tenantId && !!configId,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
});
|
||||
};
|
||||
|
||||
export const useCreatePOSConfiguration = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const tenantId = useTenantId();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: (data: CreatePOSConfigurationRequest) =>
|
||||
posService.createConfiguration(tenantId, data),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['pos-configurations', tenantId] });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useUpdatePOSConfiguration = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const tenantId = useTenantId();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: ({ configId, data }: { configId: string; data: UpdatePOSConfigurationRequest }) =>
|
||||
posService.updateConfiguration(tenantId, configId, data),
|
||||
onSuccess: (_, { configId }) => {
|
||||
queryClient.invalidateQueries({ queryKey: ['pos-configurations', tenantId] });
|
||||
queryClient.invalidateQueries({ queryKey: ['pos-configuration', tenantId, configId] });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useDeletePOSConfiguration = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const tenantId = useTenantId();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: (configId: string) =>
|
||||
posService.deleteConfiguration(tenantId, configId),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['pos-configurations', tenantId] });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useTestPOSConnection = () => {
|
||||
const tenantId = useTenantId();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: (configId: string) =>
|
||||
posService.testConnection(tenantId, configId),
|
||||
});
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// SYNCHRONIZATION HOOKS
|
||||
// ============================================================================
|
||||
|
||||
export const useTriggerPOSSync = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const tenantId = useTenantId();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: ({ configId, syncRequest }: { configId: string; syncRequest: SyncRequest }) =>
|
||||
posService.triggerSync(tenantId, configId, syncRequest),
|
||||
onSuccess: (_, { configId }) => {
|
||||
queryClient.invalidateQueries({ queryKey: ['pos-sync-status', tenantId, configId] });
|
||||
queryClient.invalidateQueries({ queryKey: ['pos-sync-logs', tenantId, configId] });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const usePOSSyncStatus = (configId?: string, pollingInterval?: number) => {
|
||||
const tenantId = useTenantId();
|
||||
|
||||
return useQuery({
|
||||
queryKey: ['pos-sync-status', tenantId, configId],
|
||||
queryFn: () => posService.getSyncStatus(tenantId, configId!),
|
||||
enabled: !!tenantId && !!configId,
|
||||
refetchInterval: pollingInterval || 30000, // Poll every 30 seconds by default
|
||||
staleTime: 10 * 1000, // 10 seconds
|
||||
});
|
||||
};
|
||||
|
||||
export const usePOSSyncLogs = (configId?: string, params?: {
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
status?: string;
|
||||
sync_type?: string;
|
||||
data_type?: string;
|
||||
}) => {
|
||||
const tenantId = useTenantId();
|
||||
|
||||
return useQuery({
|
||||
queryKey: ['pos-sync-logs', tenantId, configId, params],
|
||||
queryFn: () => posService.getSyncLogs(tenantId, configId!, params),
|
||||
enabled: !!tenantId && !!configId,
|
||||
staleTime: 2 * 60 * 1000, // 2 minutes
|
||||
});
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// TRANSACTION HOOKS
|
||||
// ============================================================================
|
||||
|
||||
export const usePOSTransactions = (params?: {
|
||||
pos_system?: string;
|
||||
start_date?: string;
|
||||
end_date?: string;
|
||||
status?: string;
|
||||
is_synced?: boolean;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
}) => {
|
||||
const tenantId = useTenantId();
|
||||
|
||||
return useQuery({
|
||||
queryKey: ['pos-transactions', tenantId, params],
|
||||
queryFn: () => posService.getTransactions(tenantId, params),
|
||||
enabled: !!tenantId,
|
||||
staleTime: 2 * 60 * 1000, // 2 minutes
|
||||
});
|
||||
};
|
||||
|
||||
export const useSyncSingleTransaction = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const tenantId = useTenantId();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: ({ transactionId, force }: { transactionId: string; force?: boolean }) =>
|
||||
posService.syncSingleTransaction(tenantId, transactionId, force),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['pos-transactions', tenantId] });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useResyncFailedTransactions = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const tenantId = useTenantId();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: (daysBack: number) =>
|
||||
posService.resyncFailedTransactions(tenantId, daysBack),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['pos-transactions', tenantId] });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// ANALYTICS HOOKS
|
||||
// ============================================================================
|
||||
|
||||
export const usePOSAnalytics = (days: number = 30) => {
|
||||
const tenantId = useTenantId();
|
||||
|
||||
return useQuery({
|
||||
queryKey: ['pos-analytics', tenantId, days],
|
||||
queryFn: () => posService.getSyncAnalytics(tenantId, days),
|
||||
enabled: !!tenantId,
|
||||
staleTime: 10 * 60 * 1000, // 10 minutes
|
||||
});
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// SYSTEM INFO HOOKS
|
||||
// ============================================================================
|
||||
|
||||
export const useSupportedPOSSystems = () => {
|
||||
return useQuery({
|
||||
queryKey: ['supported-pos-systems'],
|
||||
queryFn: () => posService.getSupportedSystems(),
|
||||
staleTime: 60 * 60 * 1000, // 1 hour
|
||||
});
|
||||
};
|
||||
|
||||
export const useWebhookStatus = (posSystem?: string) => {
|
||||
return useQuery({
|
||||
queryKey: ['webhook-status', posSystem],
|
||||
queryFn: () => posService.getWebhookStatus(posSystem!),
|
||||
enabled: !!posSystem,
|
||||
staleTime: 5 * 60 * 1000, // 5 minutes
|
||||
});
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// COMPOSITE HOOKS
|
||||
// ============================================================================
|
||||
|
||||
export const usePOSDashboard = () => {
|
||||
const tenantId = useTenantId();
|
||||
|
||||
// Get configurations
|
||||
const { data: configurationsData, isLoading: configurationsLoading } = usePOSConfigurations();
|
||||
|
||||
// Get recent transactions
|
||||
const { data: transactionsData, isLoading: transactionsLoading } = usePOSTransactions({
|
||||
limit: 10
|
||||
});
|
||||
|
||||
// Get analytics for last 7 days
|
||||
const { data: analyticsData, isLoading: analyticsLoading } = usePOSAnalytics(7);
|
||||
|
||||
const isLoading = configurationsLoading || transactionsLoading || analyticsLoading;
|
||||
|
||||
return {
|
||||
configurations: configurationsData?.configurations || [],
|
||||
transactions: transactionsData?.transactions || [],
|
||||
analytics: analyticsData,
|
||||
isLoading,
|
||||
summary: {
|
||||
total_configurations: configurationsData?.total || 0,
|
||||
active_configurations: configurationsData?.configurations?.filter(c => c.is_active).length || 0,
|
||||
connected_configurations: configurationsData?.configurations?.filter(c => c.is_connected).length || 0,
|
||||
total_transactions: transactionsData?.total || 0,
|
||||
total_revenue: transactionsData?.summary?.total_amount || 0,
|
||||
sync_health: analyticsData?.success_rate || 0,
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export const usePOSConfigurationManagement = () => {
|
||||
const createMutation = useCreatePOSConfiguration();
|
||||
const updateMutation = useUpdatePOSConfiguration();
|
||||
const deleteMutation = useDeletePOSConfiguration();
|
||||
const testConnectionMutation = useTestPOSConnection();
|
||||
|
||||
const [selectedConfiguration, setSelectedConfiguration] = useState<POSConfiguration | null>(null);
|
||||
const [isFormOpen, setIsFormOpen] = useState(false);
|
||||
|
||||
const handleCreate = async (data: CreatePOSConfigurationRequest) => {
|
||||
await createMutation.mutateAsync(data);
|
||||
setIsFormOpen(false);
|
||||
};
|
||||
|
||||
const handleUpdate = async (configId: string, data: UpdatePOSConfigurationRequest) => {
|
||||
await updateMutation.mutateAsync({ configId, data });
|
||||
setIsFormOpen(false);
|
||||
setSelectedConfiguration(null);
|
||||
};
|
||||
|
||||
const handleDelete = async (configId: string) => {
|
||||
await deleteMutation.mutateAsync(configId);
|
||||
};
|
||||
|
||||
const handleTestConnection = async (configId: string) => {
|
||||
return await testConnectionMutation.mutateAsync(configId);
|
||||
};
|
||||
|
||||
const openCreateForm = () => {
|
||||
setSelectedConfiguration(null);
|
||||
setIsFormOpen(true);
|
||||
};
|
||||
|
||||
const openEditForm = (configuration: POSConfiguration) => {
|
||||
setSelectedConfiguration(configuration);
|
||||
setIsFormOpen(true);
|
||||
};
|
||||
|
||||
const closeForm = () => {
|
||||
setIsFormOpen(false);
|
||||
setSelectedConfiguration(null);
|
||||
};
|
||||
|
||||
return {
|
||||
// State
|
||||
selectedConfiguration,
|
||||
isFormOpen,
|
||||
|
||||
// Actions
|
||||
handleCreate,
|
||||
handleUpdate,
|
||||
handleDelete,
|
||||
handleTestConnection,
|
||||
openCreateForm,
|
||||
openEditForm,
|
||||
closeForm,
|
||||
|
||||
// Loading states
|
||||
isCreating: createMutation.isPending,
|
||||
isUpdating: updateMutation.isPending,
|
||||
isDeleting: deleteMutation.isPending,
|
||||
isTesting: testConnectionMutation.isPending,
|
||||
|
||||
// Errors
|
||||
createError: createMutation.error,
|
||||
updateError: updateMutation.error,
|
||||
deleteError: deleteMutation.error,
|
||||
testError: testConnectionMutation.error,
|
||||
};
|
||||
};
|
||||
392
frontend/src/api/services/pos.service.ts
Normal file
392
frontend/src/api/services/pos.service.ts
Normal file
@@ -0,0 +1,392 @@
|
||||
// frontend/src/api/services/pos.service.ts
|
||||
/**
|
||||
* POS Integration API Service
|
||||
* Handles all communication with the POS service backend
|
||||
*/
|
||||
|
||||
import { apiClient } from '../client';
|
||||
|
||||
// ============================================================================
|
||||
// TYPES & INTERFACES
|
||||
// ============================================================================
|
||||
|
||||
export interface POSConfiguration {
|
||||
id: string;
|
||||
tenant_id: string;
|
||||
pos_system: 'square' | 'toast' | 'lightspeed';
|
||||
provider_name: string;
|
||||
is_active: boolean;
|
||||
is_connected: boolean;
|
||||
environment: 'sandbox' | 'production';
|
||||
location_id?: string;
|
||||
merchant_id?: string;
|
||||
sync_enabled: boolean;
|
||||
sync_interval_minutes: string;
|
||||
auto_sync_products: boolean;
|
||||
auto_sync_transactions: boolean;
|
||||
webhook_url?: string;
|
||||
last_sync_at?: string;
|
||||
last_successful_sync_at?: string;
|
||||
last_sync_status?: 'success' | 'failed' | 'partial';
|
||||
last_sync_message?: string;
|
||||
provider_settings?: Record<string, any>;
|
||||
last_health_check_at?: string;
|
||||
health_status: 'healthy' | 'unhealthy' | 'warning' | 'unknown';
|
||||
health_message?: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
created_by?: string;
|
||||
notes?: string;
|
||||
}
|
||||
|
||||
export interface CreatePOSConfigurationRequest {
|
||||
pos_system: 'square' | 'toast' | 'lightspeed';
|
||||
provider_name: string;
|
||||
environment: 'sandbox' | 'production';
|
||||
location_id?: string;
|
||||
merchant_id?: string;
|
||||
sync_enabled?: boolean;
|
||||
sync_interval_minutes?: string;
|
||||
auto_sync_products?: boolean;
|
||||
auto_sync_transactions?: boolean;
|
||||
notes?: string;
|
||||
// Credentials
|
||||
api_key?: string;
|
||||
api_secret?: string;
|
||||
access_token?: string;
|
||||
application_id?: string;
|
||||
webhook_secret?: string;
|
||||
}
|
||||
|
||||
export interface UpdatePOSConfigurationRequest {
|
||||
provider_name?: string;
|
||||
is_active?: boolean;
|
||||
environment?: 'sandbox' | 'production';
|
||||
location_id?: string;
|
||||
merchant_id?: string;
|
||||
sync_enabled?: boolean;
|
||||
sync_interval_minutes?: string;
|
||||
auto_sync_products?: boolean;
|
||||
auto_sync_transactions?: boolean;
|
||||
notes?: string;
|
||||
// Credentials (only if updating)
|
||||
api_key?: string;
|
||||
api_secret?: string;
|
||||
access_token?: string;
|
||||
application_id?: string;
|
||||
webhook_secret?: string;
|
||||
}
|
||||
|
||||
export interface POSTransaction {
|
||||
id: string;
|
||||
tenant_id: string;
|
||||
pos_config_id: string;
|
||||
pos_system: string;
|
||||
external_transaction_id: string;
|
||||
external_order_id?: string;
|
||||
transaction_type: 'sale' | 'refund' | 'void' | 'exchange';
|
||||
status: 'completed' | 'pending' | 'failed' | 'refunded' | 'voided';
|
||||
subtotal: number;
|
||||
tax_amount: number;
|
||||
tip_amount: number;
|
||||
discount_amount: number;
|
||||
total_amount: number;
|
||||
currency: string;
|
||||
payment_method?: string;
|
||||
payment_status?: string;
|
||||
transaction_date: string;
|
||||
pos_created_at: string;
|
||||
pos_updated_at?: string;
|
||||
location_id?: string;
|
||||
location_name?: string;
|
||||
staff_id?: string;
|
||||
staff_name?: string;
|
||||
customer_id?: string;
|
||||
customer_email?: string;
|
||||
customer_phone?: string;
|
||||
order_type?: string;
|
||||
table_number?: string;
|
||||
receipt_number?: string;
|
||||
is_synced_to_sales: boolean;
|
||||
sales_record_id?: string;
|
||||
sync_attempted_at?: string;
|
||||
sync_completed_at?: string;
|
||||
sync_error?: string;
|
||||
sync_retry_count: number;
|
||||
is_processed: boolean;
|
||||
processing_error?: string;
|
||||
is_duplicate: boolean;
|
||||
duplicate_of?: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
items: POSTransactionItem[];
|
||||
}
|
||||
|
||||
export interface POSTransactionItem {
|
||||
id: string;
|
||||
transaction_id: string;
|
||||
external_item_id?: string;
|
||||
sku?: string;
|
||||
product_name: string;
|
||||
product_category?: string;
|
||||
product_subcategory?: string;
|
||||
quantity: number;
|
||||
unit_price: number;
|
||||
total_price: number;
|
||||
discount_amount: number;
|
||||
tax_amount: number;
|
||||
modifiers?: Record<string, any>;
|
||||
inventory_product_id?: string;
|
||||
is_mapped_to_inventory: boolean;
|
||||
is_synced_to_sales: boolean;
|
||||
sync_error?: string;
|
||||
}
|
||||
|
||||
export interface POSSyncLog {
|
||||
id: string;
|
||||
tenant_id: string;
|
||||
pos_config_id: string;
|
||||
sync_type: 'full' | 'incremental' | 'manual' | 'webhook_triggered';
|
||||
sync_direction: 'inbound' | 'outbound' | 'bidirectional';
|
||||
data_type: 'transactions' | 'products' | 'customers' | 'orders';
|
||||
pos_system: string;
|
||||
status: 'started' | 'in_progress' | 'completed' | 'failed' | 'cancelled';
|
||||
started_at: string;
|
||||
completed_at?: string;
|
||||
duration_seconds?: number;
|
||||
sync_from_date?: string;
|
||||
sync_to_date?: string;
|
||||
records_requested: number;
|
||||
records_processed: number;
|
||||
records_created: number;
|
||||
records_updated: number;
|
||||
records_skipped: number;
|
||||
records_failed: number;
|
||||
api_calls_made: number;
|
||||
error_message?: string;
|
||||
error_code?: string;
|
||||
retry_attempt: number;
|
||||
max_retries: number;
|
||||
progress_percentage?: number;
|
||||
revenue_synced?: number;
|
||||
transactions_synced: number;
|
||||
triggered_by?: string;
|
||||
triggered_by_user_id?: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
export interface SyncRequest {
|
||||
sync_type?: 'full' | 'incremental';
|
||||
data_types?: ('transactions' | 'products' | 'customers')[];
|
||||
from_date?: string;
|
||||
to_date?: string;
|
||||
}
|
||||
|
||||
export interface SyncStatus {
|
||||
current_sync?: POSSyncLog;
|
||||
last_successful_sync?: POSSyncLog;
|
||||
recent_syncs: POSSyncLog[];
|
||||
sync_health: {
|
||||
status: 'healthy' | 'unhealthy' | 'warning';
|
||||
success_rate: number;
|
||||
average_duration_minutes: number;
|
||||
last_error?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface SupportedPOSSystem {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
features: string[];
|
||||
supported_regions: string[];
|
||||
}
|
||||
|
||||
export interface POSAnalytics {
|
||||
period_days: number;
|
||||
total_syncs: number;
|
||||
successful_syncs: number;
|
||||
failed_syncs: number;
|
||||
success_rate: number;
|
||||
average_duration_minutes: number;
|
||||
total_transactions_synced: number;
|
||||
total_revenue_synced: number;
|
||||
sync_frequency: {
|
||||
daily_average: number;
|
||||
peak_day?: string;
|
||||
peak_count: number;
|
||||
};
|
||||
error_analysis: {
|
||||
common_errors: Array<{ error: string; count: number }>;
|
||||
error_trends: Array<{ date: string; count: number }>;
|
||||
};
|
||||
}
|
||||
|
||||
export interface ConnectionTestResult {
|
||||
status: 'success' | 'error';
|
||||
message: string;
|
||||
tested_at: string;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// API FUNCTIONS
|
||||
// ============================================================================
|
||||
|
||||
export const posService = {
|
||||
// Configuration Management
|
||||
async getConfigurations(tenantId: string, params?: {
|
||||
pos_system?: string;
|
||||
is_active?: boolean;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
}): Promise<{ configurations: POSConfiguration[]; total: number }> {
|
||||
const response = await apiClient.get(`/pos-service/api/v1/tenants/${tenantId}/pos/configurations`, {
|
||||
params
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async createConfiguration(tenantId: string, data: CreatePOSConfigurationRequest): Promise<POSConfiguration> {
|
||||
const response = await apiClient.post(`/pos-service/api/v1/tenants/${tenantId}/pos/configurations`, data);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async getConfiguration(tenantId: string, configId: string): Promise<POSConfiguration> {
|
||||
const response = await apiClient.get(`/pos-service/api/v1/tenants/${tenantId}/pos/configurations/${configId}`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async updateConfiguration(tenantId: string, configId: string, data: UpdatePOSConfigurationRequest): Promise<POSConfiguration> {
|
||||
const response = await apiClient.put(`/pos-service/api/v1/tenants/${tenantId}/pos/configurations/${configId}`, data);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async deleteConfiguration(tenantId: string, configId: string): Promise<void> {
|
||||
await apiClient.delete(`/pos-service/api/v1/tenants/${tenantId}/pos/configurations/${configId}`);
|
||||
},
|
||||
|
||||
async testConnection(tenantId: string, configId: string): Promise<ConnectionTestResult> {
|
||||
const response = await apiClient.post(`/pos-service/api/v1/tenants/${tenantId}/pos/configurations/${configId}/test-connection`);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// Synchronization
|
||||
async triggerSync(tenantId: string, configId: string, syncRequest: SyncRequest): Promise<{
|
||||
message: string;
|
||||
sync_id: string;
|
||||
status: string;
|
||||
sync_type: string;
|
||||
data_types: string[];
|
||||
estimated_duration: string;
|
||||
}> {
|
||||
const response = await apiClient.post(`/pos-service/api/v1/tenants/${tenantId}/pos/configurations/${configId}/sync`, syncRequest);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async getSyncStatus(tenantId: string, configId: string, limit?: number): Promise<SyncStatus> {
|
||||
const response = await apiClient.get(`/pos-service/api/v1/tenants/${tenantId}/pos/configurations/${configId}/sync/status`, {
|
||||
params: { limit }
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async getSyncLogs(tenantId: string, configId: string, params?: {
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
status?: string;
|
||||
sync_type?: string;
|
||||
data_type?: string;
|
||||
}): Promise<{ logs: POSSyncLog[]; total: number; has_more: boolean }> {
|
||||
const response = await apiClient.get(`/pos-service/api/v1/tenants/${tenantId}/pos/configurations/${configId}/sync/logs`, {
|
||||
params
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// Transaction Management
|
||||
async getTransactions(tenantId: string, params?: {
|
||||
pos_system?: string;
|
||||
start_date?: string;
|
||||
end_date?: string;
|
||||
status?: string;
|
||||
is_synced?: boolean;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
}): Promise<{
|
||||
transactions: POSTransaction[];
|
||||
total: number;
|
||||
has_more: boolean;
|
||||
summary: {
|
||||
total_amount: number;
|
||||
transaction_count: number;
|
||||
sync_status: {
|
||||
synced: number;
|
||||
pending: number;
|
||||
failed: number;
|
||||
};
|
||||
};
|
||||
}> {
|
||||
const response = await apiClient.get(`/pos-service/api/v1/tenants/${tenantId}/pos/transactions`, {
|
||||
params
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async syncSingleTransaction(tenantId: string, transactionId: string, force?: boolean): Promise<{
|
||||
message: string;
|
||||
transaction_id: string;
|
||||
sync_status: string;
|
||||
sales_record_id?: string;
|
||||
}> {
|
||||
const response = await apiClient.post(`/pos-service/api/v1/tenants/${tenantId}/pos/transactions/${transactionId}/sync`,
|
||||
{}, { params: { force } }
|
||||
);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
async resyncFailedTransactions(tenantId: string, daysBack: number): Promise<{
|
||||
message: string;
|
||||
job_id: string;
|
||||
scope: string;
|
||||
estimated_transactions: number;
|
||||
}> {
|
||||
const response = await apiClient.post(`/pos-service/api/v1/tenants/${tenantId}/pos/data/resync`,
|
||||
{}, { params: { days_back: daysBack } }
|
||||
);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// Analytics
|
||||
async getSyncAnalytics(tenantId: string, days: number = 30): Promise<POSAnalytics> {
|
||||
const response = await apiClient.get(`/pos-service/api/v1/tenants/${tenantId}/pos/analytics/sync-performance`, {
|
||||
params: { days }
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// System Information
|
||||
async getSupportedSystems(): Promise<{ systems: SupportedPOSSystem[] }> {
|
||||
const response = await apiClient.get('/pos-service/api/v1/pos/supported-systems');
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// Webhook Status
|
||||
async getWebhookStatus(posSystem: string): Promise<{
|
||||
pos_system: string;
|
||||
status: string;
|
||||
endpoint: string;
|
||||
supported_events: {
|
||||
events: string[];
|
||||
format: string;
|
||||
authentication: string;
|
||||
};
|
||||
last_received?: string;
|
||||
total_received: number;
|
||||
}> {
|
||||
const response = await apiClient.get(`/pos-service/api/v1/webhooks/${posSystem}/status`);
|
||||
return response.data;
|
||||
}
|
||||
};
|
||||
|
||||
export default posService;
|
||||
Reference in New Issue
Block a user