diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..7571cec --- /dev/null +++ b/.dockerignore @@ -0,0 +1,50 @@ +# Dependencies +node_modules +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# Build outputs +dist +dist-ssr +*.local + +# Git +.git +.gitignore + +# Docker +Dockerfile +docker-compose.yml +.dockerignore + +# IDE +.vscode +.idea +*.sw? +*.suo +*.ntvs* +*.njsproj +*.sln + +# OS +.DS_Store +Thumbs.db + +# Environment +.env +.env.local +.env.*.local + +# Documentation +README.md +*.md + +# Testing +coverage +.nyc_output + +# Logs +logs +*.log diff --git a/.env.example b/.env.example index b1cef5b..74604e7 100644 --- a/.env.example +++ b/.env.example @@ -3,6 +3,7 @@ VITE_API_URL=http://localhost:3000/api # Environment VITE_APP_ENV=development +APP_PORT=3000 # App Configuration VITE_APP_NAME=GOLS Control diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..eb455ea --- /dev/null +++ b/.env.production @@ -0,0 +1,9 @@ +# API Configuration (Production) +VITE_API_URL=https://api.golscontrol.com/api + +# Environment +VITE_APP_ENV=production + +# App Configuration +VITE_APP_NAME=GOLS Control +VITE_APP_VERSION=1.0.0 diff --git a/.gitignore b/.gitignore index 50c8dda..378ffdb 100644 --- a/.gitignore +++ b/.gitignore @@ -23,4 +23,10 @@ dist-ssr *.sln *.sw? +# Environment files .env +.env.local +.env.*.local + +# Docker +docker-compose.override.yml diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..ed0fbb0 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,33 @@ +# Stage 1: Build the application +FROM node:22-alpine AS builder + +WORKDIR /app + +# Copy package files first to leverage Docker cache +COPY package*.json ./ + +# Install dependencies +RUN npm ci + +# Copy the rest of the application code +COPY . . + +# Build the application +ARG VITE_API_URL +ENV VITE_API_URL=$VITE_API_URL +RUN npm run build + +# Stage 2: Serve the application with Nginx +FROM nginx:alpine AS production + +# Copy the built artifacts from the builder stage +COPY --from=builder /app/dist /usr/share/nginx/html + +# Copy custom Nginx configuration +COPY nginx.conf /etc/nginx/conf.d/default.conf + +# Expose port 80 +EXPOSE 80 + +# Start Nginx +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/README.md b/README.md index 15a778a..f08a85e 100644 --- a/README.md +++ b/README.md @@ -1,115 +1,20 @@ # Estructura del Proyecto - GOLS Control Frontend -## 📁 Estructura de Carpetas +## Docker (Producción) -``` -src/ -├── App.vue # Componente raíz (cambia entre demos) -├── main.ts # Punto de entrada -├── MainLayout.vue # Layout principal con Sidebar + TopBar -├── ColorDemo.vue # Demo de personalización de colores -│ -├── assets/ # Recursos estáticos -│ └── styles/ -│ └── main.css # Estilos globales y variables CSS -│ -├── components/ # Componentes globales -│ ├── layout/ # Componentes de layout -│ │ ├── TopBar.vue # Barra superior -│ │ ├── Sidebar.vue # Menú lateral -│ │ └── AppConfig.vue # Panel de configuración de colores -│ │ -│ ├── shared/ # Componentes compartidos -│ │ └── KpiCard.vue # Tarjeta de KPI -│ │ -│ ├── ui/ # Componentes UI reutilizables -│ │ └── (vacío por ahora) -│ │ -│ └── Holos/ # (Legacy - se puede eliminar) -│ ├── AppTopbar.vue -│ └── AppConfig.vue -│ -├── composables/ # Composables globales -│ └── useLayout.ts # Gestión de tema y colores -│ -├── modules/ # Módulos de negocio -│ └── warehouse/ # Módulo de almacén -│ ├── components/ -│ │ ├── WarehouseDashboard.vue # Dashboard principal -│ │ └── InventoryTable.vue # Tabla de inventario -│ │ -│ ├── composables/ -│ │ └── useWarehouse.ts # Lógica de negocio -│ │ -│ ├── services/ -│ │ └── warehouseService.ts # API del módulo -│ │ -│ └── types/ -│ └── warehouse.d.ts # Tipos TypeScript -│ -├── services/ # Servicios globales -│ └── api.ts # Cliente HTTP base -│ -└── types/ # Tipos globales - └── global.d.ts # Definiciones TypeScript globales +```bash +# 1. Configurar +cp .env.production .env + +# 2. Levantar +docker-compose up -d + +# 3. Verificar en http://localhost ``` -## 🎯 Convenciones +Ver [DOCKER.md](DOCKER.md) para más detalles. -### Módulos -Cada módulo sigue la estructura: -``` -modules/[nombre-modulo]/ -├── components/ # Componentes específicos del módulo -├── composables/ # Lógica de negocio del módulo -├── services/ # API calls del módulo -└── types/ # Types específicos del módulo -``` - -### Componentes -- **Layout**: Componentes de estructura (TopBar, Sidebar, etc.) -- **Shared**: Componentes reutilizables entre módulos -- **UI**: Componentes de interfaz básicos - -### Composables -- Prefijo `use` (ej: `useWarehouse`, `useLayout`) -- Encapsulan lógica reutilizable -- Retornan estado reactivo y métodos - -### Services -- Manejan comunicaciones HTTP -- Retornan Promises -- Usan el cliente `api.ts` base - -## 🚀 Uso - -### Ver Demo de Colores -```ts -// En App.vue -const currentView = ref<'color' | 'warehouse'>('color'); -``` - -### Ver Dashboard de Almacén -```ts -// En App.vue -const currentView = ref<'color' | 'warehouse'>('warehouse'); -``` - -## 📦 Crear un Nuevo Módulo - -1. Crear estructura en `src/modules/[nombre]/` -2. Definir tipos en `types/[nombre].d.ts` -3. Crear servicio en `services/[nombre]Service.ts` -4. Crear composable en `composables/use[Nombre].ts` -5. Crear componentes en `components/` - -## 🎨 Sistema de Colores - -- Color primario: **Azul** (fijo) -- Colores de superficie: **5 opciones** (slate, gray, zinc, neutral, stone) -- Modo oscuro: Activable desde TopBar - -## 📝 Notas +## Notas - Los componentes de PrimeVue se auto-importan - TypeScript configurado con strict mode diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..ecb8767 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,17 @@ +services: + controls-front: + build: + context: . + dockerfile: Dockerfile + args: + VITE_API_URL: ${VITE_API_URL} + container_name: controls-front-prod + ports: + - "${APP_PORT}:80" + networks: + - controls-network + restart: unless-stopped + +networks: + controls-network: + driver: bridge \ No newline at end of file diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..b4a471c --- /dev/null +++ b/nginx.conf @@ -0,0 +1,23 @@ +server { + listen 80; + server_name 127.0.0.1; + + root /usr/share/nginx/html; + index index.html; + + + location / { + try_files $uri $uri/ /index.html; + } + # Optional: Cache static assets for better performance + location ~* \.(?:ico|css|js|gif|jpe?g|png|woff2?|eot|ttf|svg|otf)$ { + expires 6M; + access_log off; + add_header Cache-Control "public"; + } + + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } +} diff --git a/src/components/shared/KpiCard.vue b/src/components/shared/KpiCard.vue index 72a1b23..eaefa51 100644 --- a/src/components/shared/KpiCard.vue +++ b/src/components/shared/KpiCard.vue @@ -10,7 +10,7 @@ interface Props { color?: 'primary' | 'success' | 'warning' | 'danger' | 'info'; } -const props = withDefaults(defineProps(), { +withDefaults(defineProps(), { color: 'primary' }); diff --git a/src/modules/catalog/components/UnitOfMeasure.vue b/src/modules/catalog/components/UnitOfMeasure.vue index 61560f8..c2c523f 100644 --- a/src/modules/catalog/components/UnitOfMeasure.vue +++ b/src/modules/catalog/components/UnitOfMeasure.vue @@ -19,7 +19,6 @@ import ProgressSpinner from 'primevue/progressspinner'; import { useUnitOfMeasureStore } from '../stores/unitOfMeasureStore'; import { unitTypesService } from '../services/unitsTypes'; import type { UnitOfMeasure, CreateUnitOfMeasureData } from '../types/unitOfMeasure'; -import type { UnitType } from '../types/unitTypes'; const router = useRouter(); const toast = useToast(); diff --git a/src/modules/catalog/stores/supplierStore.ts b/src/modules/catalog/stores/supplierStore.ts index b252c0f..accefa2 100644 --- a/src/modules/catalog/stores/supplierStore.ts +++ b/src/modules/catalog/stores/supplierStore.ts @@ -15,11 +15,11 @@ export const useSupplierStore = defineStore('supplier', () => { const response = await supplierServices.getSuppliers(false); // Si la respuesta es paginada, usar response.data; si es lista, usar response.suppliers o response directamente if (Array.isArray(response)) { - suppliers.value = response; + suppliers.value = response as Supplier[]; } else if ('suppliers' in response) { - suppliers.value = response.suppliers; + suppliers.value = (response as any).suppliers; } else if ('data' in response) { - suppliers.value = response.data; + suppliers.value = (response as any).data; } else { suppliers.value = []; } diff --git a/src/modules/purchases/components/ProductsModal.vue b/src/modules/purchases/components/ProductsModal.vue index 68db7b3..a1712d1 100644 --- a/src/modules/purchases/components/ProductsModal.vue +++ b/src/modules/purchases/components/ProductsModal.vue @@ -1,14 +1,15 @@ - +
- +
- + :loading="loading" stripedRows responsiveLayout="scroll" class="text-sm"> - + - + :loading="loading" stripedRows responsiveLayout="scroll" class="text-sm"> @@ -231,7 +223,7 @@
- + - +
diff --git a/src/modules/warehouse/components/WarehouseForm.vue b/src/modules/warehouse/components/WarehouseForm.vue index 263e282..5906bb4 100644 --- a/src/modules/warehouse/components/WarehouseForm.vue +++ b/src/modules/warehouse/components/WarehouseForm.vue @@ -10,7 +10,6 @@ import InputSwitch from 'primevue/inputswitch'; import Textarea from 'primevue/textarea'; import Dropdown from 'primevue/dropdown'; import Chip from 'primevue/chip'; -import Avatar from 'primevue/avatar'; import Toast from 'primevue/toast'; import { warehouseService } from '../services/warehouseService'; import { useClassificationStore } from '../stores/classificationStore'; @@ -44,13 +43,16 @@ const isSubmitting = ref(false); // Categories from store const availableClassifications = computed(() => { - return classificationStore.activeClassifications.map(cls => ({ + // Recursive function to ensure all children arrays are defined + const mapClassification = (cls: any): any => ({ id: cls.id, name: cls.name, code: cls.code, parent_id: cls.parent_id, - children: cls.children || [] - })); + children: (cls.children || []).map(mapClassification) + }); + + return classificationStore.activeClassifications.map(mapClassification); }); // Get root classifications (categories without parent) @@ -87,7 +89,7 @@ const addSelectedCategory = () => { // If subcategory is selected, use it instead if (selectedSubCategory.value) { - const subcat = parent.children?.find((c: any) => c.id === selectedSubCategory.value); + const subcat = parent.children.find((c: any) => c.id === selectedSubCategory.value); if (subcat) { categoryToAdd = subcat; categoryName = `${parent.name} > ${subcat.name}`; @@ -95,7 +97,7 @@ const addSelectedCategory = () => { } // Check if already added - if (assignedCategories.value.some(c => c.id === categoryToAdd.id)) { + if (assignedCategories.value.some((c: any) => c.id === categoryToAdd.id)) { toast.add({ severity: 'warn', summary: 'Categoría ya agregada', @@ -108,7 +110,9 @@ const addSelectedCategory = () => { assignedCategories.value.push({ id: categoryToAdd.id, name: categoryName, - code: categoryToAdd.code + code: categoryToAdd.code, + parent_id: categoryToAdd.parent_id, + children: categoryToAdd.children || [] }); // Reset selections @@ -116,27 +120,27 @@ const addSelectedCategory = () => { selectedSubCategory.value = null; }; -// Staff -const assignedStaff = ref([ - { - id: 1, - name: 'Jane Cooper', - role: 'Gerente de Almacén', - avatar: 'https://i.pravatar.cc/150?img=1' - }, - { - id: 2, - name: 'Cody Fisher', - role: 'Operador de Montacargas', - avatar: 'https://i.pravatar.cc/150?img=2' - }, - { - id: 3, - name: 'Esther Howard', - role: 'Auxiliar de Recepción', - avatar: 'https://i.pravatar.cc/150?img=3' - } -]); +// Staff (unused, for future use) +// const assignedStaff = ref([ +// { +// id: 1, +// name: 'Jane Cooper', +// role: 'Gerente de Almacén', +// avatar: 'https://i.pravatar.cc/150?img=1' +// }, +// { +// id: 2, +// name: 'Cody Fisher', +// role: 'Operador de Montacargas', +// avatar: 'https://i.pravatar.cc/150?img=2' +// }, +// { +// id: 3, +// name: 'Esther Howard', +// role: 'Auxiliar de Recepción', +// avatar: 'https://i.pravatar.cc/150?img=3' +// } +// ]); const saveDisabled = ref(false); @@ -144,17 +148,18 @@ const removeCategory = (id: number) => { assignedCategories.value = assignedCategories.value.filter(cat => cat.id !== id); }; -const addStaff = () => { - console.log('Add staff'); -}; +// Unused staff methods (for future use) +// const addStaff = () => { +// console.log('Add staff'); +// }; -const editStaff = (id: number) => { - console.log('Edit staff:', id); -}; +// const editStaff = (id: number) => { +// console.log('Edit staff:', id); +// }; -const removeStaff = (id: number) => { - assignedStaff.value = assignedStaff.value.filter(staff => staff.id !== id); -}; +// const removeStaff = (id: number) => { +// assignedStaff.value = assignedStaff.value.filter(staff => staff.id !== id); +// }; const cancel = () => { router.push('/warehouse'); diff --git a/src/modules/warehouse/components/index.html b/src/modules/warehouse/components/index.html index 14b7b69..2f2ace4 100644 --- a/src/modules/warehouse/components/index.html +++ b/src/modules/warehouse/components/index.html @@ -1,12 +1,17 @@ - - - -WMS - Batch Add Inventory Items - - - - + + + - - -
- -
-
-
-
- - - -
-

