first commit
This commit is contained in:
@@ -0,0 +1,749 @@
|
||||
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();
|
||||
Reference in New Issue
Block a user