Merge branch 'mayankSprint2' of http://git.wdipl.com/Mayank.Mishra/MinglarBackendNestJS into paritosh-main1

This commit is contained in:
paritosh18
2026-02-23 17:52:03 +05:30
11 changed files with 335 additions and 136 deletions

53
insertCities.js Normal file
View File

@@ -0,0 +1,53 @@
import { PrismaClient } from '@prisma/client';
import fs from 'fs';
import path from 'path';
const prisma = new PrismaClient();
async function insertCities() {
try {
const statesFolder = path.join(process.cwd(), 'states-cities');
const files = fs.readdirSync(statesFolder);
for (const file of files) {
if (!file.endsWith('.json')) continue;
const stateName = file.replace('.json', '');
const state = await prisma.states.findFirst({
where: { stateName },
});
if (!state) {
console.log(`❌ State not found: ${stateName}`);
continue;
}
const filePath = path.join(statesFolder, file);
const citiesData = JSON.parse(
fs.readFileSync(filePath, 'utf-8')
);
await prisma.cities.createMany({
data: citiesData.map((city) => ({
stateXid: state.id,
cityName:
typeof city === 'string'
? city.trim()
: city.cityName.trim(),
})),
skipDuplicates: true,
});
console.log(`${stateName} cities inserted`);
}
console.log('🎉 All cities inserted successfully');
} catch (error) {
console.error('Error inserting cities:', error);
} finally {
await prisma.$disconnect();
}
}
insertCities();

View File

@@ -54,12 +54,14 @@
"class-validator": "^0.14.0",
"date-fns": "^4.1.0",
"fast-xml-parser": "^5.3.1",
"fs": "^0.0.1-security",
"helmet": "^7.1.0",
"http-status": "^2.1.0",
"moment": "^2.30.1",
"passport": "^0.7.0",
"passport-jwt": "^4.0.1",
"passport-local": "^1.0.0",
"path": "^0.12.7",
"prisma": "^7.0.1",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.8.1",

64
prisma/citiesSeeder.ts Normal file
View File

@@ -0,0 +1,64 @@
import fs from 'fs'
import path from 'path'
import { PrismaClient } from '@prisma/client'
export async function seedCities(prisma: PrismaClient) {
const statesFolder = path.join(process.cwd(), 'states-cities')
const files = fs.readdirSync(statesFolder)
for (const file of files) {
if (!file.endsWith('.json')) continue
const stateName = file.replace('.json', '')
const state = await prisma.states.findFirst({
where: {
stateName: {
equals: stateName,
mode: 'insensitive',
},
},
})
if (!state) {
console.log(`❌ State not found: ${stateName}`)
continue
}
const filePath = path.join(statesFolder, file)
const rawData = JSON.parse(fs.readFileSync(filePath, 'utf-8'))
if (!rawData.districts) {
console.log(`❌ Invalid structure in ${file}`)
continue
}
const allVillages: string[] = []
for (const district of rawData.districts) {
for (const sub of district.subDistricts || []) {
for (const village of sub.villages || []) {
if (village && village.trim()) {
allVillages.push(village.trim())
}
}
}
}
console.log(`📦 Total villages found in ${stateName}:`, allVillages.length)
const result = await prisma.cities.createMany({
data: allVillages.map((village) => ({
stateXid: state.id,
cityName: village,
})),
skipDuplicates: true,
})
console.log(`${stateName} inserted: ${result.count}`)
}
console.log('🎉 All states processed successfully!')
}

View File