WMS Dashboard

-
-
- -
- - -
-
-
-
-
-
-
-Dashboard -/ -Inventory -/ -Batch Add Items -
-
-
-

Add Items to Inventory

-

Search and add multiple products to your stock in a single batch.

-
-
-
-

Select Products from Catalog

-
-
- -
-search - -
-
-
-

Selected Product

-
-
-image -
-
-

Smart Display Panel

-

SKU: DISP-PNL-SD-001

-
-
-
-
- - -
-
- - -
-
- - -
-
- -
-
-
-
-
-
-
-

Queued Items (4)

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Product NameSKUVariantQuantityUnitAction
-
-
-product -
-Smart Display Panel -
-
DISP-PNL-SD-001 -
-Medida: 85 -Resolución: 4K -
-
- -pcs - -
-
-
-product -
-Mechanical Keyboard RGB -
-
KYBD-RGB-US-02 -Red Switch - - -pcs - -
-
-
-product -
-USB-C Charging Cable 2m -
-
CBL-USBC-2M -Braided - - -pcs - -
-
-
-product -
-Smart Display Panel -
-
DISP-PNL-SD-001 -
-Medida: 36 -Resolución: 1080 -
-
- -pcs - -
-
-
- Total items to be added: 142 units across 4 unique products. -
-
-
-
-
-
-
-Storage Location - -
-
-
- - -
-
-
-
- \ No newline at end of file + +
+ +
+
+
+
+ Inicio + chevron_right + Órdenes de Compra + chevron_right + Registrar Entrada (Multialmacén) +
+
+
+
+ search + +
+ + +
+
+
+
+
+
+

