diff --git a/src/components/layout/Sidebar.vue b/src/components/layout/Sidebar.vue index 8772744..0d8a2fc 100644 --- a/src/components/layout/Sidebar.vue +++ b/src/components/layout/Sidebar.vue @@ -25,7 +25,8 @@ const menuItems = ref([ { label: 'Unidades de Medida', icon: 'pi pi-calculator', to: '/catalog/units-of-measure' }, { label: 'Clasificaciones Comerciales', icon: 'pi pi-tags', to: '/catalog/classifications-comercial' }, { label: 'Proveedores', icon: 'pi pi-briefcase', to: '/catalog/suppliers' }, - { label: 'Documentos del Modelo', icon: 'pi pi-file', to: '/catalog/model-documents' } + { label: 'Documentos del Modelo', icon: 'pi pi-file', to: '/catalog/model-documents' }, + { label: 'Empresas', icon: 'pi pi-building', to: '/catalog/companies' } ] }, { diff --git a/src/modules/catalog/components/companies/Companies.vue b/src/modules/catalog/components/companies/Companies.vue new file mode 100644 index 0000000..3a0c152 --- /dev/null +++ b/src/modules/catalog/components/companies/Companies.vue @@ -0,0 +1,344 @@ + + + + + \ No newline at end of file diff --git a/src/modules/catalog/components/companies/CompaniesForm.vue b/src/modules/catalog/components/companies/CompaniesForm.vue new file mode 100644 index 0000000..8cf067a --- /dev/null +++ b/src/modules/catalog/components/companies/CompaniesForm.vue @@ -0,0 +1,429 @@ + + + + + \ No newline at end of file diff --git a/src/modules/catalog/components/companies/companies.router.ts b/src/modules/catalog/components/companies/companies.router.ts new file mode 100644 index 0000000..61c6d2a --- /dev/null +++ b/src/modules/catalog/components/companies/companies.router.ts @@ -0,0 +1,14 @@ +import type { RouteRecordRaw } from "vue-router"; +import Companies from "./Companies.vue"; + +const companiesRouter : RouteRecordRaw = { + path: 'companies', + name: 'companies', + component: Companies, + meta: { + title: 'Empresas', + requiresAuth: true + }, +} + +export default companiesRouter; \ No newline at end of file diff --git a/src/modules/catalog/components/companies/companies.service.ts b/src/modules/catalog/components/companies/companies.service.ts new file mode 100644 index 0000000..5b81e6d --- /dev/null +++ b/src/modules/catalog/components/companies/companies.service.ts @@ -0,0 +1,123 @@ +import api from '@/services/api'; +import type { + Company, + CompanyCreateResponse, + CompanyFormData, + CompanyQueryParams, + PaginatedResponse +} from './companies.types'; + + +export class CompanyService { + + /** + * Obtener todas las empresas con paginación y filtros opcionales + */ + async getAll(params?: CompanyQueryParams): Promise | Company[]> { + try { + const response = await api.get('api/catalogs/companies', { params }); + + // Si la respuesta tiene paginación, devolver el objeto completo + if (response.data.current_page !== undefined) { + return response.data as PaginatedResponse; + } + + // Si no tiene paginación, devolver solo el array de data + return response.data.data as Company[]; + } catch (error: any) { + console.error('Error al obtener empresas:', error); + throw error; + } + } + + /** + * Obtener una empresa por ID + */ + async getById(id: number): Promise { + try { + const response = await api.get(`api/catalogs/companies/${id}`); + return response.data; + } catch (error: any) { + console.error(`Error al obtener empresa con ID ${id}:`, error); + throw error; + } + } + + /** + * Crear una nueva empresa + */ + async create(data: CompanyFormData): Promise { + try { + const response = await api.post('api/catalogs/companies', data); + return response.data; + } catch (error: any) { + console.error('Error al crear empresa:', error); + // Mejorar el mensaje de error si viene del backend + if (error.response?.data) { + throw { + ...error, + message: error.response.data.message || error.response.data.error || 'Error al crear la empresa' + }; + } + throw error; + } + } + + /** + * Actualizar una empresa existente + */ + async update(id: number, data: Partial): Promise { + try { + const response = await api.put(`api/catalogs/companies/${id}`, data); + return response.data; + } catch (error: any) { + console.error(`Error al actualizar empresa con ID ${id}:`, error); + // Mejorar el mensaje de error si viene del backend + if (error.response?.data) { + throw { + ...error, + message: error.response.data.message || error.response.data.error || 'Error al actualizar la empresa' + }; + } + throw error; + } + } + + /** + * Eliminar una empresa + */ + async delete(id: number): Promise { + try { + await api.delete(`api/catalogs/companies/${id}`); + } catch (error: any) { + console.error(`Error al eliminar empresa con ID ${id}:`, error); + // Mejorar el mensaje de error si viene del backend + if (error.response?.data) { + throw { + ...error, + message: error.response.data.message || error.response.data.error || 'Error al eliminar la empresa' + }; + } + throw error; + } + } + + /** + * Buscar empresas por múltiples criterios + */ + async search(params: CompanyQueryParams): Promise { + try { + const response = await api.get('api/catalogs/companies', { + params: { ...params, paginate: false } + }); + return response.data.data; + } catch (error: any) { + console.error('Error al buscar empresas:', error); + throw error; + } + } + +}; + +// Exportar una instancia única del servicio +export const companyService = new CompanyService(); diff --git a/src/modules/catalog/components/companies/companies.types.ts b/src/modules/catalog/components/companies/companies.types.ts new file mode 100644 index 0000000..3351a50 --- /dev/null +++ b/src/modules/catalog/components/companies/companies.types.ts @@ -0,0 +1,72 @@ +export interface CompanyAddress { + country: string; + postal_code: string; + state: string; + municipality: string; + city: string; + street: string; + num_ext: string; + num_int?: string; +} + +export interface Company { + id?: number; + rfc: string; + curp?: string; + company_name: string; + vat_rate: number; + isr_withholding: number; + vat_withholding: number; + additional_tax: number; + address: CompanyAddress; + created_at?: string; + updated_at?: string; +} + +export interface CompanyCreateResponse{ + data: Company; +} + +export interface CompanyFormData extends Omit {} + +export interface CompanyStats { + total: number; + active: number; + pending: number; + monthlyIncrease: number; + activePercentage: number; +} + +export interface PaginationLink { + url: string | null; + label: string; + active: boolean; +} + +export interface PaginatedResponse { + current_page: number; + data: T[]; + first_page_url: string; + from: number; + last_page: number; + last_page_url: string; + links: PaginationLink[]; + next_page_url: string | null; + path: string; + per_page: number; + prev_page_url: string | null; + to: number; + total: number; +} + +export interface CompanyListResponse { + data: Company[]; +} + +export interface CompanyQueryParams { + paginate?: boolean; + rfc?: string; + curp?: string; + company_name?: string; + page?: number; +} diff --git a/src/modules/requisitions/CreateRequisition.vue b/src/modules/requisitions/CreateRequisition.vue index d94e41d..ccc9504 100644 --- a/src/modules/requisitions/CreateRequisition.vue +++ b/src/modules/requisitions/CreateRequisition.vue @@ -1,5 +1,5 @@ @@ -262,7 +441,7 @@ onMounted(async () => { - + @@ -347,6 +526,12 @@ onMounted(async () => { + + - + + + +
+
+
+ +
+

+ {{ approvalType === 'technical' ? '¿Aprobar requisición técnicamente?' : '¿Aprobar requisición financieramente?' }} +

+

+ Folio: {{ requisitionToApprove.folio }} +

+

+ Solicitante: {{ requisitionToApprove.requester }} +

+

+ Monto: ${{ requisitionToApprove.totalAmount.toLocaleString('es-MX') }} +

+

+ {{ approvalType === 'technical' + ? 'Al aprobar, la requisición pasará automáticamente a finanzas.' + : 'Al aprobar, la requisición pasará a almacén.' + }} +

+
+
+
+ +
+ +