750 lines
26 KiB
TypeScript
750 lines
26 KiB
TypeScript
import { NoPermissionMessage } from "../../helpers/NoPermissionMessage";
|
|
import EmployeesList from "../Employees/Employee";
|
|
import { EmployeeRoles } from "../Employees/Employees.Interface";
|
|
import UserList from "../Users/Users";
|
|
import { IUserDocument } from "../Users/Users.Adapter.Mongoose";
|
|
import { PaymentsAdapterMongoose } from "./Payments.Adapter.Mongoose";
|
|
import {
|
|
CreatePaymentParams,
|
|
DeletePaymentParams,
|
|
DeletePaymentsByClientParams,
|
|
DeletePaymentsByCompanyParams,
|
|
FindPaymentsParams,
|
|
GetAppointmentPaymentsParams,
|
|
IPayment,
|
|
IPaymentsManager,
|
|
MarkAsPayedParams,
|
|
PaginateNotPayedAppointmentsParams,
|
|
PaginateNotPayedAppointmentsResult,
|
|
NotPayedReportResult,
|
|
PaginatePaymentsView,
|
|
PaginatePaymentsViewParams,
|
|
PaginatePaymentsViewResults,
|
|
PaymentsReportResult,
|
|
PAYMENT_METHODS_CLIENT_ACCOUNT,
|
|
PAYMENT_PROCCESS_DATE,
|
|
} from "./Payments.Interface";
|
|
import AppointmentList from "../Appointments/Appointments";
|
|
import {
|
|
CLIENT_ACCOUNT_MOVEMENT_STATUS,
|
|
CLIENT_ACCOUNT_MOVEMENT_TYPES,
|
|
CLIENT_ACCOUNT_PAYMENT_METHODS,
|
|
} from "../ClientAccountMovements/ClientAccountMovements.Interface";
|
|
import ClientsList from "../Clients/Clients";
|
|
import ServicesList from "../Services/Service";
|
|
import ClientAccount from "../ClientAccounts/ClientAccount";
|
|
import ClientAccountMovements from "../ClientAccountMovements/ClientAccountMovements";
|
|
import CashFlowBalance from "../CashFlowBalance/CashFlowBalance";
|
|
import dayjs from "dayjs";
|
|
import { FilterQuery } from "mongoose";
|
|
import { IAppointment } from "../Appointments/Appointments.Interface";
|
|
import PlanSubscriptionsList from "../PlanSubscriptions/PlanSubscriptons";
|
|
import CompaniesList from "../Companies/Companies";
|
|
import { PlanFeatures } from "../Plans/Plans.interface";
|
|
|
|
class PaymentsManager implements IPaymentsManager {
|
|
public async getPaymentsReport(
|
|
filters: FindPaymentsParams
|
|
): Promise<PaymentsReportResult> {
|
|
await this.validateSessionUser(((filters.sessionUser || "") || ""));
|
|
await this.validatePermissions(((filters.sessionUser || "") || ""), String(filters.companyId));
|
|
|
|
const results = await this.payments.find(filters);
|
|
// Sort descending by createdAt since find() in adapter doesn't sort by default
|
|
results.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
|
|
|
|
const contentData: PaginatePaymentsView[] = [];
|
|
let totalAmount = 0;
|
|
|
|
for (const pago of results) {
|
|
const appointment = await AppointmentList.Appointments.findOne({
|
|
_id: pago.appointmentId,
|
|
});
|
|
|
|
if (!appointment) continue;
|
|
|
|
const client = await ClientsList.clients.findOne({
|
|
_id: appointment.clientId,
|
|
});
|
|
|
|
if (!client) continue;
|
|
|
|
const employee = await EmployeesList.employees.findOne({
|
|
_id: appointment.employeeId,
|
|
});
|
|
|
|
if (!employee) continue;
|
|
|
|
const employeeUser = await UserList.users.findOne({
|
|
_id: String(employee.userId),
|
|
});
|
|
|
|
if (!employeeUser) continue;
|
|
|
|
const service = await ServicesList.services.findOne({
|
|
_id: appointment.serviceId,
|
|
});
|
|
|
|
const clientName = await ClientsList.getClientFullName(client);
|
|
const employeeName = await UserList.getUserFullName(employeeUser);
|
|
|
|
totalAmount += pago.amount;
|
|
|
|
contentData.push({
|
|
id: pago.id || "",
|
|
appointmentId: appointment.id,
|
|
appointmentDate: appointment.start as Date,
|
|
clientId: String(client._id),
|
|
clientName: clientName || "",
|
|
employeeId: employee?.id || "",
|
|
employeeName: employeeName || "",
|
|
serviceId: service?.id || "",
|
|
serviceName: service?.name || "",
|
|
price: pago.amount,
|
|
method: pago.method || "",
|
|
status: pago.status as any,
|
|
description: pago.description || "",
|
|
createdAt: pago.createdAt as Date,
|
|
});
|
|
}
|
|
|
|
return {
|
|
items: contentData,
|
|
totalAmount
|
|
};
|
|
}
|
|
|
|
payments: PaymentsAdapterMongoose;
|
|
|
|
constructor() {
|
|
this.payments = new PaymentsAdapterMongoose();
|
|
}
|
|
|
|
public async deletePaymentsByCompany(data: DeletePaymentsByCompanyParams): Promise<void> {
|
|
await this.payments.paymentsList.deleteMany({
|
|
companyId: data.companyId,
|
|
});
|
|
}
|
|
|
|
public async deletePaymentsByClient(data: DeletePaymentsByClientParams): Promise<void> {
|
|
await this.payments.paymentsList.deleteMany({
|
|
clientId: data.clientId,
|
|
});
|
|
}
|
|
|
|
public async paginatedPaymentsViewTotal(data: FindPaymentsParams): Promise<number> {
|
|
const pagos = await this.payments.find(data);
|
|
|
|
const pagosPrice = pagos.map((pago) => pago.amount);
|
|
return pagosPrice.reduce((previous, current) => current + previous, 0);
|
|
}
|
|
|
|
public async paginatePaymentsView(
|
|
data: PaginatePaymentsViewParams
|
|
): Promise<PaginatePaymentsViewResults> {
|
|
const userSession = await this.validateSessionUser((data.sessionUser || ""));
|
|
await this.validatePermissions(String(userSession.id), String(data.companyId));
|
|
|
|
const results: Array<PaginatePaymentsView> = [];
|
|
|
|
const pagos = await this.payments.paginate(data);
|
|
|
|
for (const pago of pagos.data) {
|
|
const appointment = await AppointmentList.Appointments.findOne({
|
|
_id: pago.appointmentId,
|
|
});
|
|
|
|
if (!appointment) {
|
|
continue;
|
|
}
|
|
|
|
const client = await ClientsList.clients.findOne({
|
|
_id: appointment.clientId,
|
|
});
|
|
|
|
if (!client) {
|
|
continue;
|
|
}
|
|
|
|
const employee = await EmployeesList.employees.findOne({
|
|
_id: appointment.employeeId,
|
|
});
|
|
|
|
if (!employee) {
|
|
continue;
|
|
}
|
|
|
|
const employeeUser = await UserList.users.findOne({
|
|
_id: String(employee.userId),
|
|
});
|
|
|
|
if (!employeeUser) {
|
|
continue;
|
|
}
|
|
|
|
const service = await ServicesList.services.findOne({
|
|
_id: appointment.serviceId,
|
|
});
|
|
|
|
if (!service) {
|
|
continue;
|
|
}
|
|
|
|
if (!pago._id) {
|
|
continue;
|
|
}
|
|
|
|
results.push({
|
|
id: String(pago.id),
|
|
appointmentId: String(pago.appointmentId),
|
|
appointmentDate: appointment.dateDay,
|
|
clientId: String(pago.clientId),
|
|
clientName: ClientsList.getClientFullName(client),
|
|
employeeId: String(pago.employeeId),
|
|
employeeName: UserList.getUserFullName(employeeUser),
|
|
serviceId: String(pago.serviceId),
|
|
serviceName: service.name,
|
|
price: Number(pago.amount),
|
|
status: pago.status,
|
|
method: pago.method || "",
|
|
description: pago.description,
|
|
createdAt: pago.createdAt,
|
|
});
|
|
}
|
|
|
|
return {
|
|
data: results,
|
|
page: data.page,
|
|
pages: pagos.pages,
|
|
};
|
|
}
|
|
|
|
private async validateSessionUser(sessionUserId: string): Promise<IUserDocument> {
|
|
const sessionUser = await UserList.users.findOne({
|
|
_id: sessionUserId,
|
|
});
|
|
|
|
if (!sessionUser) {
|
|
throw new Error(
|
|
"No se ha encontrado el usuario o no tiene permisos para realizar esta acción"
|
|
);
|
|
}
|
|
|
|
return sessionUser;
|
|
}
|
|
|
|
private async validatePermissions(sessionUserId: string, companyId: string): Promise<void> {
|
|
// Verificar si el usuario de sesión es un empleado con permisos de administrador
|
|
const hasAdminPermission = await EmployeesList.checkRoleById(
|
|
companyId,
|
|
sessionUserId,
|
|
EmployeeRoles.ADMIN
|
|
);
|
|
|
|
if (!hasAdminPermission) {
|
|
throw new Error(NoPermissionMessage());
|
|
}
|
|
|
|
const company = await CompaniesList.companies.findOne({
|
|
_id: companyId,
|
|
});
|
|
|
|
if (!company) {
|
|
throw new Error("No se ha encontrado la organización");
|
|
}
|
|
|
|
const canAccess = await PlanSubscriptionsList.checkFeature({
|
|
userId: String(company.ownerId),
|
|
feature: PlanFeatures.PAYMENTS,
|
|
});
|
|
|
|
if (!canAccess) {
|
|
throw new Error("La organizacion no tiene un plan que soporte el módulo de pagos");
|
|
}
|
|
}
|
|
|
|
private async getPayedAmount(appointmentId: string): Promise<number> {
|
|
const payments = await this.payments.find({
|
|
appointmentId: appointmentId,
|
|
});
|
|
|
|
const payedAmount = payments.reduce((acc, payment) => acc + payment.amount, 0);
|
|
|
|
return payedAmount;
|
|
}
|
|
|
|
public async createPayment(data: CreatePaymentParams): Promise<IPayment> {
|
|
const userSession = await this.validateSessionUser((data.sessionUser || ""));
|
|
|
|
const appointment = await AppointmentList.Appointments.findOne({
|
|
_id: data.appointmentId,
|
|
});
|
|
|
|
if (!appointment) {
|
|
throw new Error("No se encontró la reserva");
|
|
}
|
|
|
|
if (appointment.payment) {
|
|
throw new Error("La reserva ya fue pagada");
|
|
}
|
|
|
|
await this.validatePermissions(String(userSession.id), String(appointment.companyId));
|
|
|
|
const toPayAmount = appointment.price;
|
|
const payedAmount = await this.getPayedAmount(data.appointmentId);
|
|
const remainingAmount = toPayAmount - payedAmount;
|
|
|
|
if (remainingAmount <= 0) {
|
|
throw new Error("La reserva ya está pagada");
|
|
}
|
|
|
|
if (data.amount > remainingAmount) {
|
|
throw new Error("El monto del pago no puede ser mayor al monto restante");
|
|
}
|
|
|
|
if (data.amount <= 0) {
|
|
throw new Error("El monto del pago no puede ser menor o igual a 0");
|
|
}
|
|
|
|
let availableClientAccountAmount = 0;
|
|
|
|
if (data.method == PAYMENT_METHODS_CLIENT_ACCOUNT.CLIENT_ACCOUNT) {
|
|
availableClientAccountAmount = await ClientAccount.getAvailableAmount({
|
|
clientId: String(appointment.clientId),
|
|
sessionUser: (data.sessionUser || ""),
|
|
});
|
|
|
|
if (availableClientAccountAmount < data.amount) {
|
|
throw new Error("El saldo de la cuenta del cliente no es suficiente");
|
|
}
|
|
}
|
|
|
|
let proccessDate = new Date();
|
|
|
|
if (data.proccessDate == PAYMENT_PROCCESS_DATE.NOW) {
|
|
proccessDate = new Date();
|
|
} else if (data.proccessDate == PAYMENT_PROCCESS_DATE.APPOINTMENT) {
|
|
proccessDate = new Date(appointment.start);
|
|
}
|
|
|
|
const payment = await this.payments.create({
|
|
...data,
|
|
clientId: String(appointment.clientId),
|
|
companyId: String(appointment.companyId),
|
|
employeeId: String(appointment.employeeId),
|
|
serviceId: String(appointment.serviceId),
|
|
...{ createdAt: proccessDate },
|
|
});
|
|
|
|
const eventData = await AppointmentList.getAppointmentEvent({
|
|
appointmentId: data.appointmentId,
|
|
sessionUser: (data.sessionUser || ""),
|
|
});
|
|
|
|
const reservaDesc =
|
|
eventData.title +
|
|
" - " +
|
|
eventData.serviceName +
|
|
" (" +
|
|
eventData.collaboratorName +
|
|
")";
|
|
|
|
//si el pago es con cuenta de cliente, se debe descontar el dinero de la cuenta del cliente
|
|
if (data.method == PAYMENT_METHODS_CLIENT_ACCOUNT.CLIENT_ACCOUNT) {
|
|
await ClientAccountMovements.add({
|
|
clientId: String(appointment.clientId),
|
|
amount: data.amount,
|
|
description: reservaDesc,
|
|
sessionUser: (data.sessionUser || ""),
|
|
type: CLIENT_ACCOUNT_MOVEMENT_TYPES.WITHDRAWAL,
|
|
status: CLIENT_ACCOUNT_MOVEMENT_STATUS.APPROVED,
|
|
paymentMethod: CLIENT_ACCOUNT_PAYMENT_METHODS.CASH,
|
|
});
|
|
}
|
|
|
|
if (remainingAmount === data.amount) {
|
|
await AppointmentList.setPaymentStatus({
|
|
appointmentId: data.appointmentId,
|
|
status: true,
|
|
sessionUser: (data.sessionUser || ""),
|
|
});
|
|
}
|
|
|
|
//Creamos el movimiento de caja si es un pago que no viene de la cuenta corriente del cliente.
|
|
if (data.method != PAYMENT_METHODS_CLIENT_ACCOUNT.CLIENT_ACCOUNT) {
|
|
const paymentDate = dayjs(payment.createdAt);
|
|
const paymentYear = paymentDate.year();
|
|
const paymentMonth = paymentDate.month();
|
|
await CashFlowBalance.createCashFlowMovement({
|
|
amount: data.amount,
|
|
description: reservaDesc,
|
|
year: paymentYear,
|
|
month: paymentMonth,
|
|
companyId: String(appointment.companyId),
|
|
paymentId: String(payment._id),
|
|
employeeId: String(appointment.employeeId),
|
|
clientId: String(appointment.clientId),
|
|
appointmentId: String(appointment._id),
|
|
paymentMethod: data.method,
|
|
reference: "",
|
|
type: CLIENT_ACCOUNT_MOVEMENT_TYPES.DEPOSIT,
|
|
proccessDate: data.proccessDate,
|
|
sessionUser: (data.sessionUser || ""),
|
|
});
|
|
}
|
|
|
|
return payment;
|
|
}
|
|
|
|
public async markAsPayed(data: MarkAsPayedParams): Promise<void> {
|
|
const userSession = await this.validateSessionUser((data.sessionUser || ""));
|
|
|
|
const appointment = await AppointmentList.Appointments.findOne({
|
|
_id: data.appointmentId,
|
|
});
|
|
|
|
if (!appointment) {
|
|
throw new Error("No se encontró la reserva");
|
|
}
|
|
|
|
await this.validatePermissions(String(userSession.id), String(appointment.companyId));
|
|
|
|
const toPayAmount = appointment.price;
|
|
const payedAmount = await this.getPayedAmount(data.appointmentId);
|
|
const remainingAmount = toPayAmount - payedAmount;
|
|
|
|
if (remainingAmount == 0) {
|
|
throw new Error("La reserva ya está pagada");
|
|
}
|
|
|
|
await this.createPayment({
|
|
appointmentId: data.appointmentId,
|
|
amount: remainingAmount,
|
|
status: CLIENT_ACCOUNT_MOVEMENT_STATUS.APPROVED,
|
|
description: "Pago total de la reserva",
|
|
method: data.method,
|
|
proccessDate: PAYMENT_PROCCESS_DATE.NOW,
|
|
sessionUser: (data.sessionUser || ""),
|
|
});
|
|
}
|
|
|
|
public async deletePayment(data: DeletePaymentParams): Promise<void> {
|
|
await this.validateSessionUser((data.sessionUser || ""));
|
|
|
|
// Primero buscamos el movimiento por su ID
|
|
const payment = await this.payments.paymentsList.findOne({
|
|
_id: String(data.id),
|
|
});
|
|
|
|
if (!payment) {
|
|
throw new Error("No se encontró el pago");
|
|
}
|
|
|
|
await this.validatePermissions((data.sessionUser || ""), payment.companyId);
|
|
|
|
const appointment = await AppointmentList.Appointments.findOne({
|
|
_id: payment.appointmentId,
|
|
});
|
|
|
|
if (!appointment) {
|
|
throw new Error("No se encontró la reserva");
|
|
}
|
|
|
|
const toPayAmount = appointment.price;
|
|
const payedAmount = await this.getPayedAmount(payment.appointmentId);
|
|
const remainingAmount = toPayAmount - (payedAmount - payment.amount);
|
|
|
|
//si el pago es con cuenta de cliente, se debe agregar el dinero a la cuenta del cliente
|
|
if (payment.method == PAYMENT_METHODS_CLIENT_ACCOUNT.CLIENT_ACCOUNT) {
|
|
await ClientAccountMovements.add({
|
|
clientId: String(appointment.clientId),
|
|
amount: payment.amount,
|
|
description: "Reembolso de la reserva - " + appointment.id,
|
|
sessionUser: (data.sessionUser || ""),
|
|
type: CLIENT_ACCOUNT_MOVEMENT_TYPES.DEPOSIT,
|
|
status: CLIENT_ACCOUNT_MOVEMENT_STATUS.APPROVED,
|
|
paymentMethod: CLIENT_ACCOUNT_PAYMENT_METHODS.CASH,
|
|
});
|
|
}
|
|
|
|
//Si el pago que se borra no viene de la cuenta del cliente, borramos el movimiento de la caja.
|
|
if (payment.method != PAYMENT_METHODS_CLIENT_ACCOUNT.CLIENT_ACCOUNT) {
|
|
await CashFlowBalance.deleteByPayment({
|
|
companyId: String(appointment.companyId),
|
|
paymentId: String(payment._id),
|
|
sessionUser: (data.sessionUser || ""),
|
|
});
|
|
}
|
|
|
|
await this.payments.delete(data.id);
|
|
|
|
if (remainingAmount > 0) {
|
|
await AppointmentList.setPaymentStatus({
|
|
appointmentId: String(appointment._id),
|
|
status: false,
|
|
sessionUser: (data.sessionUser || ""),
|
|
});
|
|
}
|
|
}
|
|
|
|
public async getAppointmentPayments(data: GetAppointmentPaymentsParams): Promise<IPayment[]> {
|
|
await this.validateSessionUser((data.sessionUser || ""));
|
|
|
|
const appointment = await AppointmentList.Appointments.findOne({
|
|
_id: data.appointmentId,
|
|
});
|
|
|
|
if (!appointment) {
|
|
throw new Error("No se encontró la reserva");
|
|
}
|
|
|
|
await this.validatePermissions((data.sessionUser || ""), String(appointment.companyId));
|
|
|
|
return await this.payments.find({
|
|
appointmentId: data.appointmentId,
|
|
});
|
|
}
|
|
|
|
private getNotPayedSearchCriteria(filters: FindPaymentsParams): FilterQuery<IAppointment> {
|
|
const searchCriteria: FilterQuery<IAppointment> = {};
|
|
|
|
if (filters.startDate) {
|
|
searchCriteria.start = {
|
|
$gte: filters.startDate,
|
|
$lte: filters.endDate,
|
|
};
|
|
}
|
|
|
|
searchCriteria.payment = false;
|
|
|
|
if (filters.clientIds && filters.clientIds.length > 0) {
|
|
searchCriteria.clientId = { $in: filters.clientIds };
|
|
} else if (filters.clientId) {
|
|
searchCriteria.clientId = filters.clientId;
|
|
}
|
|
|
|
if (filters.method) {
|
|
searchCriteria.method = filters.method;
|
|
}
|
|
|
|
if (filters.companyId) {
|
|
searchCriteria.companyId = filters.companyId;
|
|
}
|
|
|
|
if (filters.employeeId) {
|
|
searchCriteria.employeeId = filters.employeeId;
|
|
}
|
|
|
|
if (filters.serviceId) {
|
|
searchCriteria.serviceId = filters.serviceId;
|
|
}
|
|
|
|
return searchCriteria;
|
|
}
|
|
|
|
public async paginateNotPayedAppointments(
|
|
filters: PaginateNotPayedAppointmentsParams
|
|
): Promise<PaginateNotPayedAppointmentsResult> {
|
|
await this.validateSessionUser(((filters.sessionUser || "") || ""));
|
|
await this.validatePermissions(((filters.sessionUser || "") || ""), String(filters.companyId));
|
|
|
|
const searchCriteria = this.getNotPayedSearchCriteria(filters);
|
|
|
|
const count = await AppointmentList.Appointments.AppointmentList.countDocuments(
|
|
searchCriteria
|
|
).exec();
|
|
const skip = (filters.page - 1) * filters.limit;
|
|
|
|
const results = await AppointmentList.Appointments.AppointmentList.find(searchCriteria)
|
|
.skip(skip)
|
|
.limit(filters.limit)
|
|
.sort({ start: -1 })
|
|
.exec();
|
|
|
|
const contentData: PaginatePaymentsView[] = [];
|
|
|
|
for (const item of results) {
|
|
const client = await ClientsList.clients.findOne({
|
|
_id: item.clientId,
|
|
});
|
|
|
|
const employee = await EmployeesList.employees.findOne({
|
|
_id: item.employeeId,
|
|
});
|
|
|
|
const service = await ServicesList.services.findOne({
|
|
_id: item.serviceId,
|
|
});
|
|
|
|
if (!client) {
|
|
continue;
|
|
}
|
|
|
|
if (!employee) {
|
|
continue;
|
|
}
|
|
|
|
if (!service) {
|
|
continue;
|
|
}
|
|
|
|
const employeeUser = await UserList.users.findOne({
|
|
_id: String(employee.userId),
|
|
});
|
|
|
|
if (!employeeUser) {
|
|
continue;
|
|
}
|
|
|
|
const clientName = await ClientsList.getClientFullName(client);
|
|
const employeeName = await UserList.getUserFullName(employeeUser);
|
|
|
|
contentData.push({
|
|
id: item.id,
|
|
appointmentId: item.id,
|
|
appointmentDate: item.start,
|
|
clientId: item.clientId,
|
|
clientName: clientName || "",
|
|
employeeId: item.employeeId,
|
|
employeeName: employeeName || "",
|
|
serviceId: item.serviceId,
|
|
serviceName: service.name,
|
|
price: item.price,
|
|
status: CLIENT_ACCOUNT_MOVEMENT_STATUS.PENDING,
|
|
method: CLIENT_ACCOUNT_PAYMENT_METHODS.OTHER,
|
|
description: "",
|
|
createdAt: item.start,
|
|
});
|
|
}
|
|
|
|
let pages = Math.ceil(count / filters.limit);
|
|
|
|
if (pages < 1) {
|
|
pages = 1;
|
|
}
|
|
|
|
return {
|
|
data: contentData,
|
|
page: filters.page,
|
|
pages: pages,
|
|
};
|
|
}
|
|
|
|
public async paginatedNotPayedAppiontmentsTotal(data: FindPaymentsParams): Promise<number> {
|
|
await this.validateSessionUser((data.sessionUser || ""));
|
|
await this.validatePermissions((data.sessionUser || ""), String(data.companyId));
|
|
const searchCriteria = this.getNotPayedSearchCriteria(data);
|
|
const pagos = await AppointmentList.Appointments.AppointmentList.find(searchCriteria);
|
|
return pagos.reduce((previous, current) => current.price + previous, 0);
|
|
}
|
|
|
|
|
|
public async getNotPayedReport(
|
|
filters: FindPaymentsParams
|
|
): Promise<NotPayedReportResult> {
|
|
await this.validateSessionUser(((filters.sessionUser || "") || ""));
|
|
await this.validatePermissions(((filters.sessionUser || "") || ""), String(filters.companyId));
|
|
|
|
const searchCriteria = this.getNotPayedSearchCriteria(filters);
|
|
|
|
const results = await AppointmentList.Appointments.AppointmentList.find(searchCriteria)
|
|
.sort({ start: -1 })
|
|
.exec();
|
|
|
|
const contentData: PaginatePaymentsView[] = [];
|
|
let totalAmount = 0;
|
|
|
|
for (const item of results) {
|
|
const client = await ClientsList.clients.findOne({
|
|
_id: item.clientId,
|
|
});
|
|
|
|
const employee = await EmployeesList.employees.findOne({
|
|
_id: item.employeeId,
|
|
});
|
|
|
|
const service = await ServicesList.services.findOne({
|
|
_id: item.serviceId,
|
|
});
|
|
|
|
if (!client || !employee || !service) {
|
|
continue;
|
|
}
|
|
|
|
const employeeUser = await UserList.users.findOne({
|
|
_id: String(employee.userId),
|
|
});
|
|
|
|
if (!employeeUser) {
|
|
continue;
|
|
}
|
|
|
|
const clientName = await ClientsList.getClientFullName(client);
|
|
const employeeName = await UserList.getUserFullName(employeeUser);
|
|
|
|
contentData.push({
|
|
id: item.id,
|
|
appointmentId: item.id,
|
|
appointmentDate: item.start,
|
|
clientId: item.clientId,
|
|
clientName: clientName || "",
|
|
employeeId: item.employeeId,
|
|
employeeName: employeeName || "",
|
|
serviceId: item.serviceId,
|
|
serviceName: service.name,
|
|
price: item.price,
|
|
status: CLIENT_ACCOUNT_MOVEMENT_STATUS.PENDING,
|
|
method: CLIENT_ACCOUNT_PAYMENT_METHODS.OTHER,
|
|
description: "",
|
|
createdAt: item.start,
|
|
});
|
|
|
|
totalAmount += item.price;
|
|
}
|
|
|
|
return {
|
|
items: contentData,
|
|
totalAmount: totalAmount,
|
|
};
|
|
}
|
|
|
|
public async payNotPayedAppointments(data: FindPaymentsParams): Promise<void> {
|
|
await this.validateSessionUser((data.sessionUser || ""));
|
|
await this.validatePermissions((data.sessionUser || ""), String(data.companyId));
|
|
const { method, ...searchCriteria } = this.getNotPayedSearchCriteria(data); //Estraigo la propiedad method de searchCriteria
|
|
const toPayAppointments = await AppointmentList.Appointments.AppointmentList.find(
|
|
searchCriteria
|
|
);
|
|
|
|
if (!method) {
|
|
throw new Error("No se ha especidicado un método de pago");
|
|
}
|
|
|
|
if (!data.proccessDate) {
|
|
throw new Error("No se ha especidicado una fecha de pago");
|
|
}
|
|
|
|
for (const item of toPayAppointments) {
|
|
try {
|
|
if (dayjs(item.dateDay).isAfter(dayjs())) {
|
|
continue; // No se pueden pagar reservas futuras de forma masiva.
|
|
}
|
|
|
|
await this.createPayment({
|
|
appointmentId: item.id,
|
|
method: method,
|
|
status: CLIENT_ACCOUNT_MOVEMENT_STATUS.APPROVED,
|
|
description: "Pago completo de la reserva",
|
|
amount: item.price,
|
|
proccessDate: data.proccessDate,
|
|
sessionUser: (data.sessionUser || ""),
|
|
});
|
|
} catch (e) {
|
|
console.log(e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
export default new PaymentsManager();
|