Registrar + Entrada de Mercancía

+

+ receipt_long + Purchase Order #ORD-2023-001 | Distribución + Multi-Almacén +

+
+
+
+
+

Total Items + PO

+

12

+
+
+
+

Recibidos +

+

0

+
+
+ +
+
+
+
+

Productos de la Orden

+ + info + Seleccione el almacén de destino por cada producto + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ProductoSKU / RefCant. PORecibidaAlmacén de DestinoAcciones
+
+
+ inventory +
+
+ Cables + de Red Cat6 2m + Accesorios Networking +
+
+
NET-C62M-WH + + 50 +
+ +
+
+ + + Estándar +
+
+
+ laptop_mac +
+
+ MacBook + Pro M2 14" + Equipos de Cómputo +
+
+
LAP-MBP14-M2 + + 5 + 1 / 5 + +
Asignación por número de serie +
+
+ +
+
+
+
+

+ Entrada de Números de Serie (4 Pendientes)

+

Defina el almacén para + cada equipo escaneado

+
+
+ barcode + Listo para escanear +
+
+
+
+
+ +
+ qr_code_scanner + +
+
+
+ + +
+ +
+
+
+ + + + + + + + + + + + + + + + + + +
+ Nº Serie + Almacén Destino
+ SN-LAP-M2-00192 + + + Almacén + Principal (CDMX) + + + +
+ Escanee el siguiente equipo para asignar + almacén... +
+
+
+
+
+
+
+
+ print +
+
+ Impresora + Zebra ZT411 + Hardware Almacén +
+
+
PRN-ZB411-IND + + 20 / 2 +
Asignación por serie requerida +
+
+ +
+
+
+
+
+ warning +
+

