Merge branch 'paritosh' of http://git.wdipl.com/Mayank.Mishra/MinglarBackendNestJS into mayank
This commit is contained in:
@@ -208,6 +208,22 @@ functions:
|
||||
path: /host/get-pqq-question-details
|
||||
method: get
|
||||
|
||||
getActivityTypes:
|
||||
handler: src/modules/host/handlers/getActivity.handler
|
||||
package:
|
||||
patterns:
|
||||
- 'src/modules/host/handlers/getActivity.*'
|
||||
- 'src/modules/host/services/**'
|
||||
- 'common/**'
|
||||
- 'src/common/**'
|
||||
- 'node_modules/@prisma/client/**'
|
||||
- 'node_modules/.prisma/**'
|
||||
|
||||
events:
|
||||
- httpApi:
|
||||
path: /host/get-activity
|
||||
method: get
|
||||
|
||||
acceptMinglarAgreement:
|
||||
handler: src/modules/host/handlers/acceptAgreement.handler
|
||||
package:
|
||||
@@ -457,6 +473,21 @@ functions:
|
||||
path: /prepopulate/get-all-pqq-ques-ans
|
||||
method: get
|
||||
|
||||
getFrequenciesOfActivity:
|
||||
handler: src/modules/prepopulate/handlers/getAllFrequencies.handler
|
||||
package:
|
||||
patterns:
|
||||
- 'src/modules/minglaradmin/**'
|
||||
- 'common/**'
|
||||
- 'src/common/**'
|
||||
- 'node_modules/@prisma/client/**'
|
||||
- 'node_modules/.prisma/**'
|
||||
|
||||
events:
|
||||
- httpApi:
|
||||
path: /prepopulate/get-all-Frequencies
|
||||
method: get
|
||||
|
||||
assignAMToHost:
|
||||
handler: src/modules/minglaradmin/handlers/assignAM.handler
|
||||
package:
|
||||
|
||||
47
src/modules/host/handlers/getActivity.ts
Normal file
47
src/modules/host/handlers/getActivity.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { verifyHostToken } from '@/common/middlewares/jwt/authForHost';
|
||||
import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda';
|
||||
import { PrismaService } from '../../../common/database/prisma.service';
|
||||
import { safeHandler } from '../../../common/utils/handlers/safeHandler';
|
||||
import ApiError from '../../../common/utils/helper/ApiError';
|
||||
import { HostService } from '../services/host.service';
|
||||
|
||||
const prismaService = new PrismaService();
|
||||
const hostService = new HostService(prismaService);
|
||||
|
||||
/**
|
||||
* Add suggestion handler for host applications
|
||||
* Allows Minglar Admin, Co_Admin, and Account Manager to add suggestions
|
||||
* Types: Setup Profile, Review Account, Add Payment Details, Agreement
|
||||
*/
|
||||
export const handler = safeHandler(async (
|
||||
event: APIGatewayProxyEvent,
|
||||
context?: Context
|
||||
): Promise<APIGatewayProxyResult> => {
|
||||
// Verify authentication token
|
||||
const token = event.headers['x-auth-token'] || event.headers['X-Auth-Token'];
|
||||
if (!token) {
|
||||
throw new ApiError(401, 'This is a protected route. Please provide a valid token.');
|
||||
}
|
||||
|
||||
// Verify token and get user info
|
||||
const userInfo = await verifyHostToken(token);
|
||||
|
||||
|
||||
// Read optional search query (supports ?search= or ?q=)
|
||||
const search = event.queryStringParameters?.search || event.queryStringParameters?.q || undefined;
|
||||
|
||||
const data = await hostService.getAllActivityTypesWithInterest(search);
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
success: true,
|
||||
message: 'Data retrieved successfully',
|
||||
data,
|
||||
}),
|
||||
};
|
||||
});
|
||||
@@ -607,4 +607,36 @@ export class HostService {
|
||||
});
|
||||
}
|
||||
|
||||
async getAllActivityTypesWithInterest(search?: string) {
|
||||
const where: any = {
|
||||
isActive: true,
|
||||
deletedAt: null,
|
||||
};
|
||||
|
||||
if (search && search.trim() !== '') {
|
||||
const q = search.trim();
|
||||
where.OR = [
|
||||
{ activityTypeName: { contains: q, mode: 'insensitive' } },
|
||||
{ interests: { interestName: { contains: q, mode: 'insensitive' } } },
|
||||
];
|
||||
}
|
||||
|
||||
return await this.prisma.activityTypes.findMany({
|
||||
where,
|
||||
select: {
|
||||
id: true,
|
||||
activityTypeName: true,
|
||||
interestXid: true,
|
||||
interests: {
|
||||
select: {
|
||||
id: true,
|
||||
interestName: true,
|
||||
displayOrder: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: { activityTypeName: 'asc' },
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,31 +1,41 @@
|
||||
import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda';
|
||||
import {
|
||||
APIGatewayProxyEvent,
|
||||
APIGatewayProxyResult,
|
||||
Context,
|
||||
} from 'aws-lambda';
|
||||
import { safeHandler } from '../../../common/utils/handlers/safeHandler';
|
||||
import { PrismaService } from '../../../common/database/prisma.service';
|
||||
import { MinglarService } from '../services/minglar.service';
|
||||
import ApiError from '../../../common/utils/helper/ApiError';
|
||||
import { verifyMinglarAdminToken } from '../../../common/middlewares/jwt/authForMinglarAdmin';
|
||||
import { verifyOnlyMinglarAdminToken } from '@/common/middlewares/jwt/authForOnlyMinglarAdmin';
|
||||
import { sendAMEmailForHostAssign } from '../services/AMEmail.service';
|
||||
|
||||
const prismaService = new PrismaService();
|
||||
const minglarService = new MinglarService(prismaService);
|
||||
|
||||
interface assignAMToHostBody {
|
||||
host_xid: number;
|
||||
account_manager_xid: number;
|
||||
}
|
||||
host_xid: number;
|
||||
account_manager_xid: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all host applications handler
|
||||
* Returns host details with status, submission date, and account manager info
|
||||
*/
|
||||
export const handler = safeHandler(async (
|
||||
export const handler = safeHandler(
|
||||
async (
|
||||
event: APIGatewayProxyEvent,
|
||||
context?: Context
|
||||
): Promise<APIGatewayProxyResult> => {
|
||||
context?: Context,
|
||||
): Promise<APIGatewayProxyResult> => {
|
||||
// Verify authentication token
|
||||
const token = event.headers['x-auth-token'] || event.headers['X-Auth-Token'];
|
||||
const token =
|
||||
event.headers['x-auth-token'] || event.headers['X-Auth-Token'];
|
||||
if (!token) {
|
||||
throw new ApiError(401, 'This is a protected route. Please provide a valid token.');
|
||||
throw new ApiError(
|
||||
401,
|
||||
'This is a protected route. Please provide a valid token.',
|
||||
);
|
||||
}
|
||||
|
||||
// Verify token and get user info
|
||||
@@ -33,40 +43,44 @@ export const handler = safeHandler(async (
|
||||
|
||||
// Get user details including role
|
||||
const user = await prismaService.user.findUnique({
|
||||
where: { id: userInfo.id },
|
||||
select: { id: true, roleXid: true }
|
||||
where: { id: userInfo.id },
|
||||
select: { id: true, roleXid: true },
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
throw new ApiError(404, 'User not found');
|
||||
throw new ApiError(404, 'User not found');
|
||||
}
|
||||
|
||||
// Parse request body
|
||||
let body: assignAMToHostBody;
|
||||
|
||||
try {
|
||||
body = event.body ? JSON.parse(event.body) : {};
|
||||
body = event.body ? JSON.parse(event.body) : {};
|
||||
} catch (error) {
|
||||
throw new ApiError(400, 'Invalid JSON in request body');
|
||||
throw new ApiError(400, 'Invalid JSON in request body');
|
||||
}
|
||||
|
||||
const {
|
||||
host_xid,
|
||||
account_manager_xid
|
||||
} = body;
|
||||
const { host_xid, account_manager_xid } = body;
|
||||
|
||||
// Get all host applications from service based on user role
|
||||
await minglarService.assignAMToHost(user.id, host_xid, account_manager_xid);
|
||||
|
||||
try {
|
||||
await minglarService.notifyAMOfAssignment(account_manager_xid);
|
||||
} catch (err) {
|
||||
console.error('Failed to notify AM after assignment:', err);
|
||||
}
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
success: true,
|
||||
message: 'AM assigned to host successfully',
|
||||
}),
|
||||
statusCode: 200,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
success: true,
|
||||
message: 'AM assigned to host successfully',
|
||||
}),
|
||||
};
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
37
src/modules/minglaradmin/services/AMEmail.service.ts
Normal file
37
src/modules/minglaradmin/services/AMEmail.service.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
// ...existing code...
|
||||
import { brevoService } from '@/common/email/brevoApi';
|
||||
import ApiError from '@/common/utils/helper/ApiError';
|
||||
|
||||
export async function sendAMEmailForHostAssign(emailAddress: string): Promise<{
|
||||
sent: boolean;
|
||||
// messageId: string
|
||||
}> {
|
||||
const subject = 'Minglar Admin: Host Assignment Notification';
|
||||
|
||||
const htmlContent = `
|
||||
<p>Hi,</p>
|
||||
|
||||
<p>You’ve been assigned the <strong>Host</strong> role by Minglar Admin.</p>
|
||||
|
||||
<p>Best regards,<br/>Minglar Admin Team</p>
|
||||
`;
|
||||
|
||||
try {
|
||||
const result = await brevoService.sendEmail({
|
||||
recipients: [{ email: emailAddress }],
|
||||
subject,
|
||||
htmlContent,
|
||||
});
|
||||
|
||||
console.log('📧 Email sent successfully:', result);
|
||||
|
||||
return {
|
||||
sent: true,
|
||||
// messageId: result.messageId
|
||||
};
|
||||
} catch (err) {
|
||||
console.error('Brevo email send failed:', err);
|
||||
throw new ApiError(500, 'Failed to send invitation via email.');
|
||||
}
|
||||
}
|
||||
// ...existing code...
|
||||
34
src/modules/minglaradmin/services/amNotification.service.ts
Normal file
34
src/modules/minglaradmin/services/amNotification.service.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { PrismaService } from '../../../common/database/prisma.service';
|
||||
import { sendAMEmailForHostAssign } from './AMEmail.service';
|
||||
|
||||
@Injectable()
|
||||
export class AMNotificationService {
|
||||
constructor(private prisma: PrismaService) {}
|
||||
|
||||
/**
|
||||
* Fetch account manager email by id and send assignment email.
|
||||
* Returns true if email was attempted (sent or attempted), false if AM missing or no email.
|
||||
*/
|
||||
async notifyAMOfAssignment(accountManagerXid: number, hostXid?: number): Promise<boolean> {
|
||||
if (!accountManagerXid) return false;
|
||||
|
||||
const amUser = await this.prisma.user.findUnique({
|
||||
where: { id: accountManagerXid },
|
||||
select: { emailAddress: true, firstName: true, lastName: true },
|
||||
});
|
||||
|
||||
if (!amUser || !amUser.emailAddress) {
|
||||
console.warn(`AM notification skipped: user not found or missing email for id=${accountManagerXid}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
await sendAMEmailForHostAssign(amUser.emailAddress);
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.error('Error sending AM assignment email', err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import * as bcrypt from 'bcryptjs';
|
||||
import { PrismaService } from '../../../common/database/prisma.service';
|
||||
import ApiError from '../../../common/utils/helper/ApiError';
|
||||
import { CreateMinglarDto, UpdateMinglarDto } from '../dto/minglar.dto';
|
||||
import { sendAMEmailForHostAssign } from './AMEmail.service';
|
||||
|
||||
|
||||
@Injectable()
|
||||
@@ -653,6 +654,32 @@ export class MinglarService {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify Account Manager by email after assignment.
|
||||
* Encapsulates lookup + email send so handlers can call a single method.
|
||||
*/
|
||||
async notifyAMOfAssignment(accountManagerXid: number): Promise<boolean> {
|
||||
if (!accountManagerXid) return false;
|
||||
|
||||
const amUser = await this.prisma.user.findUnique({
|
||||
where: { id: accountManagerXid ,isActive:true},
|
||||
select: { emailAddress: true},
|
||||
});
|
||||
|
||||
if (!amUser || !amUser.emailAddress) {
|
||||
console.warn(`AM notification skipped: user not found or missing email for id=${accountManagerXid}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
await sendAMEmailForHostAssign(amUser.emailAddress);
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.error('Error sending AM assignment email', err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async addHostSuggestion(hostXid: number, title: string, comments: string, reviewedByXid: number) {
|
||||
// Check if host exists
|
||||
const hostHeader = await this.prisma.hostHeader.findUnique({
|
||||
|
||||
39
src/modules/prepopulate/handlers/getAllFrequencies.ts
Normal file
39
src/modules/prepopulate/handlers/getAllFrequencies.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { verifyOnlyMinglarAdminToken } from '@/common/middlewares/jwt/authForOnlyMinglarAdmin';
|
||||
import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda';
|
||||
import { PrismaService } from '../../../common/database/prisma.service';
|
||||
import { safeHandler } from '../../../common/utils/handlers/safeHandler';
|
||||
import ApiError from '../../../common/utils/helper/ApiError';
|
||||
import { PrePopulateService } from '../services/prepopulate.service';
|
||||
import { verifyHostToken } from '@/common/middlewares/jwt/authForHost';
|
||||
|
||||
const prismaService = new PrismaService();
|
||||
const prePopulateService = new PrePopulateService(prismaService);
|
||||
|
||||
export const handler = safeHandler(async (
|
||||
event: APIGatewayProxyEvent,
|
||||
context?: Context
|
||||
): Promise<APIGatewayProxyResult> => {
|
||||
// Extract token from headers
|
||||
const token = event.headers['x-auth-token'] || event.headers['X-Auth-Token']
|
||||
if (!token) {
|
||||
throw new ApiError(400, 'This is a protected route. Please provide a valid token.');
|
||||
}
|
||||
|
||||
// Authenticate user using the shared authForHost function
|
||||
await verifyHostToken(token);
|
||||
|
||||
const result = await prePopulateService.getAllFrequencies();
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
success: true,
|
||||
message: 'Data retrieved successfully',
|
||||
data: result,
|
||||
}),
|
||||
};
|
||||
});
|
||||
@@ -1,37 +1,36 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { PrismaService } from '../../../common/database/prisma.service';
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class PrePopulateService {
|
||||
constructor(private prisma: PrismaService) { }
|
||||
constructor(private prisma: PrismaService) {}
|
||||
|
||||
async getAllBankDetails() {
|
||||
return await this.prisma.banks.findMany({
|
||||
where: {
|
||||
isActive: true,
|
||||
deletedAt: null,
|
||||
},
|
||||
include: {
|
||||
BankBranches: {
|
||||
select: {
|
||||
id: true,
|
||||
branchAddress: true,
|
||||
ifscCode: true
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
async getAllBankDetails() {
|
||||
return await this.prisma.banks.findMany({
|
||||
where: {
|
||||
isActive: true,
|
||||
deletedAt: null,
|
||||
},
|
||||
include: {
|
||||
BankBranches: {
|
||||
select: {
|
||||
id: true,
|
||||
branchAddress: true,
|
||||
ifscCode: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async getAllCurrencyDetails() {
|
||||
return await this.prisma.currencies.findMany({
|
||||
where: {
|
||||
isActive: true,
|
||||
deletedAt: null,
|
||||
},
|
||||
})
|
||||
}
|
||||
async getAllCurrencyDetails() {
|
||||
return await this.prisma.currencies.findMany({
|
||||
where: {
|
||||
isActive: true,
|
||||
deletedAt: null,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async getAllPQQQuesAndAns() {
|
||||
return await this.prisma.pQQCategories.findMany({
|
||||
|
||||
Reference in New Issue
Block a user