Skip to content

Commit

Permalink
[enhance] CheckEvent controller with new query endpoints (#32)
Browse files Browse the repository at this point in the history
  • Loading branch information
Soecka authored Jan 7, 2025
1 parent 5b4a77b commit 93451bb
Show file tree
Hide file tree
Showing 4 changed files with 198 additions and 6 deletions.
2 changes: 1 addition & 1 deletion ReadMe.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ git push origin master --tags
[7]: https://typeorm.io/
[8]: https://swagger.io/
[9]: https://github.com/anttiviljami/openapi-backend
[10]: https://github.com/settings/tokens
[10]: https://github.com/settings/tokens/new?description=KYS-service&scopes=read:packages
[11]: https://www.postgresql.org/
[12]: https://azure.microsoft.com/en-us/products/storage/blobs
[13]: https://www.leancloud.cn/
Expand Down
62 changes: 61 additions & 1 deletion src/controller/CheckEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,41 @@ import {
ForbiddenError,
Get,
JsonController,
Param,
Post,
QueryParams
} from 'routing-controllers';
import { ResponseSchema } from 'routing-controllers-openapi';

import {
ActivityAgendaCheckInListChunk,
ActivityAgendaCheckInSummary,
ActivityCheckInListChunk,
ActivityCheckInSummary,
BaseFilter,
CheckEvent,
CheckEventChunk,
CheckEventFilter,
CheckEventInput,
dataSource,
User,
dataSource
UserActivityCheckInListChunk,
UserActivityCheckInSummary
} from '../model';
import { ActivityLogController } from './ActivityLog';
import { FindOptionsWhere } from 'typeorm';

@JsonController('/event/check')
export class CheckEventController {
store = dataSource.getRepository(CheckEvent);
userStore = dataSource.getRepository(User);
userActivityCheckInStore = dataSource.getRepository(
UserActivityCheckInSummary
);
activityCheckInStore = dataSource.getRepository(ActivityCheckInSummary);
activityAgendaCheckInStore = dataSource.getRepository(
ActivityAgendaCheckInSummary
);

@Post()
@Authorized()
Expand Down Expand Up @@ -79,4 +95,48 @@ export class CheckEventController {
});
return { list, count };
}

@Get('/user/:id')
@ResponseSchema(UserActivityCheckInListChunk)
async getCheckEventList(
@Param('id') id: number,
@QueryParams() { pageSize = 10, pageIndex = 1 }: BaseFilter
) {
const [list, count] = await this.userActivityCheckInStore.findAndCount({
where: { userId: id },
skip: pageSize * (pageIndex - 1),
take: pageSize
});

for (const item of list)
item.user = await this.userStore.findOneBy({ id: item.userId });
return { list, count };
}

@Get('/activity/:id')
@ResponseSchema(ActivityAgendaCheckInListChunk)
async getActivityCheckEventList(
@Param('id') id: string,
@QueryParams() { pageSize = 10, pageIndex = 1 }: BaseFilter
) {
const [list, count] =
await this.activityAgendaCheckInStore.findAndCount({
where: { activityId: id },
skip: pageSize * (pageIndex - 1),
take: pageSize
});
return { list, count };
}

@Get('/activity')
@ResponseSchema(ActivityCheckInListChunk)
async getAgendaCheckEventList(
@QueryParams() { pageSize = 10, pageIndex = 1 }: BaseFilter
) {
const [list, count] = await this.activityCheckInStore.findAndCount({
skip: pageSize * (pageIndex - 1),
take: pageSize
});
return { list, count };
}
}
121 changes: 120 additions & 1 deletion src/model/CheckEvent.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { Type } from 'class-transformer';
import {
IsEnum,
IsInt,
IsLatLong,
IsOptional,
IsString,
Min,
ValidateNested
} from 'class-validator';
import { Column, Entity, ManyToOne } from 'typeorm';
import { Column, Entity, ManyToOne, ViewColumn, ViewEntity } from 'typeorm';

import { BaseFilter, ListChunk } from './Base';
import { User, UserBase, UserInputData } from './User';
Expand Down Expand Up @@ -90,3 +91,121 @@ export class CheckEventChunk implements ListChunk<CheckEvent> {
@ValidateNested({ each: true })
list: CheckEvent[];
}

