332 lines
12 KiB
TypeScript
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);
|
|
}
|
|
}
|