Pendiente de Validación + y Distribución

+

Faltan registrar 6 números de + serie y asignar almacén de destino a 1 item de tipo estándar antes de confirmar.

+
+
+
+

Resumen de + Destinos

+
+
+ Almacén Principal (CDMX) + 1 Unidad +
+
+ Bodega Regional (MTY) + 0 Unidades +
+
+ CEDIS (GDL) + 0 Unidades +
+
+
+
+
+
+
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/src/modules/warehouse/components/modal.html b/src/modules/warehouse/components/modal.html deleted file mode 100644 index ed99dd2..0000000 --- a/src/modules/warehouse/components/modal.html +++ /dev/null @@ -1,364 +0,0 @@ - - - - -WMS - Batch Add Inventory Items - - - - - - - -
- -
-
-
-
- - - -
-

WMS Dashboard

-
-
- -
- - -
-
-
-
-
-
-
-Dashboard -/ -Inventory -/ -Batch Add Items -
-
-
-

Add Items to Inventory

-

Manage your batch inventory addition list here.

-
- -
-
-
-

Queued Items (4)

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Product NameSKUVariantQuantityUnitAction
-
-
-product -
-Smart Display Panel -
-
DISP-PNL-SD-001 -
-Medida: 85 -Resolución: 4K -
-
- -pcs - -
-
-
-product -
-Mechanical Keyboard RGB -
-
KYBD-RGB-US-02 -Red Switch - - -pcs - -
-
-
-product -
-USB-C Charging Cable 2m -
-
CBL-USBC-2M -Braided - - -pcs - -
-
-
-product -
-Smart Display Panel -
-
DISP-PNL-SD-001 -
-Medida: 36 -Resolución: 1080 -
-
- -pcs - -
-
-
- Total items to be added: 142 units across 4 unique products. -
-
-
-
-
-
-
-Storage Location - -
-
-
- - -
-
-
-
-
-
-
-
-

