feat: add showPublicScores and showPublicOpinions flags to services with plan-based access control

This commit is contained in:
2026-07-22 14:05:39 -03:00
parent da3c3abb52
commit 279e1b54cc
19 changed files with 391 additions and 43 deletions
@@ -67,6 +67,8 @@ export class CompaniesAdapterMongoose implements ICompaniesAdapter {
fixedPostIds: { type: Array, required: false },
banned: { type: Boolean, required: false, default: false },
showPublicScores: { type: Boolean, required: false, default: true },
showPublicOpinions: { type: Boolean, required: false, default: true },
});
this.companyList = model<ICompanyDocument>("Company", this.schema);
@@ -235,6 +237,14 @@ export class CompaniesAdapterMongoose implements ICompaniesAdapter {
updateCompany.banned = data.banned;
}
if (data.showPublicScores !== undefined) {
updateCompany.showPublicScores = data.showPublicScores;
}
if (data.showPublicOpinions !== undefined) {
updateCompany.showPublicOpinions = data.showPublicOpinions;
}
updateCompany.save();
//actualizo los campos correspondientes a la localizacion de los servicios de la organizacion.
@@ -54,6 +54,8 @@ export type UpdateCompanyParams = {
onboardingStep?: number;
onboardingCompleted?: boolean;
banned?: boolean;
showPublicScores?: boolean;
showPublicOpinions?: boolean;
};
export type SetCompanyFileParams = {
@@ -154,6 +156,8 @@ export interface ICompany {
onboardingCompleted?: boolean;
fixedPostIds?: Array<string>;
banned?: boolean;
showPublicScores?: boolean;
showPublicOpinions?: boolean;
}
export interface MyOranizationsView {
@@ -203,6 +207,8 @@ export interface MyOranizationsView {
onboardingStep?: number;
onboardingCompleted?: boolean;
banned?: boolean;
showPublicScores?: boolean;
showPublicOpinions?: boolean;
}
export interface ClientOrganizationView {
+21
View File
@@ -67,6 +67,17 @@ class CompaniesManager implements ICompaniesManager {
this.companies = new CompaniesAdapterMongoose();
}
private async validatePublicRatingFlagsPlan(ownerId: string): Promise<void> {
const { default: PlanSubscriptionsList } = await import("../PlanSubscriptions/PlanSubscriptons");
const subscription = await PlanSubscriptionsList.getSubscriptionByUser({
sessionUser: ownerId,
});
if (!subscription || subscription.plan.price === 0) {
throw new Error("Esta configuración está disponible solo para planes pagos.");
}
}
public async toggleFixedPost(data: FixCompanyPostParams): Promise<void> {
await validateSessionUser({
sessionUser: data.sessionUser,
@@ -489,6 +500,10 @@ class CompaniesManager implements ICompaniesManager {
throw new Error(NoPermissionMessage());
}
if (data.showPublicScores !== undefined || data.showPublicOpinions !== undefined) {
await this.validatePublicRatingFlagsPlan(String(companyCheck.ownerId));
}
let updateData = {
...data,
};
@@ -597,6 +612,8 @@ class CompaniesManager implements ICompaniesManager {
templateEmailAltaId: isNull<string>(company.templateEmailAltaId, ""),
onboardingStep: company.onboardingStep,
onboardingCompleted: company.onboardingCompleted,
showPublicScores: company.showPublicScores ?? true,
showPublicOpinions: company.showPublicOpinions ?? true,
};
}
@@ -716,6 +733,8 @@ class CompaniesManager implements ICompaniesManager {
templateEmailAltaId: isNull<string>(company.templateEmailAltaId, ""),
onboardingStep: company.onboardingStep,
onboardingCompleted: company.onboardingCompleted,
showPublicScores: company.showPublicScores ?? true,
showPublicOpinions: company.showPublicOpinions ?? true,
});
}
@@ -786,6 +805,8 @@ class CompaniesManager implements ICompaniesManager {
templateEmailAltaId: isNull<string>(company.templateEmailAltaId, ""),
onboardingStep: company.onboardingStep,
onboardingCompleted: company.onboardingCompleted,
showPublicScores: company.showPublicScores ?? true,
showPublicOpinions: company.showPublicOpinions ?? true,
});
}
}
@@ -134,7 +134,7 @@ export class RatingsAdapterMongoose implements IRatingsAdapter {
targetId: new Types.ObjectId(filters.targetId),
comment: { $regex: /\S/ },
})
.sort({ createdAt: -1 })
.sort({ score: -1, createdAt: -1 })
.limit(filters.limit || 20)
.select("score comment createdAt userId")
.populate("userId", "firstName lastName avatar")
@@ -42,6 +42,8 @@ export class ServicesAdapterMongoose implements IServicesAdapter {
longitude: { type: Number, required: false, default: 0 },
published: { type: String, required: false },
banned: { type: Boolean, required: false, default: false },
showPublicScores: { type: Boolean, required: false, default: true },
showPublicOpinions: { type: Boolean, required: false, default: true },
});
this.serviceList = model<IServiceDocument>("Service", this.schema);
@@ -93,6 +95,8 @@ export class ServicesAdapterMongoose implements IServicesAdapter {
if (data.latitude) updateService.latitude = data.latitude;
if (data.longitude) updateService.longitude = data.longitude;
if (data.banned !== undefined) updateService.banned = data.banned;
if (data.showPublicScores !== undefined) updateService.showPublicScores = data.showPublicScores;
if (data.showPublicOpinions !== undefined) updateService.showPublicOpinions = data.showPublicOpinions;
await updateService.save();
}
@@ -57,6 +57,8 @@ export type CreateServiceParams = {
latitude?: number;
longitude?: number;
sessionUser: string;
showPublicScores?: boolean;
showPublicOpinions?: boolean;
};
export type UpdateServiceParams = {
@@ -81,6 +83,8 @@ export type UpdateServiceParams = {
longitude?: number;
sessionUser: string;
banned?: boolean;
showPublicScores?: boolean;
showPublicOpinions?: boolean;
};
export type PaginatePublicServicesParams = FindServicesParams & {
@@ -155,6 +159,8 @@ export interface IService {
published?: SERVICE_PUBLISHED_STATUS;
discountId?: string;
banned?: boolean;
showPublicScores?: boolean;
showPublicOpinions?: boolean;
}
export interface CompanyServiceView {
@@ -176,6 +182,8 @@ export interface CompanyServiceView {
fontShadowColor: string;
published: SERVICE_PUBLISHED_STATUS;
banned?: boolean;
showPublicScores: boolean;
showPublicOpinions: boolean;
}
export interface PublicServiceView {
@@ -199,6 +207,8 @@ export interface PublicServiceView {
fontColor: string;
fontShadowColor: string;
banned?: boolean;
showPublicScores: boolean;
showPublicOpinions: boolean;
}
export interface FindServicesByCompanyParams {
+25
View File
@@ -46,6 +46,17 @@ class ServiceManager implements IServicesManager {
this.services = new ServicesAdapterMongoose();
}
private async validatePublicRatingFlagsPlan(ownerId: string): Promise<void> {
const { default: PlanSubscriptionsList } = await import("../PlanSubscriptions/PlanSubscriptons");
const subscription = await PlanSubscriptionsList.getSubscriptionByUser({
sessionUser: ownerId,
});
if (!subscription || subscription.plan.price === 0) {
throw new Error("Esta configuración está disponible solo para planes pagos.");
}
}
public async setPublishedStatus(data: SetPublishedStatusParams): Promise<void> {
const sessionUser = await UsersManager.users.findOne({
_id: data.sessionUser,
@@ -145,6 +156,10 @@ class ServiceManager implements IServicesManager {
throw new Error("Ha alcanzado el limite de servicios permitidos de acuerdo a su plan.");
}
if (data.showPublicScores !== undefined || data.showPublicOpinions !== undefined) {
await this.validatePublicRatingFlagsPlan(String(companyCheck.ownerId));
}
const newService = await this.services.create({
...data,
...{
@@ -190,6 +205,10 @@ class ServiceManager implements IServicesManager {
throw new Error(NoPermissionMessage());
}
if (data.showPublicScores !== undefined || data.showPublicOpinions !== undefined) {
await this.validatePublicRatingFlagsPlan(String(companyCheck.ownerId));
}
await this.services.update(data);
}
@@ -307,6 +326,8 @@ class ServiceManager implements IServicesManager {
service.published,
SERVICE_PUBLISHED_STATUS.PRIVATE
),
showPublicScores: service.showPublicScores ?? true,
showPublicOpinions: service.showPublicOpinions ?? true,
});
}
@@ -363,6 +384,8 @@ class ServiceManager implements IServicesManager {
fontColor: isNull<string>(service.fontColor, defFontColor),
fontShadowColor: isNull<string>(service.fontShadowColor, defFontShadowColor),
published: isNull<SERVICE_PUBLISHED_STATUS>(service.published, SERVICE_PUBLISHED_STATUS.PRIVATE),
showPublicScores: service.showPublicScores ?? true,
showPublicOpinions: service.showPublicOpinions ?? true,
};
}
@@ -486,6 +509,8 @@ class ServiceManager implements IServicesManager {
color: isNull<string>(service.color, defColor),
fontColor: isNull<string>(service.fontColor, defFontColor),
fontShadowColor: isNull<string>(service.fontShadowColor, defFontShadowColor),
showPublicScores: service.showPublicScores ?? true,
showPublicOpinions: service.showPublicOpinions ?? true,
});
}
+4
View File
@@ -55,6 +55,8 @@ export type PublicOrganizationView = {
latitude: number;
longitude: number;
appointmentAlert: string;
showPublicScores: boolean;
showPublicOpinions: boolean;
};
export type PublicOrganizationServiceViewParams = {
@@ -163,6 +165,8 @@ class Views {
services,
employees: services,
appointmentAlert: isNull<string>(company.appointmentAlert, ""),
showPublicScores: company.showPublicScores ?? true,
showPublicOpinions: company.showPublicOpinions ?? true,
};
}