- HERENCIA-SIMCO.md actualizado con directivas v3.7 y v3.8 - Cambios en backend y frontend Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
217 lines
7.6 KiB
TypeScript
217 lines
7.6 KiB
TypeScript
import axios, { AxiosError } from 'axios';
|
|
|
|
// Use proxy in development (vite will forward to backend)
|
|
// In production, use VITE_API_URL
|
|
const API_BASE = import.meta.env.VITE_API_URL || '';
|
|
const API_PREFIX = import.meta.env.VITE_API_PREFIX || '/api/v1';
|
|
|
|
export const api = axios.create({
|
|
baseURL: `${API_BASE}${API_PREFIX}`,
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
});
|
|
|
|
// Add auth interceptor - attach token to requests
|
|
api.interceptors.request.use((config) => {
|
|
const token = localStorage.getItem('accessToken');
|
|
if (token) {
|
|
config.headers.Authorization = `Bearer ${token}`;
|
|
}
|
|
return config;
|
|
});
|
|
|
|
// Response interceptor - handle 401 errors
|
|
api.interceptors.response.use(
|
|
(response) => response,
|
|
async (error: AxiosError) => {
|
|
if (error.response?.status === 401) {
|
|
// Try refresh token
|
|
const refreshToken = localStorage.getItem('refreshToken');
|
|
if (refreshToken) {
|
|
try {
|
|
const response = await axios.post(`${API_BASE}${API_PREFIX}/auth/refresh`, {
|
|
refreshToken,
|
|
});
|
|
const { accessToken, refreshToken: newRefresh } = response.data;
|
|
localStorage.setItem('accessToken', accessToken);
|
|
localStorage.setItem('refreshToken', newRefresh);
|
|
|
|
// Retry original request
|
|
if (error.config) {
|
|
error.config.headers.Authorization = `Bearer ${accessToken}`;
|
|
return axios(error.config);
|
|
}
|
|
} catch {
|
|
// Refresh failed, clear tokens and redirect to login
|
|
localStorage.removeItem('accessToken');
|
|
localStorage.removeItem('refreshToken');
|
|
localStorage.removeItem('user');
|
|
localStorage.removeItem('tenant');
|
|
window.location.href = '/login';
|
|
}
|
|
} else {
|
|
// No refresh token, redirect to login
|
|
localStorage.removeItem('accessToken');
|
|
localStorage.removeItem('user');
|
|
localStorage.removeItem('tenant');
|
|
window.location.href = '/login';
|
|
}
|
|
}
|
|
return Promise.reject(error);
|
|
}
|
|
);
|
|
|
|
// Auth API
|
|
export const authApi = {
|
|
register: (data: {
|
|
name: string;
|
|
ownerName: string;
|
|
businessType: string;
|
|
phone: string;
|
|
pin: string;
|
|
email?: string;
|
|
whatsapp?: string;
|
|
}) => api.post('/auth/register', data),
|
|
|
|
login: (data: { phone: string; pin: string }) =>
|
|
api.post('/auth/login', data),
|
|
|
|
refresh: (refreshToken: string) =>
|
|
api.post('/auth/refresh', { refreshToken }),
|
|
|
|
changePin: (data: { currentPin: string; newPin: string }) =>
|
|
api.post('/auth/change-pin', data),
|
|
};
|
|
|
|
// Products API
|
|
export const productsApi = {
|
|
getAll: (params?: { category?: string; search?: string }) =>
|
|
api.get('/products', { params }),
|
|
getById: (id: string) => api.get(`/products/${id}`),
|
|
create: (data: any) => api.post('/products', data),
|
|
update: (id: string, data: any) => api.patch(`/products/${id}`, data),
|
|
delete: (id: string) => api.delete(`/products/${id}`),
|
|
};
|
|
|
|
// Orders API
|
|
export const ordersApi = {
|
|
getAll: (params?: { status?: string; date?: string }) =>
|
|
api.get('/orders', { params }),
|
|
getById: (id: string) => api.get(`/orders/${id}`),
|
|
create: (data: any) => api.post('/orders', data),
|
|
updateStatus: (id: string, status: string) =>
|
|
api.patch(`/orders/${id}/status`, { status }),
|
|
};
|
|
|
|
// Customers API
|
|
export const customersApi = {
|
|
getAll: (params?: { search?: string }) =>
|
|
api.get('/customers', { params }),
|
|
getById: (id: string) => api.get(`/customers/${id}`),
|
|
create: (data: any) => api.post('/customers', data),
|
|
update: (id: string, data: any) => api.patch(`/customers/${id}`, data),
|
|
getFiado: (id: string) => api.get(`/customers/${id}/fiado`),
|
|
};
|
|
|
|
// Inventory API
|
|
export const inventoryApi = {
|
|
getMovements: (params?: { productId?: string; type?: string }) =>
|
|
api.get('/inventory/movements', { params }),
|
|
createMovement: (data: any) => api.post('/inventory/movements', data),
|
|
getLowStock: () => api.get('/inventory/low-stock'),
|
|
getAlerts: () => api.get('/inventory/alerts'),
|
|
};
|
|
|
|
// Dashboard API
|
|
export const dashboardApi = {
|
|
getStats: () => api.get('/dashboard/stats'),
|
|
getSalesChart: (period: string) => api.get('/dashboard/sales', { params: { period } }),
|
|
getTopProducts: () => api.get('/dashboard/top-products'),
|
|
};
|
|
|
|
// Referrals API
|
|
export const referralsApi = {
|
|
getMyCode: () => api.get('/referrals/my-code'),
|
|
generateCode: () => api.post('/referrals/generate-code'),
|
|
validateCode: (code: string) => api.get(`/referrals/validate/${code}`),
|
|
applyCode: (code: string) => api.post('/referrals/apply-code', { code }),
|
|
getMyReferrals: () => api.get('/referrals/list'),
|
|
getStats: () => api.get('/referrals/stats'),
|
|
getRewards: () => api.get('/referrals/rewards'),
|
|
getAvailableMonths: () => api.get('/referrals/rewards/available-months'),
|
|
getDiscount: () => api.get('/referrals/discount'),
|
|
};
|
|
|
|
// CoDi/SPEI API
|
|
export const codiSpeiApi = {
|
|
// CoDi
|
|
generateQr: (data: { amount: number; description?: string; saleId?: string }) =>
|
|
api.post('/codi/generate-qr', data),
|
|
getCodiStatus: (id: string) => api.get(`/codi/status/${id}`),
|
|
getCodiTransactions: (limit?: number) =>
|
|
api.get('/codi/transactions', { params: { limit } }),
|
|
|
|
// SPEI
|
|
getClabe: () => api.get('/spei/clabe'),
|
|
createClabe: (beneficiaryName: string) =>
|
|
api.post('/spei/create-clabe', { beneficiaryName }),
|
|
getSpeiTransactions: (limit?: number) =>
|
|
api.get('/spei/transactions', { params: { limit } }),
|
|
|
|
// Summary
|
|
getSummary: (date?: string) =>
|
|
api.get('/payments/summary', { params: { date } }),
|
|
};
|
|
|
|
// Invoices API (SAT/CFDI)
|
|
export const invoicesApi = {
|
|
// Tax Config
|
|
getTaxConfig: () => api.get('/invoices/tax-config'),
|
|
saveTaxConfig: (data: any) => api.post('/invoices/tax-config', data),
|
|
|
|
// Invoices
|
|
getAll: (params?: { status?: string; from?: string; to?: string; limit?: number }) =>
|
|
api.get('/invoices', { params }),
|
|
getById: (id: string) => api.get(`/invoices/${id}`),
|
|
create: (data: any) => api.post('/invoices', data),
|
|
stamp: (id: string) => api.post(`/invoices/${id}/stamp`),
|
|
cancel: (id: string, reason: string, uuidReplacement?: string) =>
|
|
api.post(`/invoices/${id}/cancel`, { reason, uuidReplacement }),
|
|
send: (id: string, email?: string) =>
|
|
api.post(`/invoices/${id}/send`, { email }),
|
|
getSummary: (month?: string) =>
|
|
api.get('/invoices/summary', { params: { month } }),
|
|
};
|
|
|
|
// Marketplace API
|
|
export const marketplaceApi = {
|
|
// Suppliers
|
|
getSuppliers: (params?: { category?: string; zipCode?: string; search?: string; limit?: number }) =>
|
|
api.get('/marketplace/suppliers', { params }),
|
|
getSupplier: (id: string) => api.get(`/marketplace/suppliers/${id}`),
|
|
getSupplierProducts: (id: string, params?: { category?: string; search?: string }) =>
|
|
api.get(`/marketplace/suppliers/${id}/products`, { params }),
|
|
getSupplierReviews: (id: string, params?: { limit?: number }) =>
|
|
api.get(`/marketplace/suppliers/${id}/reviews`, { params }),
|
|
|
|
// Orders
|
|
createOrder: (data: any) => api.post('/marketplace/orders', data),
|
|
getOrders: (params?: { status?: string; supplierId?: string; limit?: number }) =>
|
|
api.get('/marketplace/orders', { params }),
|
|
getOrder: (id: string) => api.get(`/marketplace/orders/${id}`),
|
|
cancelOrder: (id: string, reason: string) =>
|
|
api.put(`/marketplace/orders/${id}/cancel`, { reason }),
|
|
|
|
// Reviews
|
|
createReview: (data: any) => api.post('/marketplace/reviews', data),
|
|
|
|
// Favorites
|
|
getFavorites: () => api.get('/marketplace/favorites'),
|
|
addFavorite: (supplierId: string) => api.post(`/marketplace/favorites/${supplierId}`),
|
|
removeFavorite: (supplierId: string) => api.delete(`/marketplace/favorites/${supplierId}`),
|
|
|
|
// Stats
|
|
getStats: () => api.get('/marketplace/stats'),
|
|
};
|