@ViewEntity({
expression: connection =>
connection
.createQueryBuilder()
.from(CheckEvent, 'ce')
.groupBy('ce.user.id, ce.activityId')
.select('ce.activityId', 'activityId')
.addSelect('ce.user.id', 'userId')
.addSelect('ce.activityName', 'activityName')
.addSelect('COUNT(ce.id)', 'checkCount')
})
export class UserActivityCheckInSummary {
@ViewColumn()
@IsInt()
@Min(1)
userId: number;

@ViewColumn()
@IsString()
activityId: string;

@ViewColumn()
@IsString()
activityName: string;

@ViewColumn()
@IsInt()
@Min(0)
checkCount: number;

@Type(() => User)
@ValidateNested()
user: User;
}

@ViewEntity({
expression: connection =>
connection
.createQueryBuilder()
.from(CheckEvent, 'ce')
.groupBy('ce.activityId')
.select('ce.activityId', 'activityId')
.addSelect('ce.activityName', 'activityName')
.addSelect('COUNT(ce.id)', 'checkCount')
})
export class ActivityCheckInSummary {
@ViewColumn()
@IsString()
activityId: string;

@ViewColumn()
@IsString()
activityName: string;

@ViewColumn()
@IsInt()
@Min(0)
checkCount: number;
}

@ViewEntity({
expression: connection =>
connection
.createQueryBuilder()
.from(CheckEvent, 'ce')
.groupBy('ce.activityId, ce.agendaId')
.select('ce.activityId', 'activityId')
.addSelect('ce.activityName', 'activityName')
.addSelect('ce.agendaId', 'agendaId')
.addSelect('ce.agendaTitle', 'agendaTitle')
.addSelect('COUNT(ce.id)', 'checkCount')
})
export class ActivityAgendaCheckInSummary extends ActivityCheckInSummary {
@ViewColumn()
@IsString()
agendaId: string;

@ViewColumn()
@IsString()
agendaTitle: string;
}

export class UserActivityCheckInListChunk
implements ListChunk<UserActivityCheckInSummary>
{
@IsInt()
@Min(0)
count: number;

@Type(() => UserActivityCheckInSummary)
@ValidateNested({ each: true })
list: UserActivityCheckInSummary[];
}

export class ActivityCheckInListChunk
implements ListChunk<ActivityCheckInSummary>
{
@IsInt()
@Min(0)
count: number;

@Type(() => ActivityCheckInSummary)
@ValidateNested({ each: true })
list: ActivityCheckInSummary[];
}

export class ActivityAgendaCheckInListChunk
implements ListChunk<ActivityAgendaCheckInSummary>
{
@IsInt()
@Min(0)
count: number;

@Type(() => ActivityAgendaCheckInSummary)
@ValidateNested({ each: true })
list: ActivityAgendaCheckInSummary[];
}
19 changes: 16 additions & 3 deletions src/model/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@ import { DataSource } from 'typeorm';
import { SqliteConnectionOptions } from 'typeorm/driver/sqlite/SqliteConnectionOptions';

import { DATABASE_URL, isProduct } from '../utility';
import { CheckEvent } from './CheckEvent';
import {
ActivityAgendaCheckInSummary,
ActivityCheckInSummary,
CheckEvent,
UserActivityCheckInSummary
} from './CheckEvent';
import { User } from './User';
import { ActivityLog } from './ActivityLog';
import { ActivityLog, UserRank } from './ActivityLog';

export * from './Base';
export * from './CheckEvent';
Expand All @@ -24,7 +29,15 @@ const commonOptions: Pick<
> = {
logging: true,
synchronize: true,
entities: [User, ActivityLog, CheckEvent],
entities: [
User,
UserRank,
ActivityLog,
CheckEvent,
UserActivityCheckInSummary,
ActivityAgendaCheckInSummary,
ActivityCheckInSummary
],
migrations: [`${isProduct ? '.tmp' : 'migration'}/*.ts`]
};

Expand Down

0 comments on commit 93451bb

Please sign in to comment.