@@ -342,7 +342,7 @@ model Cities {
id Int @id @default(autoincrement())
stateXid Int @map("state_xid")
states States @relation(fields: [stateXid], references: [id], onDelete: Cascade)
cityName String @unique @map("city_name") @db.VarChar(50)
cityName String @map("city_name") @db.VarChar(50)
isActive Boolean @default(true) @map("is_active")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
@@ -356,6 +356,7 @@ model Cities {
checkOutActivities Activities[] @relation("CheckOutCity")
schoolCompanies SchoolCompany[]
@@unique([stateXid, cityName])
@@map("cities")
@@schema("mst")
}

View File

@@ -1,6 +1,7 @@
import { PrismaClient } from '@prisma/client';
import { PrismaPg } from '@prisma/adapter-pg';
import 'dotenv/config';
import { seedCities } from './citiesSeeder'
const prisma = new PrismaClient({
adapter: new PrismaPg({ connectionString: process.env.DATABASE_URL }),
@@ -18,6 +19,60 @@ async function main() {
isActive: true,
},
});
// ================= STATES =================
const statesList = [
'Andhra Pradesh',
'Arunachal Pradesh',
'Assam',
'Bihar',
'Chhattisgarh',
'Goa',
'Gujarat',
'Haryana',
'Himachal Pradesh',
'Jharkhand',
'Karnataka',
'Kerala',
'Madhya Pradesh',
'Maharashtra',
'Manipur',
'Meghalaya',
'Mizoram',
'Nagaland',
'Odisha',
'Punjab',
'Rajasthan',
'Sikkim',
'Tamil Nadu',
'Telangana',
'Tripura',
'Uttar Pradesh',
'Uttarakhand',
'West Bengal',
// Union Territories
'Andaman and Nicobar Islands',
'Chandigarh',
'Dadra and Nagar Haveli and Daman and Diu',
'Delhi',
'Jammu and Kashmir',
'Ladakh',
'Lakshadweep',
'Puducherry'
];
for (const stateName of statesList) {
await prisma.states.upsert({
where: { stateName },
update: {},
create: {
countryXid: india.id,
stateName,
},
});
}
// ✅ Currencies
await prisma.currencies.createMany({
@@ -659,6 +714,10 @@ async function main() {
skipDuplicates: true,
});
console.log('🚀 Starting city seeding...')
await seedCities(prisma)
console.log('✅ City seeding finished')
// ✅ PQQ Categories + Questions + Answers
const categoriesData = [
{
@@ -1617,8 +1676,6 @@ async function main() {
});
}
console.log('✅ Seed data inserted successfully!');
}

View File

@@ -256,7 +256,7 @@ removeConnectionDetails:
events:
- httpApi:
path: /user/connections/remove-connection-details
method: post
method: delete
getAllConnectionOfUser:
handler: src/modules/user/handlers/connections/getAllConnectionDetailsOfUser.handler

View File

@@ -34,14 +34,15 @@ export const handler = safeHandler(async (
throw new ApiError(404, 'Host not found');
}
let body: { activityXid: number; venueXid: number; scheduleHeaderXid: number; slotXid: number; cancellationReason?: string };
let body: { activityXid: number; venueXid: number; cancellations: { scheduleHeaderXid: number; slotXid: number; cancellationReason: string }[] };
try {
body = event.body ? JSON.parse(event.body) : {};
} catch {
throw new ApiError(400, 'Invalid JSON payload');
}
if(!body.activityXid || !body.venueXid || !body.scheduleHeaderXid || !body.slotXid){
if (!body.activityXid || !body.venueXid || !Array.isArray(body.cancellations) || body.cancellations.length === 0) {
throw new ApiError(400, 'Missing required fields');
}
@@ -63,12 +64,15 @@ export const handler = safeHandler(async (
}
await schedulingService.cancelSlotForActivity(
Number(body.scheduleHeaderXid),
Number(body.slotXid),
body.cancellationReason || 'No reason provided'
await schedulingService.cancelMultipleSlotsForActivity(
body.cancellations.map((item: any) => ({
scheduleHeaderXid: Number(item.scheduleHeaderXid),
slotXid: Number(item.slotXid),
cancellationReason: item.cancellationReason
}))
);
const result = await schedulingService.getVenueDurationByAct(Number(body.activityXid), Number(hostId));
return {

View File

@@ -694,24 +694,23 @@ export class SchedulingService {
return result;
}
async cancelSlotForActivity(
scheduleHeaderXid: number,
slotXid?: number,
cancellationReason?: string
) {
return await this.prisma.cancellations.create({
data: {
scheduleHeader: {
connect: { id: scheduleHeaderXid },
},
slot: {
connect: { id: slotXid },
},
cancellationReason
}
})
async cancelMultipleSlotsForActivity(cancellations: {
scheduleHeaderXid: number;
slotXid: number;
cancellationReason?: string;
}[]) {
return await this.prisma.cancellations.createMany({
data: cancellations.map(item => ({
scheduleHeaderXid: item.scheduleHeaderXid,
slotXid: item.slotXid,
cancellationReason: item.cancellationReason || 'No reason provided'
})),
skipDuplicates: true
});
}
async openCanceledSlot(
cancellationXid: number,
slotXid?: number,

View File

@@ -2,10 +2,12 @@ export class AddSchoolCompanyDetailDTO {
schoolCompanyName: string;
isSchool: boolean;
cityXid: number;
userId: number;
constructor(schoolCompanyName: string, isSchool: boolean, cityXid: number) {
constructor(schoolCompanyName: string, isSchool: boolean, cityXid: number, userId: number) {
this.schoolCompanyName = schoolCompanyName;
this.isSchool = isSchool;
this.cityXid = cityXid;
this.userId = userId;
}
}

View File

@@ -86,6 +86,7 @@ export const handler = safeHandler(
schoolCompanyName.trim().toLowerCase(),
isSchool,
cityXid,
userId
);
// Call service to add or find school/company
@@ -99,11 +100,8 @@ export const handler = safeHandler(
},
body: JSON.stringify({
success: true,
message: result.isNew
? `${isSchool ? 'School' : 'Company'} created successfully`
: `${isSchool ? 'School' : 'Company'} already exists, returning existing record`,
data: result.data,
isNew: result.isNew,
message: 'Connection added successfully',
data: null,
}),
};
},

View File

@@ -1943,7 +1943,7 @@ export class UserService {
async addOrFindSchoolCompanyDetail(dto: AddSchoolCompanyDetailDTO) {
const { schoolCompanyName, isSchool, cityXid } = dto;
const { schoolCompanyName, isSchool, cityXid, userId } = dto;
const normalizedName = normalizeName(schoolCompanyName);
@@ -1961,7 +1961,7 @@ export class UserService {
}
// ✅ 2. Check existing (lowercase match)
const existing = await this.prisma.schoolCompany.findFirst({
let schoolCompany = await this.prisma.schoolCompany.findFirst({
where: {
schoolCompanyName: normalizedName,
cityXid,
@@ -1971,16 +1971,10 @@ export class UserService {
},
});
if (existing) {
return {
isNew: false,
data: existing,
message: "Already exists",
};
}
let isNewSchoolCompany = false;
// ✅ 3. Create new (store lowercase)
const created = await this.prisma.schoolCompany.create({
if (!schoolCompany) {
schoolCompany = await this.prisma.schoolCompany.create({
data: {
schoolCompanyName: normalizedName,
isSchool,
@@ -1988,13 +1982,38 @@ export class UserService {
},
});
isNewSchoolCompany = true;
}
// 4⃣ Check if user already connected
const existingConnection = await this.prisma.connectDetails.findFirst({
where: {
userXid: userId,
schoolCompanyXid: schoolCompany.id,
isActive: true,
},
});
if (existingConnection) {
return {
isNew: true,
data: created,
message: "Created successfully",
isNew: false,
data: schoolCompany,
message: "Already connected",
};
}
// 5⃣ Create connectDetails safely
await this.prisma.connectDetails.create({
data: {
userXid: userId,
schoolCompanyXid: schoolCompany.id,
isActive: true,
},
});
return true;
}
async getAllActivitiesFromConnectionsUserInterests(
userId: number,
schoolCompanyXids: number[],