Add Product to Batch

-

Search and configure the product variant

-
- -
-
-
- -
-search - -
-
-
-
-
-image -
-
-

Smart Display Panel

-

SKU: DISP-PNL-SD-001

-
-
-
-
- - -
-
- - -
-
- -
- -pcs -
-
-
-
-info -Current Stock: 420 units -
-
-
-
-
-
- - -
-
-
-
- - \ No newline at end of file diff --git a/src/modules/warehouse/services/inventoryWarehouse.services.ts b/src/modules/warehouse/services/inventoryWarehouse.services.ts new file mode 100644 index 0000000..832ab5d --- /dev/null +++ b/src/modules/warehouse/services/inventoryWarehouse.services.ts @@ -0,0 +1,16 @@ +import api from "../../../services/api"; +import type { CreateInventoryRequest, CreateInventoryResponse } from "../types/warehouse.inventory"; + +export const inventoryWarehouseServices = { + async addInventory(data: CreateInventoryRequest): Promise { + try { + const response = await api.post('/api/inventory-warehouses', data); + console.log('📦 Add Inventory response:', response.data); + return response.data; + } catch (error) { + console.error('❌ Error adding inventory:', error); + throw error; + } + } + +} diff --git a/src/modules/warehouse/services/warehouseService.ts b/src/modules/warehouse/services/warehouseService.ts index f45c612..f18eccd 100644 --- a/src/modules/warehouse/services/warehouseService.ts +++ b/src/modules/warehouse/services/warehouseService.ts @@ -1,5 +1,5 @@ import api from '../../../services/api'; -import type { WarehousesResponse, CreateWarehouseData } from '../types/warehouse'; +import type { WarehousesResponse, CreateWarehouseData, WarehouseDetailResponse } from '../types/warehouse'; export const warehouseService = { async getWarehouses() { @@ -22,5 +22,16 @@ export const warehouseService = { console.error('Error creating warehouse:', error); throw error; } + }, + + async getWarehouseById(warehouseId: number) { + try { + const response = await api.get(`/api/warehouses/${warehouseId}`); + console.log(`Warehouse with ID ${warehouseId} response:`, response.data); + return response.data; + } catch (error) { + console.error(`Error fetching warehouse with ID ${warehouseId}:`, error); + throw error; + } } }; diff --git a/src/modules/warehouse/types/warehouse.d.ts b/src/modules/warehouse/types/warehouse.d.ts index eb78ea4..652dcfb 100644 --- a/src/modules/warehouse/types/warehouse.d.ts +++ b/src/modules/warehouse/types/warehouse.d.ts @@ -46,3 +46,63 @@ export interface WarehousesResponse { warehouses: WarehousePagination; }; } + +export interface WarehouseProduct { + id: number; + code: string; + sku: string; + name: string; + barcode: string; + description: string; + unit_of_measure_id: number; + suggested_sale_price: number; + attributes: Record | null; + is_active: boolean; + created_at: string; + updated_at: string; + deleted_at: string | null; +} + +export interface WarehouseStock { + id: number; + product_id: number; + warehouse_id: number; + stock: number; + stock_min: number | null; + stock_max: number | null; + reorder_point: number | null; + is_active: number; + created_at: string; + updated_at: string; + product: WarehouseProduct; +} + +export interface WarehouseInventoryItem { + id: number; + product_id: number; + warehouse_id: number; + quantity: string; + serial_number: string | null; + acquisition_date: string; + warehouse_number: string | null; + attributes: Record | null; + purchase_cost: number; + warranty_days: number | null; + warranty_end_date: string | null; + expiration_date: string | null; + created_at: string; + updated_at: string; + deleted_at: string | null; + product: WarehouseProduct; +} + +export interface WarehouseDetailData { + warehouse: Warehouse; + stocks: WarehouseStock[]; + items: WarehouseInventoryItem[]; +} + +export interface WarehouseDetailResponse { + status: string; + data: WarehouseDetailData; +} diff --git a/src/modules/warehouse/types/warehouse.inventory.d.ts b/src/modules/warehouse/types/warehouse.inventory.d.ts new file mode 100644 index 0000000..d2dc8c6 --- /dev/null +++ b/src/modules/warehouse/types/warehouse.inventory.d.ts @@ -0,0 +1,74 @@ +export interface InventoryProductItem { + product_id: number; + warehouse_id: number; + purchase_cost: number; + quantity?: number; + attributes?: Record; + serial_number?: string; + serial_numbers?: string[]; +} + +export interface CreateInventoryRequest { + products: InventoryProductItem[]; +} + +export interface InventoryProduct { + id: number; + code: string; + sku: string; + name: string; + barcode: string; + description: string; + unit_of_measure_id: number; + suggested_sale_price: number; + attributes: Record | null; + is_active: boolean; + created_at: string; + updated_at: string; + deleted_at: string | null; +} + +export interface InventoryWarehouse { + id: number; + code: string; + name: string; + description: string; + address: string | null; + is_active: boolean; + created_at: string; + updated_at: string; + deleted_at: string | null; +} + +export interface InventoryItemDetail { + id: number; + product_id: number; + warehouse_id: number; + quantity: string; + serial_number: string | null; + attributes: Record | null; + purchase_cost: number; + acquisition_date: string; + created_at: string; + updated_at: string; + product: InventoryProduct; + warehouse: InventoryWarehouse; +} + +export interface InventoryGroupResult { + inventory_items: InventoryItemDetail[]; + previous_stock: number; + added_quantity: number; + new_stock: number; + type: 'stock' | 'serialized'; +} + +export interface CreateInventoryResponseMeta { + total_items: number; +} + +export interface CreateInventoryResponse { + message: string; + data: InventoryGroupResult[]; + meta: CreateInventoryResponseMeta; +} diff --git a/src/router/index.ts b/src/router/index.ts index 322f302..f8e6f2c 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -7,8 +7,6 @@ import MainLayout from '../MainLayout.vue'; import WarehouseIndex from '../modules/warehouse/components/WarehouseIndex.vue'; import WarehouseForm from '../modules/warehouse/components/WarehouseForm.vue'; import WarehouseDetails from '../modules/warehouse/components/WarehouseDetails.vue'; -import BatchAddInventory from '../modules/warehouse/components/BatchAddInventory.vue'; - import WarehouseClassification from '../modules/warehouse/components/WarehouseClassification.vue'; import UnitOfMeasure from '../modules/catalog/components/UnitOfMeasure.vue'; import ComercialClassification from '../modules/catalog/components/ComercialClassification.vue'; @@ -28,6 +26,7 @@ import Suppliers from '../modules/catalog/components/suppliers/Suppliers.vue'; import Purchases from '../modules/purchases/components/Purchases.vue'; import PurchaseDetails from '../modules/purchases/components/PurchaseDetails.vue'; import PurchaseForm from '../modules/purchases/components/PurchaseForm.vue'; +import WarehouseAddInventory from '../modules/warehouse/components/WarehouseAddInventory.vue'; const routes: RouteRecordRaw[] = [ { path: '/login', @@ -100,8 +99,8 @@ const routes: RouteRecordRaw[] = [ }, { path: 'batch-add', - name: 'BatchAddInventory', - component: BatchAddInventory, + name: 'WarehouseAddInventory', + component: WarehouseAddInventory, meta: { title: 'Agregar Items al Inventario', requiresAuth: true