Files
lehuo/apps/api/src/old-items/old-items.controller.ts
T

332 lines
12 KiB
TypeScript

import {
Body,
Controller,
Get,
Inject,
Param,
Patch,
Post,
Query,
Req,
ValidationPipe,
HttpStatus,
} from '@nestjs/common';
import {
API_ERROR_CODES,
PERMISSION_CODES,
type ConfirmUploadResponse,
type CreateUploadIntentResponse,
} from '@lehuo/contracts';
import { RequireSessionChannel } from '../auth/decorators/require-session-channel.decorator';
import { CurrentAuth } from '../common/decorators/current-auth.decorator';
import { ApplicationError } from '../common/application-error';
import { Public } from '../common/decorators/public.decorator';
import { RequirePermissions } from '../common/decorators/require-permissions.decorator';
import type { AuthContext, RequestContext } from '../common/request-context';
import { SessionChannel } from '../generated/prisma/enums';
import { MediaService } from '../participation/media.service';
import {
CreateOldItemDonationDto,
CreateOldItemMediaUploadIntentDto,
CreateOldItemDropOffPointDto,
CreateOldItemNeedDto,
OldItemDonationQueryDto,
OldItemNeedQueryDto,
TransitionOldItemDonationDto,
TransitionOldItemNeedDto,
UpdateOldItemNeedDto,
CreateOldItemInventoryDto,
ImportOldItemInventoryDto,
OldItemInventoryQueryDto,
TransitionOldItemInventoryDto,
ActivateOldItemRewardConfigDto,
AdjustOldItemPointsDto,
IssueOldItemCertificateDto,
OldItemPointAccountQueryDto,
RevokeOldItemCertificateDto,
} from './dto/old-items.dto';
import { OldItemInventoryService } from './old-item-inventory.service';
import { OldItemRewardsService } from './old-item-rewards.service';
import { OldItemsService } from './old-items.service';
const strict = (expectedType: new () => object) =>
new ValidationPipe({
transform: true,
whitelist: true,
forbidNonWhitelisted: true,
expectedType,
});
@Controller('api/v1/old-items')
export class OldItemsController {
constructor(
@Inject(OldItemsService) private readonly service: OldItemsService,
@Inject(MediaService) private readonly media: MediaService,
@Inject(OldItemRewardsService) private readonly rewards: OldItemRewardsService,
) {}
@Get('stats') @Public() stats() {
return this.service.stats();
}
@Get('needs') @Public() needs(@Query(strict(OldItemNeedQueryDto)) q: OldItemNeedQueryDto) {
return this.service.listNeeds(q);
}
@Get('needs/:publicId') @Public() need(@Param('publicId') id: string) {
return this.service.getNeed(id);
}
@Get('drop-off-points') @Public() points() {
return this.service.dropOffPoints();
}
@Post('media/upload-intents') @RequireSessionChannel(SessionChannel.WECHAT) mediaIntent(
@Body(strict(CreateOldItemMediaUploadIntentDto)) input: CreateOldItemMediaUploadIntentDto,
@CurrentAuth() actor: AuthContext,
@Req() req: RequestContext,
): Promise<CreateUploadIntentResponse> {
if (input.businessType !== 'OLD_ITEM_DONATION_IMAGE')
throw new ApplicationError(
API_ERROR_CODES.VALIDATION_ERROR,
'图片业务类型无效',
HttpStatus.BAD_REQUEST,
);
return this.media.createIntent(input, actor, req);
}
@Post('media/:publicId/confirm') @RequireSessionChannel(SessionChannel.WECHAT) confirm(
@Param('publicId') id: string,
@CurrentAuth() actor: AuthContext,
@Req() req: RequestContext,
): Promise<ConfirmUploadResponse> {
return this.media.confirm(id, actor, req);
}
@Post('donations') @RequireSessionChannel(SessionChannel.WECHAT) create(
@Body(strict(CreateOldItemDonationDto)) input: CreateOldItemDonationDto,
@CurrentAuth() actor: AuthContext,
@Req() req: RequestContext,
) {
return this.service.createDonation(input, actor, req);
}
@Get('me/donations') @RequireSessionChannel(SessionChannel.WECHAT) mine(
@Query(strict(OldItemDonationQueryDto)) q: OldItemDonationQueryDto,
@CurrentAuth() actor: AuthContext,
) {
return this.service.myDonations(q, actor);
}
@Get('me/donations/:publicId') @RequireSessionChannel(SessionChannel.WECHAT) mineOne(
@Param('publicId') id: string,
@CurrentAuth() actor: AuthContext,
) {
return this.service.myDonation(id, actor);
}
@Get('me/media/:publicId/download')
@RequireSessionChannel(SessionChannel.WECHAT)
image(
@Param('publicId') id: string,
@CurrentAuth() actor: AuthContext,
@Req() req: RequestContext,
) {
return this.service.imageDownload(id, actor, req);
}
@Get('me/rewards') @RequireSessionChannel(SessionChannel.WECHAT) myRewards(
@CurrentAuth() actor: AuthContext,
) {
return this.rewards.myRewards(actor);
}
@Get('me/certificates/:publicId')
@RequireSessionChannel(SessionChannel.WECHAT)
myCertificate(@Param('publicId') id: string, @CurrentAuth() actor: AuthContext) {
return this.rewards.myCertificate(id, actor);
}
}
@Controller('api/v1/admin/old-items')
@RequireSessionChannel(SessionChannel.ADMIN)
export class AdminOldItemsController {
constructor(
@Inject(OldItemsService) private readonly service: OldItemsService,
@Inject(OldItemInventoryService) private readonly inventory: OldItemInventoryService,
@Inject(OldItemRewardsService) private readonly rewards: OldItemRewardsService,
) {}
@Get('assignees') @RequirePermissions(PERMISSION_CODES.OLD_ITEMS_READ) assignees() {
return this.service.assignees();
}
@Get('media/:publicId/download') @RequirePermissions(PERMISSION_CODES.OLD_ITEMS_READ) image(
@Param('publicId') id: string,
@CurrentAuth() actor: AuthContext,
@Req() req: RequestContext,
) {
return this.service.imageDownload(id, actor, req, true);
}
@Get('donations') @RequirePermissions(PERMISSION_CODES.OLD_ITEMS_READ) donations(
@Query(strict(OldItemDonationQueryDto)) q: OldItemDonationQueryDto,
) {
return this.service.adminDonations(q);
}
@Get('donations/:publicId') @RequirePermissions(PERMISSION_CODES.OLD_ITEMS_READ) donation(
@Param('publicId') id: string,
@CurrentAuth() actor: AuthContext,
@Req() req: RequestContext,
) {
return this.service.adminDonation(id, actor, req);
}
@Post('donations/:publicId/transition')
@RequirePermissions(PERMISSION_CODES.OLD_ITEMS_MANAGE)
transition(
@Param('publicId') id: string,
@Body(strict(TransitionOldItemDonationDto)) input: TransitionOldItemDonationDto,
@CurrentAuth() actor: AuthContext,
@Req() req: RequestContext,
) {
return this.service.transitionDonation(id, input, actor, req);
}
@Get('needs') @RequirePermissions(PERMISSION_CODES.OLD_ITEMS_READ) needs(
@Query(strict(OldItemNeedQueryDto)) q: OldItemNeedQueryDto,
) {
return this.service.listNeeds(q, true);
}
@Get('needs/:publicId') @RequirePermissions(PERMISSION_CODES.OLD_ITEMS_READ) need(
@Param('publicId') id: string,
) {
return this.service.getNeed(id, true);
}
@Post('needs') @RequirePermissions(PERMISSION_CODES.OLD_ITEM_NEEDS_MANAGE) createNeed(
@Body(strict(CreateOldItemNeedDto)) input: CreateOldItemNeedDto,
@CurrentAuth() actor: AuthContext,
@Req() req: RequestContext,
) {
return this.service.createNeed(input, actor, req);
}
@Patch('needs/:publicId') @RequirePermissions(PERMISSION_CODES.OLD_ITEM_NEEDS_MANAGE) updateNeed(
@Param('publicId') id: string,
@Body(strict(UpdateOldItemNeedDto)) input: UpdateOldItemNeedDto,
@CurrentAuth() actor: AuthContext,
@Req() req: RequestContext,
) {
return this.service.updateNeed(id, input, actor, req);
}
@Post('needs/:publicId/transition')
@RequirePermissions(PERMISSION_CODES.OLD_ITEM_NEEDS_MANAGE)
transitionNeed(
@Param('publicId') id: string,
@Body(strict(TransitionOldItemNeedDto)) input: TransitionOldItemNeedDto,
@CurrentAuth() actor: AuthContext,
@Req() req: RequestContext,
) {
return this.service.transitionNeed(id, input, actor, req);
}
@Post('drop-off-points') @RequirePermissions(PERMISSION_CODES.OLD_ITEMS_MANAGE) createPoint(
@Body(strict(CreateOldItemDropOffPointDto)) input: CreateOldItemDropOffPointDto,
@CurrentAuth() actor: AuthContext,
@Req() req: RequestContext,
) {
return this.service.createDropOffPoint(input, actor, req);
}
@Get('inventory')
@RequirePermissions(PERMISSION_CODES.OLD_ITEM_INVENTORY_READ)
inventoryList(@Query(strict(OldItemInventoryQueryDto)) q: OldItemInventoryQueryDto) {
return this.inventory.list(q);
}
@Get('inventory/:publicId')
@RequirePermissions(PERMISSION_CODES.OLD_ITEM_INVENTORY_READ)
inventoryOne(
@Param('publicId') id: string,
@CurrentAuth() actor: AuthContext,
@Req() req: RequestContext,
) {
return this.inventory.get(id, actor, req);
}
@Post('inventory')
@RequirePermissions(PERMISSION_CODES.OLD_ITEM_INVENTORY_MANAGE)
inventoryCreate(
@Body(strict(CreateOldItemInventoryDto)) input: CreateOldItemInventoryDto,
@CurrentAuth() actor: AuthContext,
@Req() req: RequestContext,
) {
return this.inventory.create(input, actor, req);
}
@Post('inventory/import')
@RequirePermissions(PERMISSION_CODES.OLD_ITEM_INVENTORY_IMPORT)
inventoryImport(
@Body(strict(ImportOldItemInventoryDto)) input: ImportOldItemInventoryDto,
@CurrentAuth() actor: AuthContext,
@Req() req: RequestContext,
) {
return this.inventory.import(input, actor, req);
}
@Post('inventory/:publicId/transition')
@RequirePermissions(PERMISSION_CODES.OLD_ITEM_INVENTORY_MANAGE)
inventoryTransition(
@Param('publicId') id: string,
@Body(strict(TransitionOldItemInventoryDto)) input: TransitionOldItemInventoryDto,
@CurrentAuth() actor: AuthContext,
@Req() req: RequestContext,
) {
return this.inventory.transition(id, input, actor, req);
}
@Get('inventory-export/file')
@RequirePermissions(PERMISSION_CODES.OLD_ITEM_INVENTORY_EXPORT)
inventoryExport(
@Query(strict(OldItemInventoryQueryDto)) q: OldItemInventoryQueryDto,
@CurrentAuth() actor: AuthContext,
@Req() req: RequestContext,
) {
return this.inventory.export(q, actor, req);
}
@Get('reward-config')
@RequirePermissions(PERMISSION_CODES.OLD_ITEM_REWARDS_READ)
rewardConfig() {
return this.rewards.config();
}
@Post('reward-config/activate')
@RequirePermissions(PERMISSION_CODES.OLD_ITEM_REWARDS_MANAGE)
activateRewardConfig(
@Body(strict(ActivateOldItemRewardConfigDto)) input: ActivateOldItemRewardConfigDto,
@CurrentAuth() actor: AuthContext,
@Req() req: RequestContext,
) {
return this.rewards.activateConfig(input, actor, req);
}
@Get('reward-accounts')
@RequirePermissions(PERMISSION_CODES.OLD_ITEM_REWARDS_READ)
rewardAccounts(@Query(strict(OldItemPointAccountQueryDto)) q: OldItemPointAccountQueryDto) {
return this.rewards.accounts(q);
}
@Post('reward-accounts/:userPublicId/adjust')
@RequirePermissions(PERMISSION_CODES.OLD_ITEM_REWARDS_MANAGE)
adjustRewardPoints(
@Param('userPublicId') userPublicId: string,
@Body(strict(AdjustOldItemPointsDto)) input: AdjustOldItemPointsDto,
@CurrentAuth() actor: AuthContext,
@Req() req: RequestContext,
) {
return this.rewards.adjust(userPublicId, input, actor, req);
}
@Get('certificates')
@RequirePermissions(PERMISSION_CODES.OLD_ITEM_REWARDS_READ)
certificates(@Query(strict(OldItemPointAccountQueryDto)) q: OldItemPointAccountQueryDto) {
return this.rewards.certificates(q);
}
@Post('donations/:publicId/certificate')
@RequirePermissions(PERMISSION_CODES.OLD_ITEM_REWARDS_MANAGE)
issueCertificate(
@Param('publicId') publicId: string,
@Body(strict(IssueOldItemCertificateDto)) input: IssueOldItemCertificateDto,
@CurrentAuth() actor: AuthContext,
@Req() req: RequestContext,
) {
return this.rewards.issue(publicId, input, actor, req);
}
@Post('certificates/:publicId/revoke')
@RequirePermissions(PERMISSION_CODES.OLD_ITEM_REWARDS_MANAGE)
revokeCertificate(
@Param('publicId') publicId: string,
@Body(strict(RevokeOldItemCertificateDto)) input: RevokeOldItemCertificateDto,
@CurrentAuth() actor: AuthContext,
@Req() req: RequestContext,
) {
return this.rewards.revoke(publicId, input, actor, req);
}
}