michangarrito/apps/backend/dist/modules/customers/customers.service.js
rckrdmrd 48dea7a5d0 feat: Initial commit - michangarrito
Marketplace móvil para negocios locales mexicanos.

Estructura inicial:
- apps/backend (NestJS API)
- apps/frontend (React Web)
- apps/mobile (Expo/React Native)
- apps/mcp-server (Claude MCP Server)
- apps/whatsapp-service (WhatsApp Business API)
- database/ (PostgreSQL DDL)
- docs/ (Documentación)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 04:41:02 -06:00

202 lines
8.4 KiB
JavaScript

"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CustomersService = void 0;
const common_1 = require("@nestjs/common");
const typeorm_1 = require("@nestjs/typeorm");
const typeorm_2 = require("typeorm");
const customer_entity_1 = require("./entities/customer.entity");
const fiado_entity_1 = require("./entities/fiado.entity");
const fiado_payment_entity_1 = require("./entities/fiado-payment.entity");
let CustomersService = class CustomersService {
constructor(customerRepo, fiadoRepo, fiadoPaymentRepo) {
this.customerRepo = customerRepo;
this.fiadoRepo = fiadoRepo;
this.fiadoPaymentRepo = fiadoPaymentRepo;
}
async findAll(tenantId) {
return this.customerRepo.find({
where: { tenantId, status: 'active' },
order: { name: 'ASC' },
});
}
async findOne(tenantId, id) {
const customer = await this.customerRepo.findOne({
where: { id, tenantId },
relations: ['fiados'],
});
if (!customer) {
throw new common_1.NotFoundException('Cliente no encontrado');
}
return customer;
}
async findByPhone(tenantId, phone) {
return this.customerRepo.findOne({
where: { tenantId, phone },
});
}
async create(tenantId, dto) {
const customer = this.customerRepo.create({
...dto,
tenantId,
});
return this.customerRepo.save(customer);
}
async update(tenantId, id, dto) {
const customer = await this.findOne(tenantId, id);
Object.assign(customer, dto);
return this.customerRepo.save(customer);
}
async toggleActive(tenantId, id) {
const customer = await this.findOne(tenantId, id);
customer.status = customer.status === 'active' ? 'inactive' : 'active';
return this.customerRepo.save(customer);
}
async getWithFiados(tenantId) {
return this.customerRepo.find({
where: { tenantId, fiadoEnabled: true },
order: { currentFiadoBalance: 'DESC' },
});
}
async createFiado(tenantId, dto) {
const customer = await this.findOne(tenantId, dto.customerId);
if (!customer.fiadoEnabled) {
throw new common_1.BadRequestException('El cliente no tiene habilitado el fiado');
}
const newBalance = Number(customer.currentFiadoBalance) + dto.amount;
if (customer.fiadoLimit > 0 && newBalance > customer.fiadoLimit) {
throw new common_1.BadRequestException(`El fiado excede el límite. Límite: $${customer.fiadoLimit}, Balance actual: $${customer.currentFiadoBalance}`);
}
const fiado = this.fiadoRepo.create({
tenantId,
customerId: dto.customerId,
saleId: dto.saleId,
amount: dto.amount,
remainingAmount: dto.amount,
description: dto.description,
dueDate: dto.dueDate ? new Date(dto.dueDate) : null,
status: fiado_entity_1.FiadoStatus.PENDING,
});
await this.fiadoRepo.save(fiado);
customer.currentFiadoBalance = newBalance;
await this.customerRepo.save(customer);
return fiado;
}
async getFiados(tenantId, customerId) {
const where = { tenantId };
if (customerId) {
where.customerId = customerId;
}
return this.fiadoRepo.find({
where,
relations: ['customer', 'payments'],
order: { createdAt: 'DESC' },
});
}
async getPendingFiados(tenantId) {
return this.fiadoRepo.find({
where: [
{ tenantId, status: fiado_entity_1.FiadoStatus.PENDING },
{ tenantId, status: fiado_entity_1.FiadoStatus.PARTIAL },
],
relations: ['customer'],
order: { createdAt: 'ASC' },
});
}
async payFiado(tenantId, fiadoId, dto, userId) {
const fiado = await this.fiadoRepo.findOne({
where: { id: fiadoId, tenantId },
relations: ['customer'],
});
if (!fiado) {
throw new common_1.NotFoundException('Fiado no encontrado');
}
if (fiado.status === fiado_entity_1.FiadoStatus.PAID) {
throw new common_1.BadRequestException('Este fiado ya está pagado');
}
if (dto.amount > Number(fiado.remainingAmount)) {
throw new common_1.BadRequestException(`El monto excede el saldo pendiente: $${fiado.remainingAmount}`);
}
const payment = this.fiadoPaymentRepo.create({
fiadoId,
amount: dto.amount,
paymentMethod: dto.paymentMethod || 'cash',
notes: dto.notes,
receivedBy: userId,
});
await this.fiadoPaymentRepo.save(payment);
fiado.paidAmount = Number(fiado.paidAmount) + dto.amount;
fiado.remainingAmount = Number(fiado.remainingAmount) - dto.amount;
if (fiado.remainingAmount <= 0) {
fiado.status = fiado_entity_1.FiadoStatus.PAID;
fiado.paidAt = new Date();
}
else {
fiado.status = fiado_entity_1.FiadoStatus.PARTIAL;
}
await this.fiadoRepo.save(fiado);
const customer = fiado.customer;
customer.currentFiadoBalance = Number(customer.currentFiadoBalance) - dto.amount;
await this.customerRepo.save(customer);
return fiado;
}
async cancelFiado(tenantId, fiadoId) {
const fiado = await this.fiadoRepo.findOne({
where: { id: fiadoId, tenantId },
relations: ['customer'],
});
if (!fiado) {
throw new common_1.NotFoundException('Fiado no encontrado');
}
if (fiado.status === fiado_entity_1.FiadoStatus.PAID) {
throw new common_1.BadRequestException('No se puede cancelar un fiado pagado');
}
const customer = fiado.customer;
customer.currentFiadoBalance = Number(customer.currentFiadoBalance) - Number(fiado.remainingAmount);
await this.customerRepo.save(customer);
fiado.status = fiado_entity_1.FiadoStatus.CANCELLED;
return this.fiadoRepo.save(fiado);
}
async getCustomerStats(tenantId, customerId) {
const customer = await this.findOne(tenantId, customerId);
const pendingFiados = await this.fiadoRepo.count({
where: [
{ customerId, status: fiado_entity_1.FiadoStatus.PENDING },
{ customerId, status: fiado_entity_1.FiadoStatus.PARTIAL },
],
});
return {
customer,
stats: {
totalPurchases: customer.totalPurchases,
purchaseCount: customer.purchaseCount,
fiadoBalance: customer.currentFiadoBalance,
fiadoLimit: customer.fiadoLimit,
fiadoAvailable: Math.max(0, Number(customer.fiadoLimit) - Number(customer.currentFiadoBalance)),
pendingFiados,
},
};
}
};
exports.CustomersService = CustomersService;
exports.CustomersService = CustomersService = __decorate([
(0, common_1.Injectable)(),
__param(0, (0, typeorm_1.InjectRepository)(customer_entity_1.Customer)),
__param(1, (0, typeorm_1.InjectRepository)(fiado_entity_1.Fiado)),
__param(2, (0, typeorm_1.InjectRepository)(fiado_payment_entity_1.FiadoPayment)),
__metadata("design:paramtypes", [typeorm_2.Repository,
typeorm_2.Repository,
typeorm_2.Repository])
], CustomersService);
//# sourceMappingURL=customers.service.js.map