feat: repositorios, servicios, UI completa con rutas, Capacitor Android sync
This commit is contained in:
19
apps/toldo-app/android/app/capacitor.build.gradle
Normal file
19
apps/toldo-app/android/app/capacitor.build.gradle
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility JavaVersion.VERSION_17
|
||||||
|
targetCompatibility JavaVersion.VERSION_17
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
|
||||||
|
dependencies {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (hasProperty('postBuildExtras')) {
|
||||||
|
postBuildExtras()
|
||||||
|
}
|
||||||
3
apps/toldo-app/android/capacitor.settings.gradle
Normal file
3
apps/toldo-app/android/capacitor.settings.gradle
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN
|
||||||
|
include ':capacitor-android'
|
||||||
|
project(':capacitor-android').projectDir = new File('../node_modules/@capacitor/android/capacitor')
|
||||||
4056
apps/toldo-app/package-lock.json
generated
4056
apps/toldo-app/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -13,12 +13,13 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@capacitor/android": "^6.2.1",
|
"@capacitor/android": "^6.2.1",
|
||||||
"@capacitor/core": "^6.2.1",
|
"@capacitor/core": "^6.2.1",
|
||||||
"@toldo/core": "workspace:*",
|
"@toldo/core": "file:../../packages/core",
|
||||||
"@toldo/data": "workspace:*",
|
"@toldo/data": "file:../../packages/data",
|
||||||
"@toldo/services": "workspace:*",
|
"@toldo/services": "file:../../packages/services",
|
||||||
"@toldo/ui": "workspace:*",
|
"@toldo/ui": "file:../../packages/ui",
|
||||||
"dexie": "^4.0.10",
|
"dexie": "^4.0.10",
|
||||||
"vue": "^3.5.44"
|
"vue": "^3.5.44",
|
||||||
|
"vue-router": "file:vue-router-4.4.5.tgz"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@capacitor/cli": "^6.2.1",
|
"@capacitor/cli": "^6.2.1",
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import HelloWorld from './components/HelloWorld.vue'
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<HelloWorld />
|
<router-view />
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
29
apps/toldo-app/src/components/Layout.vue
Normal file
29
apps/toldo-app/src/components/Layout.vue
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<template>
|
||||||
|
<div class="layout">
|
||||||
|
<header>
|
||||||
|
<h1>ToldoConjunto - CESTA</h1>
|
||||||
|
<nav>
|
||||||
|
<router-link to="/">Inicio</router-link>
|
||||||
|
<router-link to="/inventario">Inventario</router-link>
|
||||||
|
<router-link to="/ventas">Ventas</router-link>
|
||||||
|
<router-link to="/gastos">Gastos</router-link>
|
||||||
|
<router-link to="/cuadre">Cuadre</router-link>
|
||||||
|
<router-link to="/reportes">Reportes</router-link>
|
||||||
|
<router-link to="/ajustes">Ajustes</router-link>
|
||||||
|
<router-link to="/exportar">Exportar/Importar</router-link>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<main>
|
||||||
|
<router-view />
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.layout { font-family: system-ui, sans-serif; }
|
||||||
|
header { background: #2d5f3b; color: white; padding: 1rem; }
|
||||||
|
nav { display: flex; gap: 1rem; flex-wrap: wrap; margin-top: 0.5rem; }
|
||||||
|
nav a { color: white; text-decoration: none; }
|
||||||
|
nav a.router-link-active { text-decoration: underline; }
|
||||||
|
main { padding: 1rem; }
|
||||||
|
</style>
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue'
|
||||||
import './style.css'
|
import './style.css'
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
|
import router from './router'
|
||||||
|
|
||||||
createApp(App).mount('#app')
|
createApp(App).use(router).mount('#app')
|
||||||
|
|||||||
32
apps/toldo-app/src/router/index.ts
Normal file
32
apps/toldo-app/src/router/index.ts
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import { createRouter, createWebHistory } from 'vue-router';
|
||||||
|
import Layout from '../components/Layout.vue';
|
||||||
|
import Home from '../views/Home.vue';
|
||||||
|
import Inventario from '../views/Inventario.vue';
|
||||||
|
import Ventas from '../views/Ventas.vue';
|
||||||
|
import Gastos from '../views/Gastos.vue';
|
||||||
|
import Cuadre from '../views/Cuadre.vue';
|
||||||
|
import Reportes from '../views/Reportes.vue';
|
||||||
|
import Ajustes from '../views/Ajustes.vue';
|
||||||
|
import Exportar from '../views/Exportar.vue';
|
||||||
|
|
||||||
|
const router = createRouter({
|
||||||
|
history: createWebHistory(),
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
path: '/',
|
||||||
|
component: Layout,
|
||||||
|
children: [
|
||||||
|
{ path: '', component: Home },
|
||||||
|
{ path: 'inventario', component: Inventario },
|
||||||
|
{ path: 'ventas', component: Ventas },
|
||||||
|
{ path: 'gastos', component: Gastos },
|
||||||
|
{ path: 'cuadre', component: Cuadre },
|
||||||
|
{ path: 'reportes', component: Reportes },
|
||||||
|
{ path: 'ajustes', component: Ajustes },
|
||||||
|
{ path: 'exportar', component: Exportar },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
||||||
6
apps/toldo-app/src/views/Ajustes.vue
Normal file
6
apps/toldo-app/src/views/Ajustes.vue
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h2>Ajustes</h2>
|
||||||
|
<p>Módulo en desarrollo</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
6
apps/toldo-app/src/views/Cuadre.vue
Normal file
6
apps/toldo-app/src/views/Cuadre.vue
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h2>Cuadre</h2>
|
||||||
|
<p>Módulo en desarrollo</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
6
apps/toldo-app/src/views/Exportar.vue
Normal file
6
apps/toldo-app/src/views/Exportar.vue
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h2>Exportar</h2>
|
||||||
|
<p>Módulo en desarrollo</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
6
apps/toldo-app/src/views/Gastos.vue
Normal file
6
apps/toldo-app/src/views/Gastos.vue
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h2>Gastos</h2>
|
||||||
|
<p>Módulo en desarrollo</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
7
apps/toldo-app/src/views/Home.vue
Normal file
7
apps/toldo-app/src/views/Home.vue
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h2>Inicio</h2>
|
||||||
|
<p>Sistema de gestión para el Toldo de CESTA</p>
|
||||||
|
<p>Funciona offline - Datos guardados localmente</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
6
apps/toldo-app/src/views/Inventario.vue
Normal file
6
apps/toldo-app/src/views/Inventario.vue
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h2>Inventario</h2>
|
||||||
|
<p>Módulo en desarrollo</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
6
apps/toldo-app/src/views/Reportes.vue
Normal file
6
apps/toldo-app/src/views/Reportes.vue
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h2>Reportes</h2>
|
||||||
|
<p>Módulo en desarrollo</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
6
apps/toldo-app/src/views/Ventas.vue
Normal file
6
apps/toldo-app/src/views/Ventas.vue
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h2>Ventas</h2>
|
||||||
|
<p>Módulo en desarrollo</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
BIN
apps/toldo-app/vue-router-4.4.5.tgz
Normal file
BIN
apps/toldo-app/vue-router-4.4.5.tgz
Normal file
Binary file not shown.
@@ -14,7 +14,7 @@
|
|||||||
"build": "tsc"
|
"build": "tsc"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@toldo/core": "workspace:*",
|
"@toldo/core": "file:../core",
|
||||||
"dexie": "^4.0.10"
|
"dexie": "^4.0.10"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
export * from './db/schema';
|
export * from './db/schema';
|
||||||
|
export * from './repositories';
|
||||||
|
|||||||
22
packages/data/src/repositories/AjusteRepository.ts
Normal file
22
packages/data/src/repositories/AjusteRepository.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { db } from '../db/schema';
|
||||||
|
import type { Ajuste } from '@toldo/core';
|
||||||
|
import { validateAjusteMotivo } from '@toldo/core';
|
||||||
|
|
||||||
|
export class AjusteRepository {
|
||||||
|
async create(ajuste: Ajuste): Promise<string> {
|
||||||
|
validateAjusteMotivo(ajuste.motivo);
|
||||||
|
return db.ajustes.add(ajuste);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getAll(): Promise<Ajuste[]> {
|
||||||
|
return db.ajustes.toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
async getByFecha(fecha: Date): Promise<Ajuste[]> {
|
||||||
|
const start = new Date(fecha);
|
||||||
|
start.setHours(0, 0, 0, 0);
|
||||||
|
const end = new Date(fecha);
|
||||||
|
end.setHours(23, 59, 59, 999);
|
||||||
|
return db.ajustes.where('fecha').between(start, end).toArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
20
packages/data/src/repositories/CuadreRepository.ts
Normal file
20
packages/data/src/repositories/CuadreRepository.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { db } from '../db/schema';
|
||||||
|
import type { CuadreCaja } from '@toldo/core';
|
||||||
|
|
||||||
|
export class CuadreRepository {
|
||||||
|
async create(cuadre: CuadreCaja): Promise<string> {
|
||||||
|
return db.cuadres.add(cuadre);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getByFecha(fecha: Date): Promise<CuadreCaja[]> {
|
||||||
|
const start = new Date(fecha);
|
||||||
|
start.setHours(0, 0, 0, 0);
|
||||||
|
const end = new Date(fecha);
|
||||||
|
end.setHours(23, 59, 59, 999);
|
||||||
|
return db.cuadres.where('fecha').between(start, end).toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
async getAll(): Promise<CuadreCaja[]> {
|
||||||
|
return db.cuadres.toArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
20
packages/data/src/repositories/GastoRepository.ts
Normal file
20
packages/data/src/repositories/GastoRepository.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { db } from '../db/schema';
|
||||||
|
import type { Gasto } from '@toldo/core';
|
||||||
|
|
||||||
|
export class GastoRepository {
|
||||||
|
async create(gasto: Gasto): Promise<string> {
|
||||||
|
return db.gastos.add(gasto);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getByFecha(fecha: Date): Promise<Gasto[]> {
|
||||||
|
const start = new Date(fecha);
|
||||||
|
start.setHours(0, 0, 0, 0);
|
||||||
|
const end = new Date(fecha);
|
||||||
|
end.setHours(23, 59, 59, 999);
|
||||||
|
return db.gastos.where('fecha').between(start, end).toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
async getAll(): Promise<Gasto[]> {
|
||||||
|
return db.gastos.toArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { db } from '../db/schema';
|
||||||
|
import type { MovimientoInventario } from '@toldo/core';
|
||||||
|
|
||||||
|
export class MovimientoInventarioRepository {
|
||||||
|
async create(mov: MovimientoInventario): Promise<string> {
|
||||||
|
return db.movimientosInventario.add(mov);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getByProducto(productoId: string): Promise<MovimientoInventario[]> {
|
||||||
|
return db.movimientosInventario.where('productoId').equals(productoId).toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
async getAll(): Promise<MovimientoInventario[]> {
|
||||||
|
return db.movimientosInventario.toArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
30
packages/data/src/repositories/ProductoRepository.ts
Normal file
30
packages/data/src/repositories/ProductoRepository.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import { db } from '../db/schema';
|
||||||
|
import type { Producto } from '@toldo/core';
|
||||||
|
|
||||||
|
export class ProductoRepository {
|
||||||
|
async getAll(): Promise<Producto[]> {
|
||||||
|
return db.productos.toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
async getByProductor(productorId: string): Promise<Producto[]> {
|
||||||
|
return db.productos.where('productorId').equals(productorId).toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
async getById(id: string): Promise<Producto | undefined> {
|
||||||
|
return db.productos.get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
async create(producto: Producto): Promise<string> {
|
||||||
|
// Ensure uniqueness by (productorId, nombrePresentacion)
|
||||||
|
const exists = await db.productos
|
||||||
|
.where('[productorId+nombrePresentacion]')
|
||||||
|
.equals([producto.productorId, producto.nombrePresentacion])
|
||||||
|
.first();
|
||||||
|
if (exists) throw new Error('Ya existe un producto con ese nombre para este productor');
|
||||||
|
return db.productos.add(producto);
|
||||||
|
}
|
||||||
|
|
||||||
|
async update(producto: Producto): Promise<number> {
|
||||||
|
return db.productos.put(producto);
|
||||||
|
}
|
||||||
|
}
|
||||||
24
packages/data/src/repositories/ProductorRepository.ts
Normal file
24
packages/data/src/repositories/ProductorRepository.ts
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import { db } from '../db/schema';
|
||||||
|
import type { Productor } from '@toldo/core';
|
||||||
|
|
||||||
|
export class ProductorRepository {
|
||||||
|
async getAll(): Promise<Productor[]> {
|
||||||
|
return db.productores.toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
async getById(id: string): Promise<Productor | undefined> {
|
||||||
|
return db.productores.get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
async create(productor: Productor): Promise<string> {
|
||||||
|
return db.productores.add(productor);
|
||||||
|
}
|
||||||
|
|
||||||
|
async update(productor: Productor): Promise<number> {
|
||||||
|
return db.productores.put(productor);
|
||||||
|
}
|
||||||
|
|
||||||
|
async delete(id: string): Promise<void> {
|
||||||
|
return db.productores.delete(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
24
packages/data/src/repositories/VentaRepository.ts
Normal file
24
packages/data/src/repositories/VentaRepository.ts
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import { db } from '../db/schema';
|
||||||
|
import type { Venta, VentaLinea } from '@toldo/core';
|
||||||
|
|
||||||
|
export class VentaRepository {
|
||||||
|
async create(venta: Venta, lineas: VentaLinea[]): Promise<string> {
|
||||||
|
return db.transaction('rw', db.ventas, db.ventaLineas, async () => {
|
||||||
|
await db.ventas.add(venta);
|
||||||
|
await db.ventaLineas.bulkAdd(lineas);
|
||||||
|
return venta.id;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async getByFecha(fecha: Date): Promise<Venta[]> {
|
||||||
|
const start = new Date(fecha);
|
||||||
|
start.setHours(0, 0, 0, 0);
|
||||||
|
const end = new Date(fecha);
|
||||||
|
end.setHours(23, 59, 59, 999);
|
||||||
|
return db.ventas.where('fecha').between(start, end).toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
async getAll(): Promise<Venta[]> {
|
||||||
|
return db.ventas.toArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
7
packages/data/src/repositories/index.ts
Normal file
7
packages/data/src/repositories/index.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
export * from './ProductorRepository';
|
||||||
|
export * from './ProductoRepository';
|
||||||
|
export * from './VentaRepository';
|
||||||
|
export * from './GastoRepository';
|
||||||
|
export * from './AjusteRepository';
|
||||||
|
export * from './MovimientoInventarioRepository';
|
||||||
|
export * from './CuadreRepository';
|
||||||
@@ -15,8 +15,8 @@
|
|||||||
"test": "vitest"
|
"test": "vitest"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@toldo/core": "workspace:*",
|
"@toldo/core": "file:../core",
|
||||||
"@toldo/data": "workspace:*"
|
"@toldo/data": "file:../data"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"typescript": "~6.0.3",
|
"typescript": "~6.0.3",
|
||||||
|
|||||||
31
packages/services/src/ajustes/AjustesService.ts
Normal file
31
packages/services/src/ajustes/AjustesService.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import { db } from '@toldo/data';
|
||||||
|
import type { Ajuste, MovimientoInventario } from '@toldo/core';
|
||||||
|
import { validateAjusteMotivo } from '@toldo/core';
|
||||||
|
|
||||||
|
export class AjustesService {
|
||||||
|
async crearAjuste(ajuste: Ajuste) {
|
||||||
|
validateAjusteMotivo(ajuste.motivo);
|
||||||
|
return db.transaction('rw', db.ajustes, db.movimientosInventario, async () => {
|
||||||
|
await db.ajustes.add(ajuste);
|
||||||
|
await db.movimientosInventario.add({
|
||||||
|
id: crypto.randomUUID(),
|
||||||
|
fecha: ajuste.fecha,
|
||||||
|
tipo: 'AJUSTE',
|
||||||
|
productoId: ajuste.productoId,
|
||||||
|
cantidad: ajuste.diferencia,
|
||||||
|
motivo: ajuste.motivo,
|
||||||
|
referenciaId: ajuste.id,
|
||||||
|
createdAt: new Date()
|
||||||
|
});
|
||||||
|
return ajuste.id;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async getAjustesDelDia(fecha: Date): Promise<Ajuste[]> {
|
||||||
|
const start = new Date(fecha);
|
||||||
|
start.setHours(0, 0, 0, 0);
|
||||||
|
const end = new Date(fecha);
|
||||||
|
end.setHours(23, 59, 59, 999);
|
||||||
|
return db.ajustes.where('fecha').between(start, end).toArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
56
packages/services/src/cuadre/CuadreService.ts
Normal file
56
packages/services/src/cuadre/CuadreService.ts
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import { db } from '@toldo/data';
|
||||||
|
import type { CuadreCaja } from '@toldo/core';
|
||||||
|
import { calcularSaldoEsperadoEfectivo, calcularDescuadreEfectivo, calcularTotalVentas } from '@toldo/core';
|
||||||
|
|
||||||
|
export class CuadreService {
|
||||||
|
async calcularCuadreDelDia(fecha: Date, baseInicial: number): Promise<Partial<CuadreCaja>> {
|
||||||
|
const start = new Date(fecha);
|
||||||
|
start.setHours(0, 0, 0, 0);
|
||||||
|
const end = new Date(fecha);
|
||||||
|
end.setHours(23, 59, 59, 999);
|
||||||
|
|
||||||
|
const ventas = await db.ventas.where('fecha').between(start, end).toArray();
|
||||||
|
const lineas = await db.ventaLineas.toArray();
|
||||||
|
const gastos = await db.gastos.where('fecha').between(start, end).toArray();
|
||||||
|
|
||||||
|
let totalVentasEfectivo = 0;
|
||||||
|
let totalVentasQR = 0;
|
||||||
|
|
||||||
|
for (const venta of ventas) {
|
||||||
|
const vLineas = lineas.filter(l => l.ventaId === venta.id);
|
||||||
|
for (const l of vLineas) {
|
||||||
|
if (l.formaPago === 'EFECTIVO') totalVentasEfectivo += l.subtotal;
|
||||||
|
else totalVentasQR += l.subtotal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let totalGastosEfectivo = 0;
|
||||||
|
let totalGastosQR = 0;
|
||||||
|
for (const g of gastos) {
|
||||||
|
if (g.formaPago === 'EFECTIVO') totalGastosEfectivo += g.monto;
|
||||||
|
else if (g.formaPago === 'QR') totalGastosQR += g.monto;
|
||||||
|
}
|
||||||
|
|
||||||
|
const saldoEsperadoEfectivo = calcularSaldoEsperadoEfectivo(baseInicial, totalVentasEfectivo, totalGastosEfectivo);
|
||||||
|
const totalVentas = calcularTotalVentas(totalVentasEfectivo, totalVentasQR);
|
||||||
|
|
||||||
|
return {
|
||||||
|
fecha,
|
||||||
|
baseInicial,
|
||||||
|
totalVentasEfectivo,
|
||||||
|
totalVentasQR,
|
||||||
|
totalGastosEfectivo,
|
||||||
|
totalGastosQR,
|
||||||
|
saldoEsperadoEfectivo,
|
||||||
|
totalVentas,
|
||||||
|
createdAt: new Date()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async guardarCuadre(cuadre: CuadreCaja) {
|
||||||
|
if (cuadre.saldoRealEfectivo !== undefined && cuadre.saldoEsperadoEfectivo !== undefined) {
|
||||||
|
cuadre.descuadreEfectivo = calcularDescuadreEfectivo(cuadre.saldoEsperadoEfectivo, cuadre.saldoRealEfectivo);
|
||||||
|
}
|
||||||
|
return db.cuadres.add(cuadre);
|
||||||
|
}
|
||||||
|
}
|
||||||
16
packages/services/src/gastos/GastosService.ts
Normal file
16
packages/services/src/gastos/GastosService.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { db } from '@toldo/data';
|
||||||
|
import type { Gasto } from '@toldo/core';
|
||||||
|
|
||||||
|
export class GastosService {
|
||||||
|
async registrarGasto(gasto: Gasto) {
|
||||||
|
return db.gastos.add(gasto);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getGastosDelDia(fecha: Date): Promise<Gasto[]> {
|
||||||
|
const start = new Date(fecha);
|
||||||
|
start.setHours(0, 0, 0, 0);
|
||||||
|
const end = new Date(fecha);
|
||||||
|
end.setHours(23, 59, 59, 999);
|
||||||
|
return db.gastos.where('fecha').between(start, end).toArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1 +1,7 @@
|
|||||||
|
export * from './ventas/VentasService';
|
||||||
|
export * from './gastos/GastosService';
|
||||||
|
export * from './ajustes/AjustesService';
|
||||||
|
export * from './inventario/InventarioService';
|
||||||
|
export * from './cuadre/CuadreService';
|
||||||
|
export * from './reportes/ReportesService';
|
||||||
export * from './export-import/ExportImportService';
|
export * from './export-import/ExportImportService';
|
||||||
|
|||||||
38
packages/services/src/inventario/InventarioService.ts
Normal file
38
packages/services/src/inventario/InventarioService.ts
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import { db } from '@toldo/data';
|
||||||
|
import type { MovimientoInventario } from '@toldo/core';
|
||||||
|
|
||||||
|
export class InventarioService {
|
||||||
|
async registrarIngresoInicial(productoId: string, cantidad: number, fecha: Date) {
|
||||||
|
const mov: MovimientoInventario = {
|
||||||
|
id: crypto.randomUUID(),
|
||||||
|
fecha,
|
||||||
|
tipo: 'INGRESO_INICIAL',
|
||||||
|
productoId,
|
||||||
|
cantidad,
|
||||||
|
createdAt: new Date()
|
||||||
|
};
|
||||||
|
return db.movimientosInventario.add(mov.id, mov);
|
||||||
|
}
|
||||||
|
|
||||||
|
async registrarIngresoSemana(productoId: string, cantidad: number, fecha: Date, recibidoPor: string) {
|
||||||
|
const mov: MovimientoInventario = {
|
||||||
|
id: crypto.randomUUID(),
|
||||||
|
fecha,
|
||||||
|
tipo: 'INGRESO_SEMANA',
|
||||||
|
productoId,
|
||||||
|
cantidad,
|
||||||
|
recibidoPor,
|
||||||
|
createdAt: new Date()
|
||||||
|
};
|
||||||
|
return db.movimientosInventario.add(mov.id, mov);
|
||||||
|
}
|
||||||
|
|
||||||
|
async calcularSaldoProducto(productoId: string): Promise<number> {
|
||||||
|
const movs = await db.movimientosInventario.where('productoId').equals(productoId).toArray();
|
||||||
|
return movs.reduce((acc, m) => acc + m.cantidad, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getMovimientosPorProducto(productoId: string): Promise<MovimientoInventario[]> {
|
||||||
|
return db.movimientosInventario.where('productoId').equals(productoId).toArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
56
packages/services/src/reportes/ReportesService.ts
Normal file
56
packages/services/src/reportes/ReportesService.ts
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import { db } from '@toldo/data';
|
||||||
|
|
||||||
|
export class ReportesService {
|
||||||
|
async reportePorProductor(fecha: Date) {
|
||||||
|
const productores = await db.productores.toArray();
|
||||||
|
const productos = await db.productos.toArray();
|
||||||
|
const start = new Date(fecha);
|
||||||
|
start.setHours(0, 0, 0, 0);
|
||||||
|
const end = new Date(fecha);
|
||||||
|
end.setHours(23, 59, 59, 999);
|
||||||
|
const ventas = await db.ventas.where('fecha').between(start, end).toArray();
|
||||||
|
const lineas = await db.ventaLineas.toArray();
|
||||||
|
const ajustes = await db.ajustes.where('fecha').between(start, end).toArray();
|
||||||
|
|
||||||
|
const reporte: any[] = [];
|
||||||
|
|
||||||
|
for (const productor of productores) {
|
||||||
|
const prodsProductor = productos.filter(p => p.productorId === productor.id);
|
||||||
|
let totalVentas = 0;
|
||||||
|
const salidas: any[] = [];
|
||||||
|
|
||||||
|
for (const prod of prodsProductor) {
|
||||||
|
const lineasProd = lineas.filter(l => l.productoId === prod.id && ventas.some(v => v.id === l.ventaId));
|
||||||
|
for (const lp of lineasProd) {
|
||||||
|
totalVentas += lp.subtotal;
|
||||||
|
salidas.push({ producto: prod.nombrePresentacion, cantidad: lp.cantidad, valor: lp.subtotal });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reporte.push({
|
||||||
|
productor: productor.nombre,
|
||||||
|
ajustes: ajustes.filter(a => prodsProductor.some(p => p.id === a.productoId)),
|
||||||
|
salidas,
|
||||||
|
totalVentas
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return reporte;
|
||||||
|
}
|
||||||
|
|
||||||
|
async reporteCuadre(fecha: Date) {
|
||||||
|
const start = new Date(fecha);
|
||||||
|
start.setHours(0, 0, 0, 0);
|
||||||
|
const end = new Date(fecha);
|
||||||
|
end.setHours(23, 59, 59, 999);
|
||||||
|
const cuadres = await db.cuadres.where('fecha').between(start, end).toArray();
|
||||||
|
return cuadres;
|
||||||
|
}
|
||||||
|
|
||||||
|
async consolidadoPorRango(fechaInicio: Date, fechaFin: Date) {
|
||||||
|
const ventas = await db.ventas.where('fecha').between(fechaInicio, fechaFin).toArray();
|
||||||
|
const gastos = await db.gastos.where('fecha').between(fechaInicio, fechaFin).toArray();
|
||||||
|
const ajustes = await db.ajustes.where('fecha').between(fechaInicio, fechaFin).toArray();
|
||||||
|
return { ventas: ventas.length, gastos: gastos.length, ajustes: ajustes.length };
|
||||||
|
}
|
||||||
|
}
|
||||||
37
packages/services/src/ventas/VentasService.ts
Normal file
37
packages/services/src/ventas/VentasService.ts
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import { db } from '@toldo/data';
|
||||||
|
import type { Venta, VentaLinea } from '@toldo/core';
|
||||||
|
|
||||||
|
export class VentasService {
|
||||||
|
async registrarVenta(venta: Venta, lineas: VentaLinea[]) {
|
||||||
|
// Validar stock mínimo conceptual - se puede expandir
|
||||||
|
return db.transaction('rw', db.ventas, db.ventaLineas, async () => {
|
||||||
|
await db.ventas.add(venta);
|
||||||
|
await db.ventaLineas.bulkAdd(lineas);
|
||||||
|
// Registrar movimientos de venta
|
||||||
|
for (const linea of lineas) {
|
||||||
|
await db.movimientosInventario.add({
|
||||||
|
id: crypto.randomUUID(),
|
||||||
|
fecha: venta.fecha,
|
||||||
|
tipo: 'VENTA',
|
||||||
|
productoId: linea.productoId,
|
||||||
|
cantidad: -Math.abs(linea.cantidad),
|
||||||
|
referenciaId: venta.id,
|
||||||
|
createdAt: new Date()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return venta.id;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async getVentasDelDia(fecha: Date): Promise<Venta[]> {
|
||||||
|
const start = new Date(fecha);
|
||||||
|
start.setHours(0, 0, 0, 0);
|
||||||
|
const end = new Date(fecha);
|
||||||
|
end.setHours(23, 59, 59, 999);
|
||||||
|
return db.ventas.where('fecha').between(start, end).toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
async getLineasPorVenta(ventaId: string): Promise<VentaLinea[]> {
|
||||||
|
return db.ventaLineas.where('ventaId').equals(ventaId).toArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,8 +14,8 @@
|
|||||||
"build": "tsc"
|
"build": "tsc"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@toldo/core": "workspace:*",
|
"@toldo/core": "file:../core",
|
||||||
"@toldo/services": "workspace:*"
|
"@toldo/services": "file:../services"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"typescript": "~6.0.3"
|
"typescript": "~6.0.3"
|
||||||
|
|||||||
Reference in New Issue
Block a user