Start Umbau zu postgres
This commit is contained in:
parent
e784b424b0
commit
7d10080069
|
|
@ -29,6 +29,7 @@
|
||||||
"@nestjs/passport": "^10.0.3",
|
"@nestjs/passport": "^10.0.3",
|
||||||
"@nestjs/platform-express": "^10.0.0",
|
"@nestjs/platform-express": "^10.0.0",
|
||||||
"@nestjs/serve-static": "^4.0.1",
|
"@nestjs/serve-static": "^4.0.1",
|
||||||
|
"drizzle-orm": "^0.30.8",
|
||||||
"handlebars": "^4.7.8",
|
"handlebars": "^4.7.8",
|
||||||
"ky": "^1.2.0",
|
"ky": "^1.2.0",
|
||||||
"nest-winston": "^1.9.4",
|
"nest-winston": "^1.9.4",
|
||||||
|
|
@ -38,6 +39,7 @@
|
||||||
"passport-google-oauth20": "^2.0.0",
|
"passport-google-oauth20": "^2.0.0",
|
||||||
"passport-jwt": "^4.0.1",
|
"passport-jwt": "^4.0.1",
|
||||||
"passport-local": "^1.0.0",
|
"passport-local": "^1.0.0",
|
||||||
|
"pg": "^8.11.5",
|
||||||
"redis": "^4.6.13",
|
"redis": "^4.6.13",
|
||||||
"redis-om": "^0.4.3",
|
"redis-om": "^0.4.3",
|
||||||
"reflect-metadata": "^0.2.0",
|
"reflect-metadata": "^0.2.0",
|
||||||
|
|
@ -58,6 +60,7 @@
|
||||||
"@types/passport-google-oauth20": "^2.0.14",
|
"@types/passport-google-oauth20": "^2.0.14",
|
||||||
"@types/passport-jwt": "^4.0.1",
|
"@types/passport-jwt": "^4.0.1",
|
||||||
"@types/passport-local": "^1.0.38",
|
"@types/passport-local": "^1.0.38",
|
||||||
|
"@types/pg": "^8.11.5",
|
||||||
"@types/supertest": "^6.0.0",
|
"@types/supertest": "^6.0.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
||||||
"@typescript-eslint/parser": "^6.0.0",
|
"@typescript-eslint/parser": "^6.0.0",
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Module } from '@nestjs/common';
|
import { MiddlewareConsumer, Module } from '@nestjs/common';
|
||||||
import { AppController } from './app.controller.js';
|
import { AppController } from './app.controller.js';
|
||||||
import { AppService } from './app.service.js';
|
import { AppService } from './app.service.js';
|
||||||
import { FileService } from './file/file.service.js';
|
import { FileService } from './file/file.service.js';
|
||||||
|
|
@ -23,11 +23,13 @@ import { ListingsModule } from './listings/listings.module.js';
|
||||||
import { SelectOptionsModule } from './select-options/select-options.module.js';
|
import { SelectOptionsModule } from './select-options/select-options.module.js';
|
||||||
import { CommercialPropertyListingsController } from './listings/commercial-property-listings.controller.js';
|
import { CommercialPropertyListingsController } from './listings/commercial-property-listings.controller.js';
|
||||||
import { ImageModule } from './image/image.module.js';
|
import { ImageModule } from './image/image.module.js';
|
||||||
|
import { RequestDurationMiddleware } from './request-duration/request-duration.middleware.js';
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
const __dirname = path.dirname(__filename);
|
const __dirname = path.dirname(__filename);
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [ConfigModule.forRoot(), MailModule, AuthModule,
|
imports: [ConfigModule.forRoot({isGlobal: true}), MailModule, AuthModule,
|
||||||
ServeStaticModule.forRoot({
|
ServeStaticModule.forRoot({
|
||||||
rootPath: join(__dirname, '..', 'pictures'), // `public` ist das Verzeichnis, wo Ihre statischen Dateien liegen
|
rootPath: join(__dirname, '..', 'pictures'), // `public` ist das Verzeichnis, wo Ihre statischen Dateien liegen
|
||||||
}),
|
}),
|
||||||
|
|
@ -52,9 +54,13 @@ const __dirname = path.dirname(__filename);
|
||||||
ListingsModule,
|
ListingsModule,
|
||||||
SelectOptionsModule,
|
SelectOptionsModule,
|
||||||
RedisModule,
|
RedisModule,
|
||||||
ImageModule
|
ImageModule,
|
||||||
],
|
],
|
||||||
controllers: [AppController, SubscriptionsController],
|
controllers: [AppController, SubscriptionsController],
|
||||||
providers: [AppService, FileService],
|
providers: [AppService, FileService],
|
||||||
})
|
})
|
||||||
export class AppModule {}
|
export class AppModule {
|
||||||
|
configure(consumer: MiddlewareConsumer) {
|
||||||
|
consumer.apply(RequestDurationMiddleware).forRoutes('*');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { jsonb, varchar } from 'drizzle-orm/pg-core';
|
||||||
|
import { pgTable, text, primaryKey } from 'drizzle-orm/pg-core';
|
||||||
|
|
||||||
|
export const businesses_json = pgTable('businesses_json', {
|
||||||
|
id: varchar('id', { length: 255 }).primaryKey(),
|
||||||
|
data: jsonb('data'),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type BusinessesJson = {
|
||||||
|
id: string;
|
||||||
|
data: Record<string, any>;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { drizzle } from 'drizzle-orm/node-postgres';
|
||||||
|
import pkg from 'pg';
|
||||||
|
const { Pool } = pkg;
|
||||||
|
import * as schema from './businesses_json.model.js';
|
||||||
|
import { ConfigService } from '@nestjs/config';
|
||||||
|
import { jsonb, varchar } from 'drizzle-orm/pg-core';
|
||||||
|
import { PG_CONNECTION } from './schema.js';
|
||||||
|
@Module({
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: PG_CONNECTION,
|
||||||
|
inject: [ConfigService],
|
||||||
|
useFactory: async (configService: ConfigService) => {
|
||||||
|
const connectionString = configService.get<string>('DATABASE_URL');
|
||||||
|
const pool = new Pool({
|
||||||
|
connectionString,
|
||||||
|
// ssl: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
return drizzle(pool, { schema });
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
exports: [PG_CONNECTION],
|
||||||
|
})
|
||||||
|
export class DrizzleModule {}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { integer, serial, text, pgTable } from 'drizzle-orm/pg-core';
|
||||||
|
import { relations } from 'drizzle-orm';
|
||||||
|
import { jsonb, varchar } from 'drizzle-orm/pg-core';
|
||||||
|
|
||||||
|
export const PG_CONNECTION = 'PG_CONNECTION';
|
||||||
|
|
||||||
|
export const businesses_json = pgTable('businesses_json', {
|
||||||
|
id: varchar('id', { length: 255 }).primaryKey(),
|
||||||
|
data: jsonb('data'),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type BusinessesJson = {
|
||||||
|
id: string;
|
||||||
|
data: Record<string, any>;
|
||||||
|
};
|
||||||
|
|
@ -21,7 +21,7 @@ export class ImageController {
|
||||||
@UseInterceptors(FileInterceptor('file'),)
|
@UseInterceptors(FileInterceptor('file'),)
|
||||||
async uploadPropertyPicture(@UploadedFile() file: Express.Multer.File,@Param('id') id:string) {
|
async uploadPropertyPicture(@UploadedFile() file: Express.Multer.File,@Param('id') id:string) {
|
||||||
const imagename = await this.fileService.storePropertyPicture(file,id);
|
const imagename = await this.fileService.storePropertyPicture(file,id);
|
||||||
await this.listingService.addImage(id,imagename);
|
// await this.listingService.addImage(id,imagename);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('uploadProfile/:id')
|
@Post('uploadProfile/:id')
|
||||||
|
|
@ -38,16 +38,16 @@ export class ImageController {
|
||||||
|
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
async getPropertyImagesById(@Param('id') id:string): Promise<any> {
|
async getPropertyImagesById(@Param('id') id:string): Promise<any> {
|
||||||
const result = await this.listingService.getCommercialPropertyListingById(id);
|
// const result = await this.listingService.getCommercialPropertyListingById(id);
|
||||||
const listing = result as CommercialPropertyListing;
|
// const listing = result as CommercialPropertyListing;
|
||||||
if (listing.imageOrder){
|
// if (listing.imageOrder){
|
||||||
return listing.imageOrder
|
// return listing.imageOrder
|
||||||
} else {
|
// } else {
|
||||||
const imageOrder = await this.fileService.getPropertyImages(id);
|
// const imageOrder = await this.fileService.getPropertyImages(id);
|
||||||
listing.imageOrder=imageOrder;
|
// listing.imageOrder=imageOrder;
|
||||||
this.listingService.saveListing(listing);
|
// this.listingService.saveListing(listing);
|
||||||
return imageOrder;
|
// return imageOrder;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
@Get('profileImages/:userids')
|
@Get('profileImages/:userids')
|
||||||
async getProfileImagesForUsers(@Param('userids') userids:string): Promise<any> {
|
async getProfileImagesForUsers(@Param('userids') userids:string): Promise<any> {
|
||||||
|
|
@ -61,7 +61,7 @@ export class ImageController {
|
||||||
@Delete('propertyPicture/:listingid/:imagename')
|
@Delete('propertyPicture/:listingid/:imagename')
|
||||||
async deletePropertyImagesById(@Param('listingid') listingid:string,@Param('imagename') imagename:string): Promise<any> {
|
async deletePropertyImagesById(@Param('listingid') listingid:string,@Param('imagename') imagename:string): Promise<any> {
|
||||||
this.fileService.deleteImage(`pictures/property/${listingid}/${imagename}`);
|
this.fileService.deleteImage(`pictures/property/${listingid}/${imagename}`);
|
||||||
await this.listingService.deleteImage(listingid,imagename);
|
// await this.listingService.deleteImage(listingid,imagename);
|
||||||
}
|
}
|
||||||
@Delete('logo/:userid/')
|
@Delete('logo/:userid/')
|
||||||
async deleteLogoImagesById(@Param('id') id:string): Promise<any> {
|
async deleteLogoImagesById(@Param('id') id:string): Promise<any> {
|
||||||
|
|
|
||||||
|
|
@ -4,51 +4,52 @@ import { convertStringToNullUndefined } from '../utils.js';
|
||||||
import { ListingsService } from './listings.service.js';
|
import { ListingsService } from './listings.service.js';
|
||||||
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
|
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
|
||||||
import { Logger } from 'winston';
|
import { Logger } from 'winston';
|
||||||
|
import { ListingCriteria } from 'src/models/main.model.js';
|
||||||
|
|
||||||
@Controller('listings/business')
|
@Controller('listings/business')
|
||||||
export class BusinessListingsController {
|
export class BusinessListingsController {
|
||||||
|
|
||||||
constructor(private readonly listingsService:ListingsService,@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger) {
|
constructor(private readonly listingsService:ListingsService,
|
||||||
|
@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
findAll(): any {
|
findAll(): any {
|
||||||
return this.listingsService.getAllBusinessListings();
|
this.logger.info(`start findAll Listing`);
|
||||||
|
return this.listingsService.findListings();
|
||||||
}
|
}
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
findById(@Param('id') id:string): any {
|
findById(@Param('id') id:string): any {
|
||||||
return this.listingsService.getBusinessListingById(id);
|
return this.listingsService.findById(id);
|
||||||
}
|
}
|
||||||
@Get('user/:userid')
|
@Get('user/:userid')
|
||||||
findByUserId(@Param('userid') userid:string): any {
|
findByUserId(@Param('userid') userid:string): any {
|
||||||
return this.listingsService.getBusinessListingByUserId(userid);
|
return this.listingsService.findByUserId(userid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post('search')
|
@Post('search')
|
||||||
find(@Body() criteria: any): any {
|
find(@Body() criteria: ListingCriteria): any {
|
||||||
return this.listingsService.findBusinessListings(criteria);
|
return this.listingsService.findByState(criteria.state);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param listing creates a new listing
|
|
||||||
*/
|
|
||||||
@Post()
|
@Post()
|
||||||
save(@Body() listing: any){
|
create(@Body() listing: any){
|
||||||
this.logger.info(`Save Listing`);
|
this.logger.info(`Save Listing`);
|
||||||
this.listingsService.saveListing(listing)
|
this.listingsService.createListing(listing)
|
||||||
|
}
|
||||||
|
@Put()
|
||||||
|
update(@Body() listing: any){
|
||||||
|
this.logger.info(`Save Listing`);
|
||||||
|
this.listingsService.updateListing(listing.id,listing)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param id deletes a listing
|
|
||||||
*/
|
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
deleteById(@Param('id') id:string){
|
deleteById(@Param('id') id:string){
|
||||||
this.listingsService.deleteBusinessListing(id)
|
this.listingsService.deleteListing(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Delete('deleteAll')
|
// @Delete('deleteAll')
|
||||||
deleteAll(){
|
// deleteAll(){
|
||||||
this.listingsService.deleteAllBusinessListings()
|
// this.listingsService.deleteAllBusinessListings()
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,39 +13,39 @@ export class CommercialPropertyListingsController {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Get(':id')
|
// @Get(':id')
|
||||||
findById(@Param('id') id:string): any {
|
// findById(@Param('id') id:string): any {
|
||||||
return this.listingsService.getCommercialPropertyListingById(id);
|
// return this.listingsService.getCommercialPropertyListingById(id);
|
||||||
}
|
// }
|
||||||
|
|
||||||
@Post('search')
|
// @Post('search')
|
||||||
find(@Body() criteria: any): any {
|
// find(@Body() criteria: any): any {
|
||||||
return this.listingsService.findCommercialPropertyListings(criteria);
|
// return this.listingsService.findCommercialPropertyListings(criteria);
|
||||||
}
|
// }
|
||||||
|
|
||||||
@Put('imageOrder/:id')
|
// @Put('imageOrder/:id')
|
||||||
async changeImageOrder(@Param('id') id:string,@Body() imageOrder: ImageProperty[]) {
|
// async changeImageOrder(@Param('id') id:string,@Body() imageOrder: ImageProperty[]) {
|
||||||
this.listingsService.updateImageOrder(id, imageOrder)
|
// this.listingsService.updateImageOrder(id, imageOrder)
|
||||||
}
|
// }
|
||||||
/**
|
// /**
|
||||||
* @param listing creates a new listing
|
// * @param listing creates a new listing
|
||||||
*/
|
// */
|
||||||
@Post()
|
// @Post()
|
||||||
save(@Body() listing: any){
|
// save(@Body() listing: any){
|
||||||
this.logger.info(`Save Listing`);
|
// this.logger.info(`Save Listing`);
|
||||||
this.listingsService.saveListing(listing)
|
// this.listingsService.saveListing(listing)
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* @param id deletes a listing
|
// * @param id deletes a listing
|
||||||
*/
|
// */
|
||||||
@Delete(':id')
|
// @Delete(':id')
|
||||||
deleteById(@Param('id') id:string){
|
// deleteById(@Param('id') id:string){
|
||||||
this.listingsService.deleteCommercialPropertyListing(id)
|
// this.listingsService.deleteCommercialPropertyListing(id)
|
||||||
}
|
// }
|
||||||
@Delete('deleteAll')
|
// @Delete('deleteAll')
|
||||||
deleteAll(){
|
// deleteAll(){
|
||||||
this.listingsService.deleteAllcommercialListings()
|
// this.listingsService.deleteAllcommercialListings()
|
||||||
}
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Module } from '@nestjs/common';
|
import { Injectable, Module, OnModuleInit } from '@nestjs/common';
|
||||||
import { BusinessListingsController } from './business-listings.controller.js';
|
import { BusinessListingsController } from './business-listings.controller.js';
|
||||||
import { ListingsService } from './listings.service.js';
|
import { ListingsService } from './listings.service.js';
|
||||||
import { CommercialPropertyListingsController } from './commercial-property-listings.controller.js';
|
import { CommercialPropertyListingsController } from './commercial-property-listings.controller.js';
|
||||||
|
|
@ -8,9 +8,15 @@ import { UnknownListingsController } from './unknown-listings.controller.js';
|
||||||
import { UserModule } from '../user/user.module.js';
|
import { UserModule } from '../user/user.module.js';
|
||||||
import { BrokerListingsController } from './broker-listings.controller.js';
|
import { BrokerListingsController } from './broker-listings.controller.js';
|
||||||
import { UserService } from '../user/user.service.js';
|
import { UserService } from '../user/user.service.js';
|
||||||
|
import { Client, Connection } from 'pg';
|
||||||
|
import { drizzle } from 'drizzle-orm/node-postgres';
|
||||||
|
import { businesses_json } from '../drizzle/businesses_json.model.js';
|
||||||
|
import { DrizzleModule } from '../drizzle/drizzle.module.js';
|
||||||
|
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [RedisModule],
|
imports: [RedisModule,DrizzleModule
|
||||||
|
],
|
||||||
controllers: [BusinessListingsController, CommercialPropertyListingsController,UnknownListingsController,BrokerListingsController],
|
controllers: [BusinessListingsController, CommercialPropertyListingsController,UnknownListingsController,BrokerListingsController],
|
||||||
providers: [ListingsService,FileService,UserService],
|
providers: [ListingsService,FileService,UserService],
|
||||||
exports: [ListingsService],
|
exports: [ListingsService],
|
||||||
|
|
|
||||||
|
|
@ -10,177 +10,186 @@ import {
|
||||||
import { convertStringToNullUndefined } from '../utils.js';
|
import { convertStringToNullUndefined } from '../utils.js';
|
||||||
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
|
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
|
||||||
import { Logger } from 'winston';
|
import { Logger } from 'winston';
|
||||||
import { EntityData, EntityId, Repository, Schema, SchemaDefinition } from 'redis-om';
|
import { EntityData, EntityId, Schema, SchemaDefinition } from 'redis-om';
|
||||||
import { REDIS_CLIENT } from '../redis/redis.module.js';
|
import { eq, ilike, sql } from 'drizzle-orm';
|
||||||
|
import { BusinessesJson, PG_CONNECTION, businesses_json } from '../drizzle/schema.js';
|
||||||
|
import { NodePgDatabase } from 'drizzle-orm/node-postgres';
|
||||||
|
import * as schema from '../drizzle/schema.js';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ListingsService {
|
export class ListingsService {
|
||||||
schemaNameBusiness:ListingCategory={name:'business'}
|
|
||||||
schemaNameCommercial:ListingCategory={name:'commercialProperty'}
|
constructor(@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger,
|
||||||
businessListingRepository:Repository;
|
@Inject(PG_CONNECTION) private conn: NodePgDatabase<typeof schema>,){
|
||||||
commercialPropertyListingRepository:Repository;
|
// this.businessListingRepository = new Repository(this.businessListingSchema, redis);
|
||||||
baseListingSchemaDef : SchemaDefinition = {
|
// this.commercialPropertyListingRepository = new Repository(this.commercialPropertyListingSchema, redis)
|
||||||
id: { type: 'string' },
|
// this.businessListingRepository.createIndex();
|
||||||
userId: { type: 'string' },
|
// this.commercialPropertyListingRepository.createIndex();
|
||||||
listingsCategory: { type: 'string' },
|
|
||||||
title: { type: 'string' },
|
|
||||||
description: { type: 'string' },
|
|
||||||
country: { type: 'string' },
|
|
||||||
state:{ type: 'string' },
|
|
||||||
city:{ type: 'string' },
|
|
||||||
zipCode: { type: 'number' },
|
|
||||||
type: { type: 'string' },
|
|
||||||
price: { type: 'number' },
|
|
||||||
favoritesForUser:{ type: 'string[]' },
|
|
||||||
hideImage:{ type: 'boolean' },
|
|
||||||
draft:{ type: 'boolean' },
|
|
||||||
created:{ type: 'date' },
|
|
||||||
updated:{ type: 'date' }
|
|
||||||
}
|
|
||||||
businessListingSchemaDef : SchemaDefinition = {
|
|
||||||
...this.baseListingSchemaDef,
|
|
||||||
salesRevenue: { type: 'number' },
|
|
||||||
cashFlow: { type: 'number' },
|
|
||||||
employees: { type: 'number' },
|
|
||||||
established: { type: 'number' },
|
|
||||||
internalListingNumber: { type: 'number' },
|
|
||||||
realEstateIncluded:{ type: 'boolean' },
|
|
||||||
leasedLocation:{ type: 'boolean' },
|
|
||||||
franchiseResale:{ type: 'boolean' },
|
|
||||||
supportAndTraining: { type: 'string' },
|
|
||||||
reasonForSale: { type: 'string' },
|
|
||||||
brokerLicencing: { type: 'string' },
|
|
||||||
internals: { type: 'string' },
|
|
||||||
}
|
|
||||||
commercialPropertyListingSchemaDef : SchemaDefinition = {
|
|
||||||
...this.baseListingSchemaDef,
|
|
||||||
imageNames:{ type: 'string[]' },
|
|
||||||
}
|
|
||||||
businessListingSchema = new Schema(this.schemaNameBusiness.name,this.businessListingSchemaDef, {
|
|
||||||
dataStructure: 'JSON'
|
|
||||||
})
|
|
||||||
commercialPropertyListingSchema = new Schema(this.schemaNameCommercial.name,this.commercialPropertyListingSchemaDef, {
|
|
||||||
dataStructure: 'JSON'
|
|
||||||
})
|
|
||||||
constructor(@Inject(REDIS_CLIENT) private readonly redis: any, @Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger){
|
|
||||||
this.businessListingRepository = new Repository(this.businessListingSchema, redis);
|
|
||||||
this.commercialPropertyListingRepository = new Repository(this.commercialPropertyListingSchema, redis)
|
|
||||||
this.businessListingRepository.createIndex();
|
|
||||||
this.commercialPropertyListingRepository.createIndex();
|
|
||||||
}
|
|
||||||
async saveListing(listing: BusinessListing | CommercialPropertyListing) {
|
|
||||||
const repo=listing.listingsCategory==='business'?this.businessListingRepository:this.commercialPropertyListingRepository;
|
|
||||||
let result
|
|
||||||
if (listing.id){
|
|
||||||
result = await repo.save(listing.id,listing as any)
|
|
||||||
} else {
|
|
||||||
result = await repo.save(listing as any)
|
|
||||||
listing.id=result[EntityId];
|
|
||||||
result = await repo.save(listing.id,listing as any)
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
async getCommercialPropertyListingById(id: string): Promise<CommercialPropertyListing>{
|
|
||||||
return await this.commercialPropertyListingRepository.fetch(id) as unknown as CommercialPropertyListing;
|
|
||||||
}
|
|
||||||
async getBusinessListingById(id: string) {
|
|
||||||
return await this.businessListingRepository.fetch(id)
|
|
||||||
}
|
|
||||||
async getBusinessListingByUserId(userid:string){
|
|
||||||
return await this.businessListingRepository.search().where('userId').equals(userid).return.all()
|
|
||||||
}
|
|
||||||
async deleteBusinessListing(id: string){
|
|
||||||
return await this.businessListingRepository.remove(id);
|
|
||||||
}
|
|
||||||
async deleteCommercialPropertyListing(id: string){
|
|
||||||
return await this.commercialPropertyListingRepository.remove(id);
|
|
||||||
}
|
|
||||||
async getAllBusinessListings(start?: number, end?: number) {
|
|
||||||
return await this.businessListingRepository.search().return.all()
|
|
||||||
}
|
|
||||||
async getAllCommercialListings(start?: number, end?: number) {
|
|
||||||
return await this.commercialPropertyListingRepository.search().return.all()
|
|
||||||
}
|
|
||||||
async findBusinessListings(criteria:ListingCriteria): Promise<any> {
|
|
||||||
// let listings = await this.getAllBusinessListings();
|
|
||||||
// return this.find(criteria,listings);
|
|
||||||
this.logger.info(`start findBusinessListings: ${JSON.stringify(criteria)}`);
|
|
||||||
const result = await this.redis.ft.search('business:index','*',{LIMIT:{from:0,size:50}});
|
|
||||||
this.logger.info(`start findBusinessListings: ${JSON.stringify(criteria)}`);
|
|
||||||
return result.documents;
|
|
||||||
}
|
|
||||||
async findCommercialPropertyListings(criteria:ListingCriteria): Promise<any> {
|
|
||||||
let listings = await this.getAllCommercialListings();
|
|
||||||
return this.find(criteria,listings);
|
|
||||||
}
|
|
||||||
async deleteAllBusinessListings(){
|
|
||||||
const ids = await this.getIdsForRepo(this.schemaNameBusiness.name);
|
|
||||||
this.businessListingRepository.remove(ids);
|
|
||||||
}
|
|
||||||
async deleteAllcommercialListings(){
|
|
||||||
const ids = await this.getIdsForRepo(this.schemaNameCommercial.name);
|
|
||||||
this.commercialPropertyListingRepository.remove(ids);
|
|
||||||
}
|
|
||||||
async getIdsForRepo(repoName:string, maxcount=100000){
|
|
||||||
let cursor = 0;
|
|
||||||
let ids = [];
|
|
||||||
do {
|
|
||||||
const reply = await this.redis.scan(cursor, {
|
|
||||||
MATCH: `${repoName}:*`,
|
|
||||||
COUNT: maxcount
|
|
||||||
});
|
|
||||||
cursor = reply.cursor;
|
|
||||||
// Extrahiere die ID aus jedem Schlüssel und füge sie zur Liste hinzu
|
|
||||||
ids = ids.concat(reply.keys.map(key => key.split(':')[1]).filter(id=>id!='index'));
|
|
||||||
} while (cursor !== 0);
|
|
||||||
return ids;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async find(criteria:ListingCriteria, listings: any[]): Promise<any> {
|
// ##############################################################
|
||||||
listings=listings.filter(l=>l.listingsCategory===criteria.listingsCategory);
|
// ##############################################################
|
||||||
if (convertStringToNullUndefined(criteria.type)){
|
async createListing(newListing: { id: string; data: BusinessesJson }): Promise<BusinessesJson> {
|
||||||
console.log(criteria.type);
|
const [createdListing] = await this.conn.insert(businesses_json).values(newListing).returning();
|
||||||
listings=listings.filter(l=>l.type===criteria.type);
|
return createdListing as BusinessesJson;
|
||||||
}
|
|
||||||
if (convertStringToNullUndefined(criteria.state)){
|
|
||||||
console.log(criteria.state);
|
|
||||||
listings=listings.filter(l=>l.state===criteria.state);
|
|
||||||
}
|
|
||||||
if (convertStringToNullUndefined(criteria.minPrice)){
|
|
||||||
console.log(criteria.minPrice);
|
|
||||||
listings=listings.filter(l=>l.price>=Number(criteria.minPrice));
|
|
||||||
}
|
|
||||||
if (convertStringToNullUndefined(criteria.maxPrice)){
|
|
||||||
console.log(criteria.maxPrice);
|
|
||||||
listings=listings.filter(l=>l.price<=Number(criteria.maxPrice));
|
|
||||||
}
|
|
||||||
if (convertStringToNullUndefined(criteria.realEstateChecked)){
|
|
||||||
console.log(criteria.realEstateChecked);
|
|
||||||
listings=listings.filter(l=>l.realEstateIncluded);
|
|
||||||
}
|
|
||||||
if (convertStringToNullUndefined(criteria.category)){
|
|
||||||
console.log(criteria.category);
|
|
||||||
listings=listings.filter(l=>l.category===criteria.category);
|
|
||||||
}
|
|
||||||
return listings
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateImageOrder(id:string,imageOrder: ImageProperty[]){
|
async updateListing(id: string, data: BusinessListing): Promise<BusinessesJson> {
|
||||||
const listing = await this.getCommercialPropertyListingById(id) as unknown as CommercialPropertyListing
|
const [updateListing] = await this.conn.update(businesses_json).set(data).where(eq(businesses_json.id, id)).returning();
|
||||||
listing.imageOrder=imageOrder;
|
return updateListing as BusinessesJson;
|
||||||
this.saveListing(listing);
|
|
||||||
}
|
}
|
||||||
async deleteImage(listingid:string,name:string,){
|
|
||||||
const listing = await this.getCommercialPropertyListingById(listingid) as unknown as CommercialPropertyListing
|
async deleteListing(id: string): Promise<void> {
|
||||||
const index = listing.imageOrder.findIndex(im=>im.name===name);
|
await this.conn.delete(businesses_json).where(eq(businesses_json.id, id));
|
||||||
if (index>-1){
|
|
||||||
listing.imageOrder.splice(index,1);
|
|
||||||
this.saveListing(listing);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
async addImage(id:string,imagename: string){
|
|
||||||
const listing = await this.getCommercialPropertyListingById(id) as unknown as CommercialPropertyListing
|
async findByPriceRange(minPrice: number, maxPrice: number): Promise<BusinessesJson[]> {
|
||||||
listing.imageOrder.push({name:imagename,code:'',id:''});
|
return this.conn.select().from(businesses_json).where(sql`${businesses_json.data}->>'price' BETWEEN ${minPrice} AND ${maxPrice}`);
|
||||||
this.saveListing(listing);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async findByState(state: string): Promise<BusinessesJson[]> {
|
||||||
|
return this.conn.select().from(businesses_json).where(sql`${businesses_json.data}->>'state' = ${state}`);
|
||||||
|
}
|
||||||
|
async findById(id: string): Promise<BusinessesJson[]> {
|
||||||
|
return this.conn.select().from(businesses_json).where(sql`${businesses_json.id} = ${id}`);
|
||||||
|
}
|
||||||
|
async findByUserId(userId: string): Promise<BusinessesJson[]> {
|
||||||
|
return this.conn.select().from(businesses_json).where(sql`${businesses_json.data}->>'userId' = ${userId}`);
|
||||||
|
}
|
||||||
|
// async findByTitleContains(title: string): Promise<BusinessesJson[]> {
|
||||||
|
// return this.conn.select().from(businesses_json).where(ilike(sql`${businesses_json.data}->>'title'`, `%${title}%`));
|
||||||
|
// }
|
||||||
|
async findByTitleContains(title: string): Promise<BusinessesJson[]> {
|
||||||
|
return this.conn.select().from(businesses_json).where(sql`${businesses_json.data}->>'title' ILIKE '%' || ${title} || '%'`);
|
||||||
|
}
|
||||||
|
async findListings(start = 0, size = 48): Promise<{ data: Record<string, any>[]; total: number }> {
|
||||||
|
// return this.conn.select({ data: businesses_json.data }).from(businesses_json).offset(start).limit(size);
|
||||||
|
const [data, total] = await Promise.all([
|
||||||
|
this.conn.select({ data: businesses_json.data }).from(businesses_json).offset(start).limit(size),
|
||||||
|
this.conn.select({ count: sql`count(*)` }).from(businesses_json).then((result) => Number(result[0].count)),
|
||||||
|
]);
|
||||||
|
return { data, total };
|
||||||
|
}
|
||||||
|
// ##############################################################
|
||||||
|
// ##############################################################
|
||||||
|
// async saveListing(listing: BusinessListing | CommercialPropertyListing) {
|
||||||
|
// const repo=listing.listingsCategory==='business'?this.businessListingRepository:this.commercialPropertyListingRepository;
|
||||||
|
// let result
|
||||||
|
// if (listing.id){
|
||||||
|
// result = await repo.save(listing.id,listing as any)
|
||||||
|
// } else {
|
||||||
|
// result = await repo.save(listing as any)
|
||||||
|
// listing.id=result[EntityId];
|
||||||
|
// result = await repo.save(listing.id,listing as any)
|
||||||
|
// }
|
||||||
|
// return result;
|
||||||
|
// }
|
||||||
|
// async getCommercialPropertyListingById(id: string): Promise<CommercialPropertyListing>{
|
||||||
|
// return await this.commercialPropertyListingRepository.fetch(id) as unknown as CommercialPropertyListing;
|
||||||
|
// }
|
||||||
|
// async getBusinessListingById(id: string) {
|
||||||
|
// return await this.businessListingRepository.fetch(id)
|
||||||
|
// }
|
||||||
|
// async getBusinessListingByUserId(userid:string){
|
||||||
|
// return await this.businessListingRepository.search().where('userId').equals(userid).return.all()
|
||||||
|
// }
|
||||||
|
// async deleteBusinessListing(id: string){
|
||||||
|
// return await this.businessListingRepository.remove(id);
|
||||||
|
// }
|
||||||
|
// async deleteCommercialPropertyListing(id: string){
|
||||||
|
// return await this.commercialPropertyListingRepository.remove(id);
|
||||||
|
// }
|
||||||
|
// async getAllBusinessListings(start?: number, end?: number) {
|
||||||
|
// return await this.businessListingRepository.search().return.all()
|
||||||
|
// }
|
||||||
|
// async getAllCommercialListings(start?: number, end?: number) {
|
||||||
|
// return await this.commercialPropertyListingRepository.search().return.all()
|
||||||
|
// }
|
||||||
|
// async findBusinessListings(criteria:ListingCriteria): Promise<any> {
|
||||||
|
// // let listings = await this.getAllBusinessListings();
|
||||||
|
// // return this.find(criteria,listings);
|
||||||
|
// const from=criteria.start?criteria.start:0
|
||||||
|
// const size=criteria.length?criteria.length:24
|
||||||
|
// this.logger.info(`start findBusinessListings: ${JSON.stringify(criteria)}`);
|
||||||
|
// const result = await this.redis.ft.search('business:index','*',{LIMIT:{from,size}});
|
||||||
|
// this.logger.info(`start findBusinessListings: ${JSON.stringify(criteria)}`);
|
||||||
|
// return result
|
||||||
|
// }
|
||||||
|
// async findCommercialPropertyListings(criteria:ListingCriteria): Promise<any> {
|
||||||
|
// let listings = await this.getAllCommercialListings();
|
||||||
|
// return this.find(criteria,listings);
|
||||||
|
// }
|
||||||
|
// async deleteAllBusinessListings(){
|
||||||
|
// const ids = await this.getIdsForRepo(this.schemaNameBusiness.name);
|
||||||
|
// this.businessListingRepository.remove(ids);
|
||||||
|
// }
|
||||||
|
// async deleteAllcommercialListings(){
|
||||||
|
// const ids = await this.getIdsForRepo(this.schemaNameCommercial.name);
|
||||||
|
// this.commercialPropertyListingRepository.remove(ids);
|
||||||
|
// }
|
||||||
|
// async getIdsForRepo(repoName:string, maxcount=100000){
|
||||||
|
// let cursor = 0;
|
||||||
|
// let ids = [];
|
||||||
|
// do {
|
||||||
|
// const reply = await this.redis.scan(cursor, {
|
||||||
|
// MATCH: `${repoName}:*`,
|
||||||
|
// COUNT: maxcount
|
||||||
|
// });
|
||||||
|
// cursor = reply.cursor;
|
||||||
|
// // Extrahiere die ID aus jedem Schlüssel und füge sie zur Liste hinzu
|
||||||
|
// ids = ids.concat(reply.keys.map(key => key.split(':')[1]).filter(id=>id!='index'));
|
||||||
|
// } while (cursor !== 0);
|
||||||
|
// return ids;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// async find(criteria:ListingCriteria, listings: any[]): Promise<any> {
|
||||||
|
// listings=listings.filter(l=>l.listingsCategory===criteria.listingsCategory);
|
||||||
|
// if (convertStringToNullUndefined(criteria.type)){
|
||||||
|
// console.log(criteria.type);
|
||||||
|
// listings=listings.filter(l=>l.type===criteria.type);
|
||||||
|
// }
|
||||||
|
// if (convertStringToNullUndefined(criteria.state)){
|
||||||
|
// console.log(criteria.state);
|
||||||
|
// listings=listings.filter(l=>l.state===criteria.state);
|
||||||
|
// }
|
||||||
|
// if (convertStringToNullUndefined(criteria.minPrice)){
|
||||||
|
// console.log(criteria.minPrice);
|
||||||
|
// listings=listings.filter(l=>l.price>=Number(criteria.minPrice));
|
||||||
|
// }
|
||||||
|
// if (convertStringToNullUndefined(criteria.maxPrice)){
|
||||||
|
// console.log(criteria.maxPrice);
|
||||||
|
// listings=listings.filter(l=>l.price<=Number(criteria.maxPrice));
|
||||||
|
// }
|
||||||
|
// if (convertStringToNullUndefined(criteria.realEstateChecked)){
|
||||||
|
// console.log(criteria.realEstateChecked);
|
||||||
|
// listings=listings.filter(l=>l.realEstateIncluded);
|
||||||
|
// }
|
||||||
|
// if (convertStringToNullUndefined(criteria.category)){
|
||||||
|
// console.log(criteria.category);
|
||||||
|
// listings=listings.filter(l=>l.category===criteria.category);
|
||||||
|
// }
|
||||||
|
// return listings
|
||||||
|
// }
|
||||||
|
|
||||||
|
// async updateImageOrder(id:string,imageOrder: ImageProperty[]){
|
||||||
|
// const listing = await this.getCommercialPropertyListingById(id) as unknown as CommercialPropertyListing
|
||||||
|
// listing.imageOrder=imageOrder;
|
||||||
|
// this.saveListing(listing);
|
||||||
|
// }
|
||||||
|
// async deleteImage(listingid:string,name:string,){
|
||||||
|
// const listing = await this.getCommercialPropertyListingById(listingid) as unknown as CommercialPropertyListing
|
||||||
|
// const index = listing.imageOrder.findIndex(im=>im.name===name);
|
||||||
|
// if (index>-1){
|
||||||
|
// listing.imageOrder.splice(index,1);
|
||||||
|
// this.saveListing(listing);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// async addImage(id:string,imagename: string){
|
||||||
|
// const listing = await this.getCommercialPropertyListingById(id) as unknown as CommercialPropertyListing
|
||||||
|
// listing.imageOrder.push({name:imagename,code:'',id:''});
|
||||||
|
// this.saveListing(listing);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,18 +12,18 @@ export class UnknownListingsController {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Get(':id')
|
// @Get(':id')
|
||||||
async findById(@Param('id') id:string): Promise<any> {
|
// async findById(@Param('id') id:string): Promise<any> {
|
||||||
const result = await this.listingsService.getBusinessListingById(id);
|
// const result = await this.listingsService.getBusinessListingById(id);
|
||||||
if (result.id){
|
// if (result.id){
|
||||||
return result
|
// return result
|
||||||
} else {
|
// } else {
|
||||||
return await this.listingsService.getCommercialPropertyListingById(id);
|
// return await this.listingsService.getCommercialPropertyListingById(id);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
@Get('repo/:repo')
|
// @Get('repo/:repo')
|
||||||
async getAllByRepo(@Param('repo') repo:string): Promise<any> {
|
// async getAllByRepo(@Param('repo') repo:string): Promise<any> {
|
||||||
return await this.listingsService.getIdsForRepo(repo);
|
// return await this.listingsService.getIdsForRepo(repo);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,22 +3,23 @@ import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
providers: [
|
providers: [
|
||||||
{
|
// {
|
||||||
provide: 'REDIS_OPTIONS',
|
// provide: 'REDIS_OPTIONS',
|
||||||
useValue: {
|
// useValue: {
|
||||||
url: 'redis://localhost:6379'
|
// url: 'redis://localhost:6379'
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
inject: ['REDIS_OPTIONS'],
|
// inject: ['REDIS_OPTIONS'],
|
||||||
provide: 'REDIS_CLIENT',
|
// provide: 'REDIS_CLIENT',
|
||||||
useFactory: async (options: { url: string }) => {
|
// useFactory: async (options: { url: string }) => {
|
||||||
const client = createClient(options);
|
// const client = createClient(options);
|
||||||
await client.connect();
|
// await client.connect();
|
||||||
return client;
|
// return client;
|
||||||
}
|
// }
|
||||||
}],
|
// }
|
||||||
exports:['REDIS_CLIENT']
|
],
|
||||||
|
// exports:['REDIS_CLIENT']
|
||||||
})
|
})
|
||||||
export class RedisModule {}
|
export class RedisModule {}
|
||||||
export const REDIS_CLIENT = "REDIS_CLIENT";
|
export const REDIS_CLIENT = "REDIS_CLIENT";
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { Injectable, NestMiddleware, Logger } from '@nestjs/common';
|
||||||
|
import { Request, Response, NextFunction } from 'express';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class RequestDurationMiddleware implements NestMiddleware {
|
||||||
|
private readonly logger = new Logger(RequestDurationMiddleware.name);
|
||||||
|
|
||||||
|
use(req: Request, res: Response, next: NextFunction) {
|
||||||
|
const start = Date.now();
|
||||||
|
res.on('finish', () => {
|
||||||
|
const duration = Date.now() - start;
|
||||||
|
this.logger.log(`${req.method} ${req.url} - ${duration}ms`);
|
||||||
|
});
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -25,9 +25,9 @@ export class UserService {
|
||||||
}, {
|
}, {
|
||||||
dataStructure: 'JSON'
|
dataStructure: 'JSON'
|
||||||
})
|
})
|
||||||
constructor(@Inject(REDIS_CLIENT) private readonly redis: any,private fileService:FileService){
|
constructor(private fileService:FileService){
|
||||||
this.userRepository = new Repository(this.userSchema, redis)
|
// this.userRepository = new Repository(this.userSchema, redis)
|
||||||
this.userRepository.createIndex();
|
// this.userRepository.createIndex();
|
||||||
}
|
}
|
||||||
async getUserById( id:string){
|
async getUserById( id:string){
|
||||||
const user = await this.userRepository.fetch(id) as UserEntity;
|
const user = await this.userRepository.fetch(id) as UserEntity;
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@
|
||||||
<div class="surface-200 h-full">
|
<div class="surface-200 h-full">
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
@for (listing of filteredListings; track listing.id) {
|
@for (listing of listings; track listing.id) {
|
||||||
<div *ngIf="listing.listingsCategory==='business'" class="col-12 lg:col-3 p-3">
|
<div *ngIf="listing.listingsCategory==='business'" class="col-12 lg:col-3 p-3">
|
||||||
<div class="shadow-2 border-round surface-card mb-3 h-full flex-column justify-content-between flex">
|
<div class="shadow-2 border-round surface-card mb-3 h-full flex-column justify-content-between flex">
|
||||||
<div class="p-4 h-full flex flex-column">
|
<div class="p-4 h-full flex flex-column">
|
||||||
|
|
|
||||||
|
|
@ -73,10 +73,11 @@ export class ListingsComponent {
|
||||||
if (this.category==='business' || this.category==='commercialProperty'){
|
if (this.category==='business' || this.category==='commercialProperty'){
|
||||||
this.users=[]
|
this.users=[]
|
||||||
this.listings=await this.listingsService.getListings(this.criteria);
|
this.listings=await this.listingsService.getListings(this.criteria);
|
||||||
|
|
||||||
this.setStates();
|
this.setStates();
|
||||||
this.filteredListings=[...this.listings];
|
//this.filteredListings=[...this.listings];
|
||||||
this.totalRecords=this.listings.length
|
this.totalRecords=this.listings.length
|
||||||
this.filteredListings=[...this.listings].splice(this.first,this.rows);
|
//this.filteredListings=[...this.listings].splice(this.first,this.rows);
|
||||||
this.cdRef.markForCheck();
|
this.cdRef.markForCheck();
|
||||||
this.cdRef.detectChanges();
|
this.cdRef.detectChanges();
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -112,9 +113,13 @@ export class ListingsComponent {
|
||||||
this.cdRef.detectChanges();
|
this.cdRef.detectChanges();
|
||||||
}
|
}
|
||||||
onPageChange(event: any) {
|
onPageChange(event: any) {
|
||||||
this.first = event.first;
|
//this.first = event.first;
|
||||||
this.rows = event.rows;
|
//this.rows = event.rows;
|
||||||
this.filteredListings=[...this.listings].splice(this.first,this.rows);
|
//this.filteredListings=[...this.listings].splice(this.first,this.rows);
|
||||||
|
this.criteria.start=event.first;
|
||||||
|
this.criteria.length=event.rows;
|
||||||
|
this.criteria.page=event.page;
|
||||||
|
this.criteria.pageCount=event.pageCount;
|
||||||
}
|
}
|
||||||
imageErrorHandler(listing: ListingType) {
|
imageErrorHandler(listing: ListingType) {
|
||||||
listing.hideImage = true; // Bild ausblenden, wenn es nicht geladen werden kann
|
listing.hideImage = true; // Bild ausblenden, wenn es nicht geladen werden kann
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,10 @@ export type ListingType =
|
||||||
| CommercialPropertyListing;
|
| CommercialPropertyListing;
|
||||||
|
|
||||||
export interface ListingCriteria {
|
export interface ListingCriteria {
|
||||||
|
start:number,
|
||||||
|
length:number,
|
||||||
|
page:number,
|
||||||
|
pageCount:number,
|
||||||
type:string,
|
type:string,
|
||||||
state:string,
|
state:string,
|
||||||
minPrice:string,
|
minPrice:string,
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1 @@
|
||||||
|
[]
|
||||||
|
|
@ -11,17 +11,20 @@
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"typescript": "^5.2.2"
|
"typescript": "^5.4.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@types/node": "^20.12.7",
|
||||||
"currency.js": "^2.0.4",
|
"currency.js": "^2.0.4",
|
||||||
"fs-extra": "^11.2.0",
|
"fs-extra": "^11.2.0",
|
||||||
"inquirer": "^9.2.17",
|
"inquirer": "^9.2.17",
|
||||||
"ioredis": "^5.3.2",
|
"ioredis": "^5.3.2",
|
||||||
"node-fetch": "^3.3.2",
|
"node-fetch": "^3.3.2",
|
||||||
|
"pg": "^8.11.5",
|
||||||
"puppeteer": "^22.1.0",
|
"puppeteer": "^22.1.0",
|
||||||
"redis": "^4.6.13",
|
"redis": "^4.6.13",
|
||||||
"redis-om": "^0.4.3",
|
"redis-om": "^0.4.3",
|
||||||
|
"uuidv4": "^6.2.13",
|
||||||
"winston": "^3.13.0",
|
"winston": "^3.13.0",
|
||||||
"yargs": "^17.7.2"
|
"yargs": "^17.7.2"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
import pkg from 'pg';
|
||||||
|
const { Pool } = pkg;
|
||||||
|
import fsextra from 'fs-extra';
|
||||||
|
const { fstat, readFileSync, writeJsonSync } = fsextra;
|
||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
// PostgreSQL Verbindungskonfiguration
|
||||||
|
const pool = new Pool({
|
||||||
|
user: 'bizmatch',
|
||||||
|
host: 'localhost',
|
||||||
|
database: 'bizmatch',
|
||||||
|
password: 'xieng7Seih',
|
||||||
|
port: 5432,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Typdefinition für das JSON-Objekt
|
||||||
|
interface BusinessListing {
|
||||||
|
userId?: string;
|
||||||
|
listingsCategory: string;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
type: string;
|
||||||
|
state: string;
|
||||||
|
city: string;
|
||||||
|
id: string;
|
||||||
|
price: number;
|
||||||
|
salesRevenue: number;
|
||||||
|
leasedLocation: boolean;
|
||||||
|
established: number;
|
||||||
|
employees: number;
|
||||||
|
reasonForSale: string;
|
||||||
|
supportAndTraining: string;
|
||||||
|
cashFlow: number;
|
||||||
|
brokerLicencing: string;
|
||||||
|
internalListingNumber: number;
|
||||||
|
realEstateIncluded: boolean;
|
||||||
|
franchiseResale: boolean;
|
||||||
|
draft: boolean;
|
||||||
|
internals: string;
|
||||||
|
created: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Funktion zum Einlesen und Importieren von JSON-Daten
|
||||||
|
async function importJsonData(filePath: string): Promise<void> {
|
||||||
|
try {
|
||||||
|
const data: string = readFileSync(filePath, 'utf8');
|
||||||
|
const jsonData: BusinessListing[] = JSON.parse(data); // Erwartet ein Array von Objekten
|
||||||
|
const out: BusinessListing[] =[]
|
||||||
|
// Daten für jedes Listing in die Datenbank einfügen
|
||||||
|
for (const listing of jsonData) {
|
||||||
|
// const uuid = uuidv4();
|
||||||
|
// listing.id=uuid;
|
||||||
|
const values = [
|
||||||
|
listing.userId, listing.listingsCategory, listing.title, listing.description,
|
||||||
|
listing.type, listing.state, listing.city, listing.id, listing.price, listing.salesRevenue,
|
||||||
|
listing.leasedLocation, listing.established, listing.employees,
|
||||||
|
listing.reasonForSale, listing.supportAndTraining, listing.cashFlow, listing.brokerLicencing,
|
||||||
|
listing.internalListingNumber, listing.realEstateIncluded, listing.franchiseResale,
|
||||||
|
listing.draft, listing.internals, listing.created, new Date(), 0, null
|
||||||
|
];
|
||||||
|
const json_values = [
|
||||||
|
listing.id, listing
|
||||||
|
]
|
||||||
|
|
||||||
|
await pool.query(`INSERT INTO businesses
|
||||||
|
(user_id, listings_category, title, description, type, state, city, id, price, sales_revenue, leased_location,
|
||||||
|
established, employees, reason_for_sale, support_and_training, cash_flow, broker_licencing, internal_listing_number,
|
||||||
|
real_estate_included, franchise_resale, draft, internals, created, updated, visits, last_visit)
|
||||||
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26)`, values);
|
||||||
|
|
||||||
|
await pool.query('INSERT INTO businesses_json (id, data) VALUES ($1,$2)', json_values);
|
||||||
|
|
||||||
|
// out.push(listing);
|
||||||
|
}
|
||||||
|
writeJsonSync('./data/businesses_.json',out);
|
||||||
|
console.log('All data imported successfully.');
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error importing data:', err.message);
|
||||||
|
} finally {
|
||||||
|
// Schließen der Verbindung zum Pool
|
||||||
|
await pool.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Passen Sie den Dateipfad an Ihre spezifischen Bedürfnisse an
|
||||||
|
importJsonData('./data/businesses_.json');
|
||||||
Loading…
Reference in New Issue