participants mappig done for other modules
This commit is contained in:
parent
bd7bdef46f
commit
934fd7a907
BIN
all_ids.txt
Normal file
BIN
all_ids.txt
Normal file
Binary file not shown.
16
drop_constraint.ts
Normal file
16
drop_constraint.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import 'dotenv/config';
|
||||||
|
import db from './src/database/models/index.js';
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
try {
|
||||||
|
console.log('Attempting to drop constraint request_participants_requestId_fkey...');
|
||||||
|
await db.sequelize.query('ALTER TABLE request_participants DROP CONSTRAINT IF EXISTS "request_participants_requestId_fkey"');
|
||||||
|
console.log('Constraint dropped successfully.');
|
||||||
|
process.exit(0);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error dropping constraint:', error);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
run();
|
||||||
32
fix_missing_participants.ts
Normal file
32
fix_missing_participants.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { ParticipantService } from './src/services/ParticipantService.js';
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
try {
|
||||||
|
const requestId = '29b742a7-6d9f-4736-8aae-295ffe32ef75';
|
||||||
|
console.log(`Fixing participants for resignation ${requestId}...`);
|
||||||
|
|
||||||
|
const { Resignation, User, Dealer, Application, District } = (await import('./src/database/models/index.js')).default;
|
||||||
|
const resignation = await Resignation.findByPk(requestId);
|
||||||
|
console.log('Resignation Record:', JSON.stringify(resignation, null, 2));
|
||||||
|
|
||||||
|
if (resignation) {
|
||||||
|
const user = await User.findByPk(resignation.dealerId);
|
||||||
|
console.log('User Record:', JSON.stringify(user, null, 2));
|
||||||
|
if (user && user.dealerId) {
|
||||||
|
const dealer = await Dealer.findByPk(user.dealerId, {
|
||||||
|
include: [{ model: Application, as: 'application', include: [{ model: District, as: 'district' }] }]
|
||||||
|
});
|
||||||
|
console.log('Dealer/Application/District Record:', JSON.stringify(dealer, null, 2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await ParticipantService.assignResignationParticipants(requestId);
|
||||||
|
console.log('Done.');
|
||||||
|
process.exit(0);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fixing participants:', error);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
run();
|
||||||
23
quick_query.ts
Normal file
23
quick_query.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import 'dotenv/config';
|
||||||
|
import db from './src/database/models/index.js';
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
try {
|
||||||
|
const participants = await db.RequestParticipant.findAll({
|
||||||
|
limit: 100,
|
||||||
|
include: [{ model: db.User, as: 'user', attributes: ['fullName', 'roleCode', 'email'] }]
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`Found ${participants.length} participants in total:`);
|
||||||
|
participants.forEach((p: any) => {
|
||||||
|
console.log(`- RequestId: ${p.requestId}, Type: ${p.requestType}, User: ${p.user.fullName}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
process.exit(0);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error querying participants:', error);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
run();
|
||||||
@ -408,7 +408,8 @@ export const REQUEST_TYPES = {
|
|||||||
APPLICATION: 'application',
|
APPLICATION: 'application',
|
||||||
RESIGNATION: 'resignation',
|
RESIGNATION: 'resignation',
|
||||||
CONSTITUTIONAL: 'constitutional',
|
CONSTITUTIONAL: 'constitutional',
|
||||||
RELOCATION: 'relocation'
|
RELOCATION: 'relocation',
|
||||||
|
TERMINATION: 'termination'
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
// Module List for Document Management
|
// Module List for Document Management
|
||||||
|
|||||||
@ -123,6 +123,11 @@ export default (sequelize: Sequelize) => {
|
|||||||
scope: { requestType: 'constitutional' },
|
scope: { requestType: 'constitutional' },
|
||||||
constraints: false
|
constraints: false
|
||||||
});
|
});
|
||||||
|
ConstitutionalChange.hasMany(models.RequestParticipant, {
|
||||||
|
foreignKey: 'requestId',
|
||||||
|
as: 'participants',
|
||||||
|
scope: { requestType: 'constitutional' }
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return ConstitutionalChange;
|
return ConstitutionalChange;
|
||||||
|
|||||||
@ -147,6 +147,11 @@ export default (sequelize: Sequelize) => {
|
|||||||
foreignKey: 'resignationId',
|
foreignKey: 'resignationId',
|
||||||
as: 'settlement'
|
as: 'settlement'
|
||||||
});
|
});
|
||||||
|
Resignation.hasMany(models.RequestParticipant, {
|
||||||
|
foreignKey: 'requestId',
|
||||||
|
as: 'participants',
|
||||||
|
scope: { requestType: 'resignation' }
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return Resignation;
|
return Resignation;
|
||||||
|
|||||||
@ -111,6 +111,11 @@ export default (sequelize: Sequelize) => {
|
|||||||
scope: { requestType: 'termination' },
|
scope: { requestType: 'termination' },
|
||||||
constraints: false
|
constraints: false
|
||||||
});
|
});
|
||||||
|
TerminationRequest.hasMany(models.RequestParticipant, {
|
||||||
|
foreignKey: 'requestId',
|
||||||
|
as: 'participants',
|
||||||
|
scope: { requestType: 'termination' }
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return TerminationRequest;
|
return TerminationRequest;
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import { AuthRequest } from '../../types/express.types.js';
|
|||||||
import { CONSTITUTIONAL_STAGES, AUDIT_ACTIONS, ROLES } from '../../common/config/constants.js';
|
import { CONSTITUTIONAL_STAGES, AUDIT_ACTIONS, ROLES } from '../../common/config/constants.js';
|
||||||
import { ConstitutionalWorkflowService } from '../../services/ConstitutionalWorkflowService.js';
|
import { ConstitutionalWorkflowService } from '../../services/ConstitutionalWorkflowService.js';
|
||||||
import { NomenclatureService } from '../../common/utils/nomenclature.js';
|
import { NomenclatureService } from '../../common/utils/nomenclature.js';
|
||||||
|
import { ParticipantService } from '../../services/ParticipantService.js';
|
||||||
|
|
||||||
export const submitRequest = async (req: AuthRequest, res: Response) => {
|
export const submitRequest = async (req: AuthRequest, res: Response) => {
|
||||||
try {
|
try {
|
||||||
@ -49,6 +50,10 @@ export const submitRequest = async (req: AuthRequest, res: Response) => {
|
|||||||
entityId: request.id
|
entityId: request.id
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Add as chat participants (Async)
|
||||||
|
ParticipantService.assignConstitutionalParticipants(request.id)
|
||||||
|
.catch(err => console.error('Error assigning participants to constitutional change:', err));
|
||||||
|
|
||||||
res.status(201).json({
|
res.status(201).json({
|
||||||
success: true,
|
success: true,
|
||||||
message: 'Constitutional change request submitted successfully',
|
message: 'Constitutional change request submitted successfully',
|
||||||
@ -96,7 +101,12 @@ export const getRequestById = async (req: AuthRequest, res: Response) => {
|
|||||||
include: [
|
include: [
|
||||||
{ model: Outlet, as: 'outlet' },
|
{ model: Outlet, as: 'outlet' },
|
||||||
{ model: User, as: 'dealer', attributes: ['fullName', 'email'] },
|
{ model: User, as: 'dealer', attributes: ['fullName', 'email'] },
|
||||||
{ model: Worknote, as: 'worknotes' }
|
{ model: Worknote, as: 'worknotes' },
|
||||||
|
{
|
||||||
|
model: db.RequestParticipant,
|
||||||
|
as: 'participants',
|
||||||
|
include: [{ model: User, as: 'user', attributes: ['id', 'fullName', 'email', 'roleCode'] }]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import ExternalMocksService from '../../common/utils/externalMocks.service.js';
|
|||||||
|
|
||||||
import { ResignationWorkflowService } from '../../services/ResignationWorkflowService.js';
|
import { ResignationWorkflowService } from '../../services/ResignationWorkflowService.js';
|
||||||
import { NomenclatureService } from '../../common/utils/nomenclature.js';
|
import { NomenclatureService } from '../../common/utils/nomenclature.js';
|
||||||
|
import { ParticipantService } from '../../services/ParticipantService.js';
|
||||||
|
|
||||||
// Removed generateResignationId and moved to NomenclatureService
|
// Removed generateResignationId and moved to NomenclatureService
|
||||||
|
|
||||||
@ -73,6 +74,11 @@ export const createResignation = async (req: AuthRequest, res: Response, next: N
|
|||||||
|
|
||||||
await transaction.commit();
|
await transaction.commit();
|
||||||
logger.info(`Resignation request created: ${resignationId} by dealer: ${req.user.email}`);
|
logger.info(`Resignation request created: ${resignationId} by dealer: ${req.user.email}`);
|
||||||
|
|
||||||
|
// Add as chat participants (Async)
|
||||||
|
ParticipantService.assignResignationParticipants(resignation.id)
|
||||||
|
.catch(err => logger.error('Error assigning participants to resignation:', err));
|
||||||
|
|
||||||
res.status(201).json({ success: true, message: 'Resignation request submitted successfully', resignationId, resignation });
|
res.status(201).json({ success: true, message: 'Resignation request submitted successfully', resignationId, resignation });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (transaction) await transaction.rollback();
|
if (transaction) await transaction.rollback();
|
||||||
@ -127,6 +133,11 @@ export const getResignationById = async (req: AuthRequest, res: Response, next:
|
|||||||
{ model: db.FnFLineItem, as: 'lineItems' },
|
{ model: db.FnFLineItem, as: 'lineItems' },
|
||||||
{ model: db.FffClearance, as: 'clearances' }
|
{ model: db.FffClearance, as: 'clearances' }
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: db.RequestParticipant,
|
||||||
|
as: 'participants',
|
||||||
|
include: [{ model: db.User, as: 'user', attributes: ['id', 'fullName', 'email', 'roleCode'] }]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
@ -505,3 +516,33 @@ export const updateClearance = async (req: AuthRequest, res: Response, next: Nex
|
|||||||
next(error);
|
next(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
// Unified status update handler for frontend compatibility
|
||||||
|
export const updateResignationStatus = async (req: AuthRequest, res: Response, next: NextFunction) => {
|
||||||
|
try {
|
||||||
|
const { action } = req.body;
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case 'approve':
|
||||||
|
return approveResignation(req, res, next);
|
||||||
|
case 'reject':
|
||||||
|
return rejectResignation(req, res, next);
|
||||||
|
case 'withdrawal':
|
||||||
|
case 'withdraw':
|
||||||
|
return withdrawResignation(req, res, next);
|
||||||
|
case 'sendback':
|
||||||
|
return sendBackResignation(req, res, next);
|
||||||
|
case 'pushfnf':
|
||||||
|
// For push to F&F, we can trigger the same logic as Legal -> FNF_INITIATED approve
|
||||||
|
// But specifically for the pushfnf button action
|
||||||
|
return approveResignation(req, res, next);
|
||||||
|
default:
|
||||||
|
return res.status(400).json({
|
||||||
|
success: false,
|
||||||
|
message: `Invalid or unsupported resignation action: ${action}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Error in updateResignationStatus:', error);
|
||||||
|
next(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@ -10,6 +10,7 @@ router.post('/', authenticate as any, resignationController.createResignation);
|
|||||||
router.get('/', authenticate as any, resignationController.getResignations);
|
router.get('/', authenticate as any, resignationController.getResignations);
|
||||||
router.get('/:id', authenticate as any, resignationController.getResignationById);
|
router.get('/:id', authenticate as any, resignationController.getResignationById);
|
||||||
router.put('/:id/approve', authenticate as any, resignationController.approveResignation);
|
router.put('/:id/approve', authenticate as any, resignationController.approveResignation);
|
||||||
|
router.post('/:id/status', authenticate as any, resignationController.updateResignationStatus);
|
||||||
router.put('/:id/reject', authenticate as any, resignationController.rejectResignation);
|
router.put('/:id/reject', authenticate as any, resignationController.rejectResignation);
|
||||||
router.put('/:id/withdraw', authenticate as any, resignationController.withdrawResignation);
|
router.put('/:id/withdraw', authenticate as any, resignationController.withdrawResignation);
|
||||||
router.put('/:id/sendback', authenticate as any, resignationController.sendBackResignation);
|
router.put('/:id/sendback', authenticate as any, resignationController.sendBackResignation);
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import ExternalMocksService from '../../common/utils/externalMocks.service.js';
|
|||||||
|
|
||||||
import { TerminationWorkflowService } from '../../services/TerminationWorkflowService.js';
|
import { TerminationWorkflowService } from '../../services/TerminationWorkflowService.js';
|
||||||
import { NomenclatureService } from '../../common/utils/nomenclature.js';
|
import { NomenclatureService } from '../../common/utils/nomenclature.js';
|
||||||
|
import { ParticipantService } from '../../services/ParticipantService.js';
|
||||||
|
|
||||||
// Create termination request
|
// Create termination request
|
||||||
export const createTermination = async (req: AuthRequest, res: Response, next: NextFunction) => {
|
export const createTermination = async (req: AuthRequest, res: Response, next: NextFunction) => {
|
||||||
@ -45,6 +46,11 @@ export const createTermination = async (req: AuthRequest, res: Response, next: N
|
|||||||
}, { transaction });
|
}, { transaction });
|
||||||
|
|
||||||
await transaction.commit();
|
await transaction.commit();
|
||||||
|
|
||||||
|
// Add as chat participants (Async)
|
||||||
|
ParticipantService.assignTerminationParticipants(termination.id)
|
||||||
|
.catch(err => logger.error('Error assigning participants to termination:', err));
|
||||||
|
|
||||||
res.status(201).json({ success: true, message: 'Termination request created', termination });
|
res.status(201).json({ success: true, message: 'Termination request created', termination });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (transaction) await transaction.rollback();
|
if (transaction) await transaction.rollback();
|
||||||
@ -110,7 +116,12 @@ export const getTerminationById = async (req: AuthRequest, res: Response, next:
|
|||||||
as: 'uploadedDocuments',
|
as: 'uploadedDocuments',
|
||||||
include: [{ model: db.User, as: 'uploader', attributes: ['fullName'] }]
|
include: [{ model: db.User, as: 'uploader', attributes: ['fullName'] }]
|
||||||
},
|
},
|
||||||
{ model: db.FnF, as: 'fnfSettlement' }
|
{ model: db.FnF, as: 'fnfSettlement' },
|
||||||
|
{
|
||||||
|
model: db.RequestParticipant,
|
||||||
|
as: 'participants',
|
||||||
|
include: [{ model: db.User, as: 'user', attributes: ['id', 'fullName', 'email', 'roleCode'] }]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -12,6 +12,7 @@ router.post('/', createTermination);
|
|||||||
router.get('/', getTerminations);
|
router.get('/', getTerminations);
|
||||||
router.get('/:id', getTerminationById);
|
router.get('/:id', getTerminationById);
|
||||||
router.put('/:id/status', updateTerminationStatus);
|
router.put('/:id/status', updateTerminationStatus);
|
||||||
|
router.post('/:id/status', updateTerminationStatus);
|
||||||
router.post('/scn-response', submitScnResponse);
|
router.post('/scn-response', submitScnResponse);
|
||||||
router.post('/hearing-record', recordPersonalHearing);
|
router.post('/hearing-record', recordPersonalHearing);
|
||||||
|
|
||||||
|
|||||||
213
src/services/ParticipantService.ts
Normal file
213
src/services/ParticipantService.ts
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
import db from '../database/models/index.js';
|
||||||
|
import { ROLES, REQUEST_TYPES } from '../common/config/constants.js';
|
||||||
|
import { Op } from 'sequelize';
|
||||||
|
|
||||||
|
const {
|
||||||
|
RequestParticipant,
|
||||||
|
User,
|
||||||
|
TerminationRequest,
|
||||||
|
ConstitutionalChange,
|
||||||
|
Dealer,
|
||||||
|
Application,
|
||||||
|
District,
|
||||||
|
Region,
|
||||||
|
Zone
|
||||||
|
} = db;
|
||||||
|
|
||||||
|
export class ParticipantService {
|
||||||
|
/**
|
||||||
|
* Common helper to add a participant
|
||||||
|
*/
|
||||||
|
private static async addParticipant(requestId: string, requestType: string, userId: string, participantType: string = 'contributor', metadata: any = {}) {
|
||||||
|
try {
|
||||||
|
await RequestParticipant.findOrCreate({
|
||||||
|
where: {
|
||||||
|
requestId,
|
||||||
|
requestType,
|
||||||
|
userId
|
||||||
|
},
|
||||||
|
defaults: {
|
||||||
|
participantType,
|
||||||
|
joinedMethod: 'auto',
|
||||||
|
metadata: {
|
||||||
|
...metadata,
|
||||||
|
autoMapped: true,
|
||||||
|
assignedAt: new Date()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error adding participant ${userId} to ${requestType} ${requestId}:`, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves location-based managers for a dealer
|
||||||
|
*/
|
||||||
|
private static async getDealerLocationManagers(dealerId: string) {
|
||||||
|
const dealer = await Dealer.findByPk(dealerId, {
|
||||||
|
include: [{
|
||||||
|
model: Application,
|
||||||
|
as: 'application',
|
||||||
|
include: [{
|
||||||
|
model: District,
|
||||||
|
as: 'district',
|
||||||
|
include: [
|
||||||
|
{ model: Region, as: 'region' },
|
||||||
|
{ model: Zone, as: 'zone' }
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!dealer || !dealer.application || !dealer.application.district) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const district = dealer.application.district;
|
||||||
|
return {
|
||||||
|
asmId: district.asmId,
|
||||||
|
zmId: district.zmId,
|
||||||
|
rbmId: district.region?.rbmId,
|
||||||
|
zbhId: district.zone?.zbhId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assign participants for Termination Request
|
||||||
|
*/
|
||||||
|
static async assignTerminationParticipants(terminationId: string) {
|
||||||
|
try {
|
||||||
|
const termination = await TerminationRequest.findByPk(terminationId);
|
||||||
|
if (!termination) return;
|
||||||
|
|
||||||
|
// TerminationRequest already uses Dealer ID
|
||||||
|
const managers = await this.getDealerLocationManagers(termination.dealerId);
|
||||||
|
const participantIds = new Set<string>();
|
||||||
|
|
||||||
|
// 1. Location based managers
|
||||||
|
if (managers) {
|
||||||
|
if (managers.rbmId) participantIds.add(managers.rbmId);
|
||||||
|
if (managers.zbhId) participantIds.add(managers.zbhId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. National roles
|
||||||
|
const nationalRoles = [ROLES.DD_LEAD, ROLES.NBH, ROLES.CCO, ROLES.CEO, ROLES.LEGAL_ADMIN];
|
||||||
|
const nationalUsers = await User.findAll({
|
||||||
|
where: {
|
||||||
|
roleCode: { [Op.in]: nationalRoles },
|
||||||
|
status: 'active'
|
||||||
|
},
|
||||||
|
attributes: ['id']
|
||||||
|
});
|
||||||
|
|
||||||
|
nationalUsers.forEach((u: any) => participantIds.add(u.id));
|
||||||
|
|
||||||
|
// 3. Add all unique participants
|
||||||
|
for (const userId of participantIds) {
|
||||||
|
await this.addParticipant(termination.id, REQUEST_TYPES.TERMINATION, userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`[ParticipantService] Added ${participantIds.size} participants to termination ${terminationId}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error assigning termination participants:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assign participants for Constitutional Change Request
|
||||||
|
*/
|
||||||
|
static async assignConstitutionalParticipants(requestId: string) {
|
||||||
|
try {
|
||||||
|
const request = await ConstitutionalChange.findByPk(requestId);
|
||||||
|
if (!request) return;
|
||||||
|
|
||||||
|
// In ConstitutionalChange model, dealerId is the User ID
|
||||||
|
const user = await User.findByPk(request.dealerId);
|
||||||
|
if (!user || !user.dealerId) {
|
||||||
|
console.error(`[ParticipantService] No Dealer ID found for user ${request.dealerId}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const managers = await this.getDealerLocationManagers(user.dealerId);
|
||||||
|
const participantIds = new Set<string>();
|
||||||
|
|
||||||
|
// 1. Location based managers
|
||||||
|
if (managers) {
|
||||||
|
if (managers.asmId) participantIds.add(managers.asmId);
|
||||||
|
if (managers.zmId) participantIds.add(managers.zmId);
|
||||||
|
if (managers.rbmId) participantIds.add(managers.rbmId);
|
||||||
|
if (managers.zbhId) participantIds.add(managers.zbhId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. National roles
|
||||||
|
const nationalRoles = [ROLES.DD_LEAD, ROLES.DD_HEAD, ROLES.NBH, ROLES.LEGAL_ADMIN];
|
||||||
|
const nationalUsers = await User.findAll({
|
||||||
|
where: {
|
||||||
|
roleCode: { [Op.in]: nationalRoles },
|
||||||
|
status: 'active'
|
||||||
|
},
|
||||||
|
attributes: ['id']
|
||||||
|
});
|
||||||
|
|
||||||
|
nationalUsers.forEach((u: any) => participantIds.add(u.id));
|
||||||
|
|
||||||
|
// 3. Add all unique participants
|
||||||
|
for (const userId of participantIds) {
|
||||||
|
await this.addParticipant(request.id, REQUEST_TYPES.CONSTITUTIONAL, userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`[ParticipantService] Added ${participantIds.size} participants to constitutional change ${requestId}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error assigning constitutional participants:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assign participants for Resignation Request
|
||||||
|
*/
|
||||||
|
static async assignResignationParticipants(requestId: string) {
|
||||||
|
try {
|
||||||
|
const resignation = await db.Resignation.findByPk(requestId);
|
||||||
|
if (!resignation) return;
|
||||||
|
|
||||||
|
// In Resignation model, dealerId is the User ID
|
||||||
|
const user = await User.findByPk(resignation.dealerId);
|
||||||
|
if (!user || !user.dealerId) {
|
||||||
|
console.error(`[ParticipantService] No Dealer ID found for user ${resignation.dealerId}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const managers = await this.getDealerLocationManagers(user.dealerId);
|
||||||
|
const participantIds = new Set<string>();
|
||||||
|
|
||||||
|
// 1. Location based managers
|
||||||
|
if (managers) {
|
||||||
|
if (managers.asmId) participantIds.add(managers.asmId);
|
||||||
|
if (managers.rbmId) participantIds.add(managers.rbmId);
|
||||||
|
if (managers.zbhId) participantIds.add(managers.zbhId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. National roles
|
||||||
|
const nationalRoles = [ROLES.DD_LEAD, ROLES.NBH, ROLES.DD_ADMIN, ROLES.FINANCE, ROLES.LEGAL_ADMIN];
|
||||||
|
const nationalUsers = await User.findAll({
|
||||||
|
where: {
|
||||||
|
roleCode: { [Op.in]: nationalRoles },
|
||||||
|
status: 'active'
|
||||||
|
},
|
||||||
|
attributes: ['id']
|
||||||
|
});
|
||||||
|
|
||||||
|
nationalUsers.forEach((u: any) => participantIds.add(u.id));
|
||||||
|
|
||||||
|
// 3. Add all unique participants
|
||||||
|
for (const userId of participantIds) {
|
||||||
|
await this.addParticipant(resignation.id, REQUEST_TYPES.RESIGNATION, userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`[ParticipantService] Added ${participantIds.size} participants to resignation ${requestId}`);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error assigning resignation participants:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -94,7 +94,7 @@ async function prospectLogin(phone) {
|
|||||||
|
|
||||||
async function mockUploadDocument(appId, token, docType) {
|
async function mockUploadDocument(appId, token, docType) {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
const fileBuffer = fs.readFileSync('/home/laxman-h/Pictures/Screenshots/Screenshot from 2026-03-27 09-48-22.png');
|
const fileBuffer = fs.readFileSync('C:/Users/BACKPACKERS/Pictures/claim_document_type.PNG');
|
||||||
const blob = new Blob([fileBuffer], { type: 'image/png' });
|
const blob = new Blob([fileBuffer], { type: 'image/png' });
|
||||||
formData.append('file', blob, 'screenshot.png');
|
formData.append('file', blob, 'screenshot.png');
|
||||||
formData.append('documentType', docType);
|
formData.append('documentType', docType);
|
||||||
@ -410,7 +410,7 @@ async function triggerWorkflow() {
|
|||||||
// 12. FINAL ONBOARDING
|
// 12. FINAL ONBOARDING
|
||||||
log(12, 'Admin Finalizing Dealer Onboarding...');
|
log(12, 'Admin Finalizing Dealer Onboarding...');
|
||||||
await apiRequest('/dealers', 'POST', { applicationId: applicationUUID }, adminToken);
|
await apiRequest('/dealers', 'POST', { applicationId: applicationUUID }, adminToken);
|
||||||
|
|
||||||
log(12, '--- WORKFLOW COMPLETED SUCCESSFULLY! ---');
|
log(12, '--- WORKFLOW COMPLETED SUCCESSFULLY! ---');
|
||||||
log(12, `The application ${applicationId} is now at 'ONBOARDED' status.`);
|
log(12, `The application ${applicationId} is now at 'ONBOARDED' status.`);
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
verify_output.txt
Normal file
BIN
verify_output.txt
Normal file
Binary file not shown.
55
verify_participants_logic.ts
Normal file
55
verify_participants_logic.ts
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import db from './src/database/models/index.js';
|
||||||
|
import { ParticipantService } from './src/services/ParticipantService.js';
|
||||||
|
|
||||||
|
async function verify() {
|
||||||
|
try {
|
||||||
|
console.log('--- Verification Started ---');
|
||||||
|
|
||||||
|
// 1. Verify Termination Participants
|
||||||
|
const termination = await db.TerminationRequest.findOne();
|
||||||
|
if (termination) {
|
||||||
|
console.log(`Found termination ${termination.id}. Assigning participants...`);
|
||||||
|
await ParticipantService.assignTerminationParticipants(termination.id);
|
||||||
|
const participants = await db.RequestParticipant.findAll({
|
||||||
|
where: { requestId: termination.id, requestType: 'termination' }
|
||||||
|
});
|
||||||
|
console.log(`Termination Participants added: ${participants.length}`);
|
||||||
|
} else {
|
||||||
|
console.log('No termination records found to verify.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Verify Constitutional Participants
|
||||||
|
const constitutional = await db.ConstitutionalChange.findOne();
|
||||||
|
if (constitutional) {
|
||||||
|
console.log(`Found constitutional change ${constitutional.id}. Assigning participants...`);
|
||||||
|
await ParticipantService.assignConstitutionalParticipants(constitutional.id);
|
||||||
|
const participants = await db.RequestParticipant.findAll({
|
||||||
|
where: { requestId: constitutional.id, requestType: 'constitutional' }
|
||||||
|
});
|
||||||
|
console.log(`Constitutional Participants added: ${participants.length}`);
|
||||||
|
} else {
|
||||||
|
console.log('No constitutional change records found to verify.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Verify Resignation Participants
|
||||||
|
const resignation = await db.Resignation.findOne();
|
||||||
|
if (resignation) {
|
||||||
|
console.log(`Found resignation ${resignation.id}. Assigning participants...`);
|
||||||
|
await ParticipantService.assignResignationParticipants(resignation.id);
|
||||||
|
const participants = await db.RequestParticipant.findAll({
|
||||||
|
where: { requestId: resignation.id, requestType: 'resignation' }
|
||||||
|
});
|
||||||
|
console.log(`Resignation Participants added: ${participants.length}`);
|
||||||
|
} else {
|
||||||
|
console.log('No resignation records found to verify.');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('--- Verification Completed ---');
|
||||||
|
process.exit(0);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Verification failed:', error);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
verify();
|
||||||
Loading…
Reference in New Issue
Block a user