diff --git a/bizmatch-server/src/listings/business-listing.service.ts b/bizmatch-server/src/listings/business-listing.service.ts index fecc507..28cd72d 100644 --- a/bizmatch-server/src/listings/business-listing.service.ts +++ b/bizmatch-server/src/listings/business-listing.service.ts @@ -21,7 +21,7 @@ export class BusinessListingService { private geoService?: GeoService, ) {} - private getWhereConditions(criteria: BusinessListingCriteria): SQL[] { + private getWhereConditions(criteria: BusinessListingCriteria, user: JwtUser): SQL[] { const whereConditions: SQL[] = []; if (criteria.city && criteria.searchType === 'exact') { @@ -98,6 +98,9 @@ export class BusinessListingService { if (criteria.brokerName) { whereConditions.push(or(ilike(schema.users.firstname, `%${criteria.brokerName}%`), ilike(schema.users.lastname, `%${criteria.brokerName}%`))); } + if (!user?.roles?.includes('ADMIN') ?? false) { + whereConditions.push(or(eq(businesses.email, user?.username), ne(businesses.draft, true))); + } whereConditions.push(and(eq(schema.users.customerType, 'professional'), eq(schema.users.customerSubType, 'broker'))); return whereConditions; } @@ -113,7 +116,7 @@ export class BusinessListingService { .from(businesses) .leftJoin(schema.users, eq(businesses.email, schema.users.email)); - const whereConditions = this.getWhereConditions(criteria); + const whereConditions = this.getWhereConditions(criteria, user); if (whereConditions.length > 0) { const whereClause = and(...whereConditions); @@ -124,7 +127,7 @@ export class BusinessListingService { query.limit(length).offset(start); const data = await query; - const totalCount = await this.getBusinessListingsCount(criteria); + const totalCount = await this.getBusinessListingsCount(criteria, user); const results = data.map(r => r.business).map(r => convertDrizzleBusinessToBusiness(r)); return { results, @@ -132,10 +135,10 @@ export class BusinessListingService { }; } - async getBusinessListingsCount(criteria: BusinessListingCriteria): Promise { + async getBusinessListingsCount(criteria: BusinessListingCriteria, user: JwtUser): Promise { const countQuery = this.conn.select({ value: count() }).from(businesses).leftJoin(schema.users, eq(businesses.email, schema.users.email)); - const whereConditions = this.getWhereConditions(criteria); + const whereConditions = this.getWhereConditions(criteria, user); if (whereConditions.length > 0) { const whereClause = and(...whereConditions); @@ -147,12 +150,20 @@ export class BusinessListingService { } async findBusinessesById(id: string, user: JwtUser): Promise { + const conditions = []; + if (!user?.roles?.includes('ADMIN') ?? false) { + conditions.push(or(eq(businesses.email, user?.username), ne(businesses.draft, true))); + } + conditions.push(sql`${businesses.id} = ${id}`); let result = await this.conn .select() .from(businesses) - .where(and(sql`${businesses.id} = ${id}`)); - result = result.filter(r => !r.draft || r.imageName === emailToDirName(user?.username) || user?.roles.includes('ADMIN')); - return convertDrizzleBusinessToBusiness(result[0]) as BusinessListing; + .where(and(...conditions)); + if (result.length > 0) { + return convertDrizzleBusinessToBusiness(result[0]) as BusinessListing; + } else { + throw new BadRequestException(`No entry available for ${id}`); + } } async findBusinessesByEmail(email: string, user: JwtUser): Promise { diff --git a/bizmatch-server/src/listings/business-listings.controller.ts b/bizmatch-server/src/listings/business-listings.controller.ts index 3260bdc..43d2110 100644 --- a/bizmatch-server/src/listings/business-listings.controller.ts +++ b/bizmatch-server/src/listings/business-listings.controller.ts @@ -30,15 +30,11 @@ export class BusinessListingsController { find(@Request() req, @Body() criteria: BusinessListingCriteria): any { return this.listingsService.searchBusinessListings(criteria, req.user as JwtUser); } + @UseGuards(OptionalJwtAuthGuard) @Post('findTotal') - findTotal(@Body() criteria: BusinessListingCriteria): Promise { - return this.listingsService.getBusinessListingsCount(criteria); + findTotal(@Request() req, @Body() criteria: BusinessListingCriteria): Promise { + return this.listingsService.getBusinessListingsCount(criteria, req.user as JwtUser); } - // @UseGuards(OptionalJwtAuthGuard) - // @Post('search') - // search(@Request() req, @Body() criteria: BusinessListingCriteria): any { - // return this.listingsService.searchBusinessListings(criteria.prompt); - // } @Post() create(@Body() listing: any) { diff --git a/bizmatch-server/src/listings/commercial-property-listings.controller.ts b/bizmatch-server/src/listings/commercial-property-listings.controller.ts index 67bbb48..a681474 100644 --- a/bizmatch-server/src/listings/commercial-property-listings.controller.ts +++ b/bizmatch-server/src/listings/commercial-property-listings.controller.ts @@ -31,9 +31,10 @@ export class CommercialPropertyListingsController { async find(@Request() req, @Body() criteria: CommercialPropertyListingCriteria): Promise { return await this.listingsService.searchCommercialProperties(criteria, req.user as JwtUser); } + @UseGuards(OptionalJwtAuthGuard) @Post('findTotal') - findTotal(@Body() criteria: CommercialPropertyListingCriteria): Promise { - return this.listingsService.getCommercialPropertiesCount(criteria); + findTotal(@Request() req, @Body() criteria: CommercialPropertyListingCriteria): Promise { + return this.listingsService.getCommercialPropertiesCount(criteria, req.user as JwtUser); } @Get('states/all') getStates(): any { diff --git a/bizmatch-server/src/listings/commercial-property.service.ts b/bizmatch-server/src/listings/commercial-property.service.ts index 789181e..023c6d2 100644 --- a/bizmatch-server/src/listings/commercial-property.service.ts +++ b/bizmatch-server/src/listings/commercial-property.service.ts @@ -20,7 +20,7 @@ export class CommercialPropertyService { private fileService?: FileService, private geoService?: GeoService, ) {} - private getWhereConditions(criteria: CommercialPropertyListingCriteria): SQL[] { + private getWhereConditions(criteria: CommercialPropertyListingCriteria, user: JwtUser): SQL[] { const whereConditions: SQL[] = []; if (criteria.city && criteria.searchType === 'exact') { @@ -49,6 +49,9 @@ export class CommercialPropertyService { if (criteria.title) { whereConditions.push(or(ilike(schema.commercials.title, `%${criteria.title}%`), ilike(schema.commercials.description, `%${criteria.title}%`))); } + if (!user?.roles?.includes('ADMIN') ?? false) { + whereConditions.push(or(eq(commercials.email, user?.username), ne(commercials.draft, true))); + } whereConditions.push(and(eq(schema.users.customerType, 'professional'))); return whereConditions; } @@ -57,7 +60,7 @@ export class CommercialPropertyService { const start = criteria.start ? criteria.start : 0; const length = criteria.length ? criteria.length : 12; const query = this.conn.select({ commercial: commercials }).from(commercials).leftJoin(schema.users, eq(commercials.email, schema.users.email)); - const whereConditions = this.getWhereConditions(criteria); + const whereConditions = this.getWhereConditions(criteria, user); if (whereConditions.length > 0) { const whereClause = and(...whereConditions); @@ -69,16 +72,16 @@ export class CommercialPropertyService { const data = await query; const results = data.map(r => r.commercial).map(r => convertDrizzleCommercialToCommercial(r)); - const totalCount = await this.getCommercialPropertiesCount(criteria); + const totalCount = await this.getCommercialPropertiesCount(criteria, user); return { results, totalCount, }; } - async getCommercialPropertiesCount(criteria: CommercialPropertyListingCriteria): Promise { + async getCommercialPropertiesCount(criteria: CommercialPropertyListingCriteria, user: JwtUser): Promise { const countQuery = this.conn.select({ value: count() }).from(schema.commercials).leftJoin(schema.users, eq(commercials.email, schema.users.email)); - const whereConditions = this.getWhereConditions(criteria); + const whereConditions = this.getWhereConditions(criteria, user); if (whereConditions.length > 0) { const whereClause = and(...whereConditions); @@ -91,12 +94,20 @@ export class CommercialPropertyService { // #### Find by ID ######################################## async findCommercialPropertiesById(id: string, user: JwtUser): Promise { + const conditions = []; + if (!user?.roles?.includes('ADMIN') ?? false) { + conditions.push(or(eq(commercials.email, user?.username), ne(commercials.draft, true))); + } + conditions.push(sql`${commercials.id} = ${id}`); let result = await this.conn .select() .from(commercials) - .where(and(sql`${commercials.id} = ${id}`)); - result = result.filter(r => !r.draft || r.imagePath === emailToDirName(user?.username) || user?.roles.includes('ADMIN')); - return convertDrizzleCommercialToCommercial(result[0]) as CommercialPropertyListing; + .where(and(...conditions)); + if (result.length > 0) { + return convertDrizzleCommercialToCommercial(result[0]) as CommercialPropertyListing; + } else { + throw new BadRequestException(`No entry available for ${id}`); + } } // #### Find by User EMail ######################################## diff --git a/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.ts b/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.ts index 2688010..7e2f407 100644 --- a/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.ts +++ b/bizmatch/src/app/pages/details/details-business-listing/details-business-listing.component.ts @@ -83,9 +83,13 @@ export class DetailsBusinessListingComponent { this.user = await this.userService.getByMail(this.keycloakUser.email); this.mailinfo = createMailInfo(this.user); } - this.listing = await lastValueFrom(this.listingsService.getListingById(this.id, 'business')); - this.listingUser = await this.userService.getByMail(this.listing.email); - this.description = this.sanitizer.bypassSecurityTrustHtml(this.listing.description); + try { + this.listing = await lastValueFrom(this.listingsService.getListingById(this.id, 'business')); + this.listingUser = await this.userService.getByMail(this.listing.email); + this.description = this.sanitizer.bypassSecurityTrustHtml(this.listing.description); + } catch (error) { + console.log(error); + } } ngOnDestroy() { this.validationMessagesService.clearMessages(); // Löschen Sie alle bestehenden Validierungsnachrichten @@ -120,7 +124,7 @@ export class DetailsBusinessListingComponent { } else if (this.listing.franchiseResale) { typeOfRealEstate = 'Franchise Re-Sale'; } - return [ + const result = [ { label: 'Category', value: this.selectOptions.getBusiness(this.listing.type) }, { label: 'Located in', value: `${this.listing.location.name}, ${this.selectOptions.getState(this.listing.location.state)}` }, { label: 'Asking Price', value: `$${this.listing.price?.toLocaleString()}` }, @@ -133,5 +137,9 @@ export class DetailsBusinessListingComponent { { label: 'Reason for Sale', value: this.listing.reasonForSale }, { label: 'Broker licensing', value: this.listing.brokerLicencing }, ]; + if (this.listing.draft) { + result.push({ label: 'Draft', value: this.listing.draft ? 'Yes' : 'No' }); + } + return result; } } diff --git a/bizmatch/src/app/pages/details/details-commercial-property-listing/details-commercial-property-listing.component.html b/bizmatch/src/app/pages/details/details-commercial-property-listing/details-commercial-property-listing.component.html index 9a3e417..54385e0 100644 --- a/bizmatch/src/app/pages/details/details-commercial-property-listing/details-commercial-property-listing.component.html +++ b/bizmatch/src/app/pages/details/details-commercial-property-listing/details-commercial-property-listing.component.html @@ -99,6 +99,7 @@
+ @if(listing){

{{ listing?.title }}

+ }
diff --git a/bizmatch/src/app/pages/details/details-commercial-property-listing/details-commercial-property-listing.component.ts b/bizmatch/src/app/pages/details/details-commercial-property-listing/details-commercial-property-listing.component.ts index 8c1c4cf..b04c440 100644 --- a/bizmatch/src/app/pages/details/details-commercial-property-listing/details-commercial-property-listing.component.ts +++ b/bizmatch/src/app/pages/details/details-commercial-property-listing/details-commercial-property-listing.component.ts @@ -88,18 +88,26 @@ export class DetailsCommercialPropertyListingComponent { this.user = await this.userService.getByMail(this.keycloakUser.email); this.mailinfo = createMailInfo(this.user); } - this.listing = (await lastValueFrom(this.listingsService.getListingById(this.id, 'commercialProperty'))) as CommercialPropertyListing; - this.listingUser = await this.userService.getByMail(this.listing.email); - this.description = this.sanitizer.bypassSecurityTrustHtml(this.listing.description); - import('flowbite').then(flowbite => { - flowbite.initCarousels(); - }); - this.propertyDetails = [ - { label: 'Property Category', value: this.selectOptions.getCommercialProperty(this.listing.type) }, - { label: 'Located in', value: this.selectOptions.getState(this.listing.location.state) }, - { label: 'City', value: this.listing.location.name }, - { label: 'Asking Price:', value: `$${this.listing.price?.toLocaleString()}` }, - ]; + try { + this.listing = (await lastValueFrom(this.listingsService.getListingById(this.id, 'commercialProperty'))) as CommercialPropertyListing; + this.listingUser = await this.userService.getByMail(this.listing.email); + this.description = this.sanitizer.bypassSecurityTrustHtml(this.listing.description); + import('flowbite').then(flowbite => { + flowbite.initCarousels(); + }); + this.propertyDetails = [ + { label: 'Property Category', value: this.selectOptions.getCommercialProperty(this.listing.type) }, + { label: 'Located in', value: this.selectOptions.getState(this.listing.location.state) }, + { label: 'City', value: this.listing.location.name }, + { label: 'Asking Price:', value: `$${this.listing.price?.toLocaleString()}` }, + ]; + if (this.listing.draft) { + this.propertyDetails.push({ label: 'Draft', value: this.listing.draft ? 'Yes' : 'No' }); + } + } catch (error) { + console.log(error); + } + //this.initFlowbite(); } ngOnDestroy() { diff --git a/bizmatch/src/app/pages/details/details-user/details-user.component.html b/bizmatch/src/app/pages/details/details-user/details-user.component.html index 1b93daf..e0e81e3 100644 --- a/bizmatch/src/app/pages/details/details-user/details-user.component.html +++ b/bizmatch/src/app/pages/details/details-user/details-user.component.html @@ -218,7 +218,7 @@

Areas (Counties) we serve

@for (area of user.areasServed; track area) { - {{ area.county }}-{{ area.state }} + {{ area.county }}{{ area.county ? '-' : '' }}{{ area.state }} }
@@ -251,25 +251,23 @@ } @if(commercialPropListings?.length>0){ -
-

My Commercial Property Listings For Sale

-
- @for (listing of commercialPropListings; track listing) { -
-
- @if (listing.imageOrder?.length>0){ - - } @else { - - } -
-

{{ selectOptions.getCommercialProperty(listing.type) }}

-

{{ listing.title }}

-
+

My Commercial Property Listings For Sale

+
+ @for (listing of commercialPropListings; track listing) { +
+
+ @if (listing.imageOrder?.length>0){ + + } @else { + + } +
+

{{ selectOptions.getCommercialProperty(listing.type) }}

+

{{ listing.title }}

- }
+ }
} @if( user?.email===keycloakUser?.email || isAdmin()){ diff --git a/bizmatch/src/app/pages/listings/business-listings/business-listings.component.html b/bizmatch/src/app/pages/listings/business-listings/business-listings.component.html index aedb278..f4d5f12 100644 --- a/bizmatch/src/app/pages/listings/business-listings/business-listings.component.html +++ b/bizmatch/src/app/pages/listings/business-listings/business-listings.component.html @@ -95,7 +95,12 @@ {{ selectOptions.getBusiness(listing.type) }}
-

{{ listing.title }}

+

+ {{ listing.title }} + @if(listing.draft){ + Draft + } +

Asking price: {{ listing.price | currency }}

Sales revenue: {{ listing.salesRevenue | currency }}

Net profit: {{ listing.cashFlow | currency }}

diff --git a/bizmatch/src/app/pages/listings/commercial-property-listings/commercial-property-listings.component.html b/bizmatch/src/app/pages/listings/commercial-property-listings/commercial-property-listings.component.html index 8ccc704..3206ab5 100644 --- a/bizmatch/src/app/pages/listings/commercial-property-listings/commercial-property-listings.component.html +++ b/bizmatch/src/app/pages/listings/commercial-property-listings/commercial-property-listings.component.html @@ -12,7 +12,12 @@ {{ selectOptions.getState(listing.location.state) }} {{ selectOptions.getCommercialProperty(listing.type) }}
-

{{ listing.title }}

+

+ {{ listing.title }} + @if(listing.draft){ + Draft + } +

{{ listing.location.name }}

{{ listing.price | currency }}