diff --git a/admin/src/app/professionals/[id]/page.tsx b/admin/src/app/professionals/[id]/page.tsx
index 135e42b..3960d67 100644
--- a/admin/src/app/professionals/[id]/page.tsx
+++ b/admin/src/app/professionals/[id]/page.tsx
@@ -23,7 +23,8 @@ interface Professional {
rate?: number; average_score?: number;
identification_picture?: string; certificate_picture?: string; banner_picture?: string;
users?: User; schedules?: Schedule[];
- specializations?: Specialization[]; payment_methods?: PaymentMethod[];
+ specializations?: Specialization[];
+ payment_methods?: PaymentMethod | PaymentMethod[] | null;
}
interface Service { id: string; description?: string; rate?: number; status: string; day: string; }
@@ -440,11 +441,12 @@ export default function ProfessionalDetailPage() {
banner_picture: 'Foto de perfil / Banner',
};
const url = professional[field];
+ const isImage = url && /\.(jpg|jpeg|png|webp|gif)(\?|$)/i.test(url);
return (
{labels[field]}
{url ? (
- url.match(/\.(jpg|jpeg|png|webp)$/i) ? (
+ isImage ? (
@@ -463,15 +465,19 @@ export default function ProfessionalDetailPage() {
{/* Métodos de pago */}
- {professional.payment_methods && professional.payment_methods.length > 0 && (
+ {professional.payment_methods && (
Métodos de pago aceptados
-
- {['nequi', 'datafono', 'transferencia']
- .filter((k) => (professional.payment_methods![0] as any)[k])
- .map((k) => {PAYMENT_LABELS[k]})}
-
+ {(() => {
+ const pm = Array.isArray(professional.payment_methods)
+ ? (professional.payment_methods as PaymentMethod[])[0]
+ : professional.payment_methods as PaymentMethod;
+ const active = pm ? ['nequi', 'datafono', 'transferencia'].filter((k) => (pm as any)[k]) : [];
+ return active.length > 0
+ ? {active.map((k) => {PAYMENT_LABELS[k]})}
+ : Ninguno configurado
;
+ })()}
)}
diff --git a/backend/src/professionals/dto/professional.dto.ts b/backend/src/professionals/dto/professional.dto.ts
index f5bf464..ef20a31 100644
--- a/backend/src/professionals/dto/professional.dto.ts
+++ b/backend/src/professionals/dto/professional.dto.ts
@@ -1,4 +1,4 @@
-import { IsString, IsOptional, IsArray, IsNumber, IsBoolean, MinLength, Matches } from 'class-validator';
+import { IsString, IsOptional, IsArray, IsNumber, IsBoolean, MinLength, Matches, IsObject } from 'class-validator';
export class CreateProfessionalDto {
@IsString()
@@ -80,6 +80,14 @@ export class UpdateProfessionalDto {
@IsOptional()
@IsString()
location_preferences?: string;
+
+ @IsOptional()
+ @IsObject()
+ payment_methods?: {
+ nequi?: boolean;
+ datafono?: boolean;
+ transferencia?: boolean;
+ };
}
export class ScheduleDto {
diff --git a/backend/src/professionals/professionals.service.ts b/backend/src/professionals/professionals.service.ts
index e555b14..57914a3 100644
--- a/backend/src/professionals/professionals.service.ts
+++ b/backend/src/professionals/professionals.service.ts
@@ -83,11 +83,21 @@ export class ProfessionalsService {
}
async upsert(userId: string, data: any) {
+ const { payment_methods: pm, ...profData } = data;
+
+ const buildPm = (forCreate = false) => {
+ if (!pm) return undefined;
+ const pmFields = { nequi: pm.nequi ?? false, datafono: pm.datafono ?? false, transferencia: pm.transferencia ?? false };
+ return forCreate ? { create: pmFields } : { upsert: { update: pmFields, create: pmFields } };
+ };
+
const existing = await this.prisma.professionals.findUnique({ where: { user_id: userId } });
if (!existing) {
await this.prisma.users.update({ where: { id: userId }, data: { pro_state: 1 } });
- const prof = await this.prisma.professionals.create({ data: { user_id: userId, is_active: false, ...data } });
+ const createData: any = { user_id: userId, is_active: false, ...profData };
+ if (pm) createData.payment_methods = buildPm(true);
+ const prof = await this.prisma.professionals.create({ data: createData });
const u = await this.prisma.users.findUnique({ where: { id: userId }, select: { name: true, email: true } });
if (u?.email) this.mail.sendProfessionalSubmitted(u.name || 'Usuario', u.email, data.profession || '').catch(() => {});
this.tryPush(userId, 'Solicitud recibida', 'Hemos recibido tu solicitud profesional. Te avisaremos cuando sea revisada.');
@@ -97,8 +107,10 @@ export class ProfessionalsService {
// Re-submitting after rejection reset (pro_state=0): move back to pending
const user = await this.prisma.users.findUnique({ where: { id: userId }, select: { pro_state: true, name: true, email: true } });
if (user?.pro_state === 0) {
+ const resubData: any = { ...profData, is_active: false };
+ if (pm) resubData.payment_methods = buildPm();
await this.prisma.$transaction([
- this.prisma.professionals.update({ where: { user_id: userId }, data: { ...data, is_active: false } }),
+ this.prisma.professionals.update({ where: { user_id: userId }, data: resubData }),
this.prisma.users.update({ where: { id: userId }, data: { pro_state: 1 } }),
]);
if (user.email) this.mail.sendProfessionalSubmitted(user.name || 'Usuario', user.email, data.profession || '').catch(() => {});
@@ -106,7 +118,9 @@ export class ProfessionalsService {
return this.prisma.professionals.findUnique({ where: { user_id: userId } });
}
- return this.prisma.professionals.update({ where: { user_id: userId }, data });
+ const updateData: any = { ...profData };
+ if (pm) updateData.payment_methods = buildPm();
+ return this.prisma.professionals.update({ where: { user_id: userId }, data: updateData });
}
async updateSchedules(professionalId: string, schedules: any[]) {