feat(authorization-service): 实现社区权益月度考核及级联激活/停用功能
- 新增 benefitValidUntil、lastAssessmentMonth、monthlyTreesAdded 字段追踪月度考核 - 实现级联激活:当社区权益激活时,自动激活所有上级社区的权益 - 实现级联停用:当月度考核不达标时,级联停用该社区及所有上级社区 - 新增定时任务:每天凌晨3点检查过期社区权益,每月1号凌晨重置月度树数 - 权益有效期为当前月+下月末 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
846915badc
commit
2af44e5854
|
|
@ -0,0 +1,33 @@
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "authorization_roles" ADD COLUMN "benefit_valid_until" TIMESTAMP(3),
|
||||||
|
ADD COLUMN "last_assessment_month" TEXT,
|
||||||
|
ADD COLUMN "monthly_trees_added" INTEGER NOT NULL DEFAULT 0,
|
||||||
|
ALTER COLUMN "user_id" SET DATA TYPE TEXT,
|
||||||
|
ALTER COLUMN "authorized_by" SET DATA TYPE TEXT,
|
||||||
|
ALTER COLUMN "revoked_by" SET DATA TYPE TEXT;
|
||||||
|
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "monthly_assessments" ALTER COLUMN "user_id" SET DATA TYPE TEXT,
|
||||||
|
ALTER COLUMN "bypassed_by" SET DATA TYPE TEXT;
|
||||||
|
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "monthly_bypasses" ALTER COLUMN "user_id" SET DATA TYPE TEXT,
|
||||||
|
ALTER COLUMN "granted_by" SET DATA TYPE TEXT,
|
||||||
|
ALTER COLUMN "approver1_id" SET DATA TYPE TEXT,
|
||||||
|
ALTER COLUMN "approver2_id" SET DATA TYPE TEXT,
|
||||||
|
ALTER COLUMN "approver3_id" SET DATA TYPE TEXT;
|
||||||
|
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "stickman_rankings" ALTER COLUMN "user_id" SET DATA TYPE TEXT;
|
||||||
|
|
||||||
|
-- RenameIndex
|
||||||
|
ALTER INDEX "idx_authorization_roles_account_sequence" RENAME TO "authorization_roles_account_sequence_idx";
|
||||||
|
|
||||||
|
-- RenameIndex
|
||||||
|
ALTER INDEX "idx_monthly_assessments_account_sequence_month" RENAME TO "monthly_assessments_account_sequence_assessment_month_idx";
|
||||||
|
|
||||||
|
-- RenameIndex
|
||||||
|
ALTER INDEX "idx_monthly_bypasses_account_sequence_month" RENAME TO "monthly_bypasses_account_sequence_bypass_month_idx";
|
||||||
|
|
||||||
|
-- RenameIndex
|
||||||
|
ALTER INDEX "idx_stickman_rankings_account_sequence_month" RENAME TO "stickman_rankings_account_sequence_current_month_idx";
|
||||||
|
|
@ -40,6 +40,11 @@ model AuthorizationRole {
|
||||||
benefitActive Boolean @default(false) @map("benefit_active")
|
benefitActive Boolean @default(false) @map("benefit_active")
|
||||||
benefitActivatedAt DateTime? @map("benefit_activated_at")
|
benefitActivatedAt DateTime? @map("benefit_activated_at")
|
||||||
benefitDeactivatedAt DateTime? @map("benefit_deactivated_at")
|
benefitDeactivatedAt DateTime? @map("benefit_deactivated_at")
|
||||||
|
benefitValidUntil DateTime? @map("benefit_valid_until") // 权益有效期截止日期(当前月+下月末)
|
||||||
|
|
||||||
|
// 月度考核追踪
|
||||||
|
lastAssessmentMonth String? @map("last_assessment_month") // 上次考核月份 YYYY-MM
|
||||||
|
monthlyTreesAdded Int @default(0) @map("monthly_trees_added") // 当月新增树数
|
||||||
|
|
||||||
// 当前考核月份索引
|
// 当前考核月份索引
|
||||||
currentMonthIndex Int @default(0) @map("current_month_index")
|
currentMonthIndex Int @default(0) @map("current_month_index")
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import {
|
||||||
} from '@/domain/repositories'
|
} from '@/domain/repositories'
|
||||||
import { AssessmentCalculatorService, ITeamStatisticsRepository } from '@/domain/services'
|
import { AssessmentCalculatorService, ITeamStatisticsRepository } from '@/domain/services'
|
||||||
import { EventPublisherService } from '@/infrastructure/kafka'
|
import { EventPublisherService } from '@/infrastructure/kafka'
|
||||||
import { TEAM_STATISTICS_REPOSITORY } from '@/application/services'
|
import { TEAM_STATISTICS_REPOSITORY, AuthorizationApplicationService } from '@/application/services'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MonthlyAssessmentScheduler {
|
export class MonthlyAssessmentScheduler {
|
||||||
|
|
@ -26,6 +26,7 @@ export class MonthlyAssessmentScheduler {
|
||||||
@Inject(TEAM_STATISTICS_REPOSITORY)
|
@Inject(TEAM_STATISTICS_REPOSITORY)
|
||||||
private readonly statsRepository: ITeamStatisticsRepository,
|
private readonly statsRepository: ITeamStatisticsRepository,
|
||||||
private readonly eventPublisher: EventPublisherService,
|
private readonly eventPublisher: EventPublisherService,
|
||||||
|
private readonly authorizationAppService: AuthorizationApplicationService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -182,4 +183,57 @@ export class MonthlyAssessmentScheduler {
|
||||||
|
|
||||||
return map
|
return map
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每天凌晨3点检查并处理过期的社区权益
|
||||||
|
*
|
||||||
|
* 业务规则:
|
||||||
|
* - 检查所有 benefitValidUntil < 当前时间 且 benefitActive=true 的社区
|
||||||
|
* - 如果当月新增树数 >= 10,续期
|
||||||
|
* - 如果不达标,级联停用该社区及其所有上级社区
|
||||||
|
*/
|
||||||
|
@Cron('0 3 * * *')
|
||||||
|
async processExpiredCommunityBenefits(): Promise<void> {
|
||||||
|
this.logger.log('[processExpiredCommunityBenefits] 开始检查社区权益过期情况...')
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await this.authorizationAppService.processExpiredCommunityBenefits(100)
|
||||||
|
|
||||||
|
this.logger.log(
|
||||||
|
`[processExpiredCommunityBenefits] 处理完成: ` +
|
||||||
|
`已处理=${result.processedCount}, 已续期=${result.renewedCount}, 已停用=${result.deactivatedCount}`,
|
||||||
|
)
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.error('[processExpiredCommunityBenefits] 社区权益过期检查失败', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每月1号凌晨0点重置所有社区的月度新增树数
|
||||||
|
*
|
||||||
|
* 注意:此任务必须在 processExpiredCommunityBenefits 之前执行
|
||||||
|
* 因为要先检查上月的考核情况,再重置计数器
|
||||||
|
*/
|
||||||
|
@Cron('0 0 1 * *')
|
||||||
|
async resetMonthlyTreeCounts(): Promise<void> {
|
||||||
|
this.logger.log('[resetMonthlyTreeCounts] 开始重置月度新增树数...')
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 获取所有激活的社区
|
||||||
|
const activeCommunities = await this.authorizationRepository.findAllActive(RoleType.COMMUNITY)
|
||||||
|
|
||||||
|
let resetCount = 0
|
||||||
|
for (const community of activeCommunities) {
|
||||||
|
if (community.benefitActive && community.monthlyTreesAdded > 0) {
|
||||||
|
community.resetMonthlyTrees()
|
||||||
|
await this.authorizationRepository.save(community)
|
||||||
|
resetCount++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.log(`[resetMonthlyTreeCounts] 重置完成: 已重置 ${resetCount} 个社区的月度计数`)
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.error('[resetMonthlyTreeCounts] 月度树数重置失败', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -859,6 +859,8 @@ export class AuthorizationApplicationService {
|
||||||
/**
|
/**
|
||||||
* 尝试激活授权权益
|
* 尝试激活授权权益
|
||||||
* 仅当权益未激活时执行激活操作
|
* 仅当权益未激活时执行激活操作
|
||||||
|
*
|
||||||
|
* 对于社区权益:需要级联激活推荐链上所有父级社区
|
||||||
*/
|
*/
|
||||||
private async tryActivateBenefit(authorization: AuthorizationRole): Promise<void> {
|
private async tryActivateBenefit(authorization: AuthorizationRole): Promise<void> {
|
||||||
if (authorization.benefitActive) {
|
if (authorization.benefitActive) {
|
||||||
|
|
@ -874,6 +876,232 @@ export class AuthorizationApplicationService {
|
||||||
await this.authorizationRepository.save(authorization)
|
await this.authorizationRepository.save(authorization)
|
||||||
await this.eventPublisher.publishAll(authorization.domainEvents)
|
await this.eventPublisher.publishAll(authorization.domainEvents)
|
||||||
authorization.clearDomainEvents()
|
authorization.clearDomainEvents()
|
||||||
|
|
||||||
|
// 如果是社区权益,需要级联激活上级社区
|
||||||
|
if (authorization.roleType === RoleType.COMMUNITY) {
|
||||||
|
await this.cascadeActivateParentCommunities(authorization.userId.accountSequence)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 级联激活上级社区权益
|
||||||
|
* 当一个社区的权益被激活时,需要同时激活推荐链上所有父级社区的权益
|
||||||
|
*
|
||||||
|
* 业务规则:
|
||||||
|
* - 从当前社区往上找,找到所有已授权但权益未激活的社区
|
||||||
|
* - 将它们的权益都激活
|
||||||
|
* - 总部社区不需要考核,不在此处理
|
||||||
|
*/
|
||||||
|
private async cascadeActivateParentCommunities(accountSequence: string): Promise<void> {
|
||||||
|
this.logger.log(
|
||||||
|
`[cascadeActivateParentCommunities] Starting cascade activation for communities above ${accountSequence}`,
|
||||||
|
)
|
||||||
|
|
||||||
|
// 1. 获取推荐链(不包括当前用户)
|
||||||
|
const ancestorAccountSequences = await this.referralServiceClient.getReferralChain(accountSequence)
|
||||||
|
if (ancestorAccountSequences.length === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 查找推荐链上所有社区授权(包括 benefitActive=false)
|
||||||
|
const ancestorCommunities = await this.authorizationRepository.findCommunityByAccountSequences(
|
||||||
|
ancestorAccountSequences,
|
||||||
|
)
|
||||||
|
|
||||||
|
// 3. 筛选出已授权但权益未激活的社区
|
||||||
|
const inactiveCommunities = ancestorCommunities.filter(
|
||||||
|
(auth) => auth.status === AuthorizationStatus.AUTHORIZED && !auth.benefitActive,
|
||||||
|
)
|
||||||
|
|
||||||
|
if (inactiveCommunities.length === 0) {
|
||||||
|
this.logger.debug('[cascadeActivateParentCommunities] No inactive parent communities to activate')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 激活这些社区的权益
|
||||||
|
for (const community of inactiveCommunities) {
|
||||||
|
this.logger.log(
|
||||||
|
`[cascadeActivateParentCommunities] Cascade activating community benefit: ` +
|
||||||
|
`authorizationId=${community.authorizationId.value}, accountSequence=${community.userId.accountSequence}`,
|
||||||
|
)
|
||||||
|
|
||||||
|
community.activateBenefit()
|
||||||
|
await this.authorizationRepository.save(community)
|
||||||
|
await this.eventPublisher.publishAll(community.domainEvents)
|
||||||
|
community.clearDomainEvents()
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.log(
|
||||||
|
`[cascadeActivateParentCommunities] Cascade activated ${inactiveCommunities.length} parent communities`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 级联停用社区权益
|
||||||
|
* 当一个社区的月度考核失败时,需要停用该社区及其推荐链上所有父级社区的权益
|
||||||
|
*
|
||||||
|
* 业务规则:
|
||||||
|
* - 从当前社区开始,往上找到所有已授权且权益已激活的社区
|
||||||
|
* - 将它们的权益都停用,重新开始10棵树的初始考核
|
||||||
|
* - 总部社区不受影响
|
||||||
|
*
|
||||||
|
* @param accountSequence 月度考核失败的社区的 accountSequence
|
||||||
|
* @param reason 停用原因
|
||||||
|
*/
|
||||||
|
async cascadeDeactivateCommunityBenefits(
|
||||||
|
accountSequence: string,
|
||||||
|
reason: string,
|
||||||
|
): Promise<{ deactivatedCount: number }> {
|
||||||
|
this.logger.log(
|
||||||
|
`[cascadeDeactivateCommunityBenefits] Starting cascade deactivation from ${accountSequence}, reason=${reason}`,
|
||||||
|
)
|
||||||
|
|
||||||
|
// 1. 获取当前社区的授权
|
||||||
|
const currentCommunity = await this.authorizationRepository.findByAccountSequenceAndRoleType(
|
||||||
|
accountSequence,
|
||||||
|
RoleType.COMMUNITY,
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!currentCommunity) {
|
||||||
|
this.logger.warn(`[cascadeDeactivateCommunityBenefits] Community not found for ${accountSequence}`)
|
||||||
|
return { deactivatedCount: 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 收集需要停用的社区列表
|
||||||
|
const communitiesToDeactivate: AuthorizationRole[] = []
|
||||||
|
|
||||||
|
// 如果当前社区权益已激活,加入停用列表
|
||||||
|
if (currentCommunity.benefitActive) {
|
||||||
|
communitiesToDeactivate.push(currentCommunity)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 获取推荐链上的所有父级社区
|
||||||
|
const ancestorAccountSequences = await this.referralServiceClient.getReferralChain(accountSequence)
|
||||||
|
if (ancestorAccountSequences.length > 0) {
|
||||||
|
const ancestorCommunities = await this.authorizationRepository.findCommunityByAccountSequences(
|
||||||
|
ancestorAccountSequences,
|
||||||
|
)
|
||||||
|
|
||||||
|
// 筛选出已授权且权益已激活的社区
|
||||||
|
const activeCommunities = ancestorCommunities.filter(
|
||||||
|
(auth) => auth.status === AuthorizationStatus.AUTHORIZED && auth.benefitActive,
|
||||||
|
)
|
||||||
|
|
||||||
|
communitiesToDeactivate.push(...activeCommunities)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (communitiesToDeactivate.length === 0) {
|
||||||
|
this.logger.debug('[cascadeDeactivateCommunityBenefits] No active communities to deactivate')
|
||||||
|
return { deactivatedCount: 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 停用这些社区的权益
|
||||||
|
for (const community of communitiesToDeactivate) {
|
||||||
|
this.logger.log(
|
||||||
|
`[cascadeDeactivateCommunityBenefits] Deactivating community benefit: ` +
|
||||||
|
`authorizationId=${community.authorizationId.value}, accountSequence=${community.userId.accountSequence}`,
|
||||||
|
)
|
||||||
|
|
||||||
|
community.deactivateBenefit(reason)
|
||||||
|
await this.authorizationRepository.save(community)
|
||||||
|
await this.eventPublisher.publishAll(community.domainEvents)
|
||||||
|
community.clearDomainEvents()
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.log(
|
||||||
|
`[cascadeDeactivateCommunityBenefits] Cascade deactivated ${communitiesToDeactivate.length} communities`,
|
||||||
|
)
|
||||||
|
|
||||||
|
return { deactivatedCount: communitiesToDeactivate.length }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理过期的社区权益
|
||||||
|
* 定时任务调用此方法来检查并处理过期的社区权益
|
||||||
|
*
|
||||||
|
* 业务规则:
|
||||||
|
* - 查找所有 benefitValidUntil < 当前时间 且 benefitActive=true 的社区
|
||||||
|
* - 检查其月度考核(当月新增10棵树)
|
||||||
|
* - 如果达标,续期;如果不达标,级联停用
|
||||||
|
*
|
||||||
|
* @param limit 每次处理的最大数量
|
||||||
|
*/
|
||||||
|
async processExpiredCommunityBenefits(limit = 100): Promise<{
|
||||||
|
processedCount: number
|
||||||
|
renewedCount: number
|
||||||
|
deactivatedCount: number
|
||||||
|
}> {
|
||||||
|
const now = new Date()
|
||||||
|
this.logger.log(`[processExpiredCommunityBenefits] Starting at ${now.toISOString()}, limit=${limit}`)
|
||||||
|
|
||||||
|
// 查找过期但仍激活的社区
|
||||||
|
// 需要在 repository 中添加此查询方法
|
||||||
|
const expiredCommunities = await this.findExpiredActiveCommunities(now, limit)
|
||||||
|
|
||||||
|
if (expiredCommunities.length === 0) {
|
||||||
|
this.logger.debug('[processExpiredCommunityBenefits] No expired communities found')
|
||||||
|
return { processedCount: 0, renewedCount: 0, deactivatedCount: 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
let renewedCount = 0
|
||||||
|
let deactivatedCount = 0
|
||||||
|
|
||||||
|
for (const community of expiredCommunities) {
|
||||||
|
const accountSequence = community.userId.accountSequence
|
||||||
|
|
||||||
|
// 获取团队统计数据,检查月度新增树数
|
||||||
|
const teamStats = await this.statsRepository.findByAccountSequence(accountSequence)
|
||||||
|
const monthlyTreesAdded = community.monthlyTreesAdded
|
||||||
|
|
||||||
|
this.logger.debug(
|
||||||
|
`[processExpiredCommunityBenefits] Checking community ${accountSequence}: ` +
|
||||||
|
`monthlyTreesAdded=${monthlyTreesAdded}, target=10`,
|
||||||
|
)
|
||||||
|
|
||||||
|
if (monthlyTreesAdded >= 10) {
|
||||||
|
// 达标,续期
|
||||||
|
community.renewBenefit(monthlyTreesAdded)
|
||||||
|
await this.authorizationRepository.save(community)
|
||||||
|
renewedCount++
|
||||||
|
|
||||||
|
this.logger.log(
|
||||||
|
`[processExpiredCommunityBenefits] Community ${accountSequence} renewed, ` +
|
||||||
|
`new validUntil=${community.benefitValidUntil?.toISOString()}`,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
// 不达标,级联停用
|
||||||
|
const result = await this.cascadeDeactivateCommunityBenefits(
|
||||||
|
accountSequence,
|
||||||
|
`月度考核不达标:本月新增${monthlyTreesAdded}棵,未达到10棵目标`,
|
||||||
|
)
|
||||||
|
deactivatedCount += result.deactivatedCount
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.log(
|
||||||
|
`[processExpiredCommunityBenefits] Completed: processed=${expiredCommunities.length}, ` +
|
||||||
|
`renewed=${renewedCount}, deactivated=${deactivatedCount}`,
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
processedCount: expiredCommunities.length,
|
||||||
|
renewedCount,
|
||||||
|
deactivatedCount,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查找过期但仍激活的社区
|
||||||
|
* TODO: 后续优化可以移到 repository 层
|
||||||
|
*/
|
||||||
|
private async findExpiredActiveCommunities(now: Date, limit: number): Promise<AuthorizationRole[]> {
|
||||||
|
// 获取所有激活的社区授权
|
||||||
|
const activeCommunities = await this.authorizationRepository.findAllActive(RoleType.COMMUNITY)
|
||||||
|
|
||||||
|
// 筛选出已过期的
|
||||||
|
return activeCommunities
|
||||||
|
.filter((auth) => auth.benefitActive && auth.isBenefitExpired(now))
|
||||||
|
.slice(0, limit)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,9 @@ export interface AuthorizationRoleProps {
|
||||||
benefitActive: boolean
|
benefitActive: boolean
|
||||||
benefitActivatedAt: Date | null
|
benefitActivatedAt: Date | null
|
||||||
benefitDeactivatedAt: Date | null
|
benefitDeactivatedAt: Date | null
|
||||||
|
benefitValidUntil: Date | null // 权益有效期截止日期
|
||||||
|
lastAssessmentMonth: string | null // 上次考核月份 YYYY-MM
|
||||||
|
monthlyTreesAdded: number // 当月新增树数
|
||||||
currentMonthIndex: number
|
currentMonthIndex: number
|
||||||
createdAt: Date
|
createdAt: Date
|
||||||
updatedAt: Date
|
updatedAt: Date
|
||||||
|
|
@ -75,6 +78,11 @@ export class AuthorizationRole extends AggregateRoot {
|
||||||
private _benefitActive: boolean
|
private _benefitActive: boolean
|
||||||
private _benefitActivatedAt: Date | null
|
private _benefitActivatedAt: Date | null
|
||||||
private _benefitDeactivatedAt: Date | null
|
private _benefitDeactivatedAt: Date | null
|
||||||
|
private _benefitValidUntil: Date | null
|
||||||
|
|
||||||
|
// 月度考核追踪
|
||||||
|
private _lastAssessmentMonth: string | null
|
||||||
|
private _monthlyTreesAdded: number
|
||||||
|
|
||||||
// 当前考核月份索引
|
// 当前考核月份索引
|
||||||
private _currentMonthIndex: number
|
private _currentMonthIndex: number
|
||||||
|
|
@ -137,6 +145,15 @@ export class AuthorizationRole extends AggregateRoot {
|
||||||
get benefitDeactivatedAt(): Date | null {
|
get benefitDeactivatedAt(): Date | null {
|
||||||
return this._benefitDeactivatedAt
|
return this._benefitDeactivatedAt
|
||||||
}
|
}
|
||||||
|
get benefitValidUntil(): Date | null {
|
||||||
|
return this._benefitValidUntil
|
||||||
|
}
|
||||||
|
get lastAssessmentMonth(): string | null {
|
||||||
|
return this._lastAssessmentMonth
|
||||||
|
}
|
||||||
|
get monthlyTreesAdded(): number {
|
||||||
|
return this._monthlyTreesAdded
|
||||||
|
}
|
||||||
get currentMonthIndex(): number {
|
get currentMonthIndex(): number {
|
||||||
return this._currentMonthIndex
|
return this._currentMonthIndex
|
||||||
}
|
}
|
||||||
|
|
@ -171,6 +188,9 @@ export class AuthorizationRole extends AggregateRoot {
|
||||||
this._benefitActive = props.benefitActive
|
this._benefitActive = props.benefitActive
|
||||||
this._benefitActivatedAt = props.benefitActivatedAt
|
this._benefitActivatedAt = props.benefitActivatedAt
|
||||||
this._benefitDeactivatedAt = props.benefitDeactivatedAt
|
this._benefitDeactivatedAt = props.benefitDeactivatedAt
|
||||||
|
this._benefitValidUntil = props.benefitValidUntil
|
||||||
|
this._lastAssessmentMonth = props.lastAssessmentMonth
|
||||||
|
this._monthlyTreesAdded = props.monthlyTreesAdded
|
||||||
this._currentMonthIndex = props.currentMonthIndex
|
this._currentMonthIndex = props.currentMonthIndex
|
||||||
this._createdAt = props.createdAt
|
this._createdAt = props.createdAt
|
||||||
this._updatedAt = props.updatedAt
|
this._updatedAt = props.updatedAt
|
||||||
|
|
@ -181,6 +201,32 @@ export class AuthorizationRole extends AggregateRoot {
|
||||||
return new AuthorizationRole(props)
|
return new AuthorizationRole(props)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算权益有效期截止日期
|
||||||
|
* 规则:激活当月 + 下月末
|
||||||
|
* 例如:11月3日激活 -> 12月31日23:59:59
|
||||||
|
*/
|
||||||
|
private static calculateBenefitValidUntil(activatedAt: Date): Date {
|
||||||
|
const year = activatedAt.getFullYear()
|
||||||
|
const month = activatedAt.getMonth() // 0-based
|
||||||
|
|
||||||
|
// 下下个月的第一天的前一天 = 下个月的最后一天
|
||||||
|
// 例如:11月 -> month=10 -> month+2=12 (1月) -> 12月31日
|
||||||
|
const nextNextMonth = month + 2
|
||||||
|
const validUntil = new Date(year, nextNextMonth, 0, 23, 59, 59, 999)
|
||||||
|
|
||||||
|
return validUntil
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前月份字符串 YYYY-MM
|
||||||
|
*/
|
||||||
|
private static getCurrentMonthString(date: Date = new Date()): string {
|
||||||
|
const year = date.getFullYear()
|
||||||
|
const month = (date.getMonth() + 1).toString().padStart(2, '0')
|
||||||
|
return `${year}-${month}`
|
||||||
|
}
|
||||||
|
|
||||||
// 工厂方法 - 创建社区授权
|
// 工厂方法 - 创建社区授权
|
||||||
static createCommunityAuth(params: { userId: UserId; communityName: string }): AuthorizationRole {
|
static createCommunityAuth(params: { userId: UserId; communityName: string }): AuthorizationRole {
|
||||||
const auth = new AuthorizationRole({
|
const auth = new AuthorizationRole({
|
||||||
|
|
@ -202,6 +248,9 @@ export class AuthorizationRole extends AggregateRoot {
|
||||||
benefitActive: false,
|
benefitActive: false,
|
||||||
benefitActivatedAt: null,
|
benefitActivatedAt: null,
|
||||||
benefitDeactivatedAt: null,
|
benefitDeactivatedAt: null,
|
||||||
|
benefitValidUntil: null,
|
||||||
|
lastAssessmentMonth: null,
|
||||||
|
monthlyTreesAdded: 0,
|
||||||
currentMonthIndex: 0,
|
currentMonthIndex: 0,
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
updatedAt: new Date(),
|
updatedAt: new Date(),
|
||||||
|
|
@ -226,6 +275,7 @@ export class AuthorizationRole extends AggregateRoot {
|
||||||
skipAssessment?: boolean
|
skipAssessment?: boolean
|
||||||
}): AuthorizationRole {
|
}): AuthorizationRole {
|
||||||
const skipAssessment = params.skipAssessment ?? false
|
const skipAssessment = params.skipAssessment ?? false
|
||||||
|
const now = new Date()
|
||||||
const auth = new AuthorizationRole({
|
const auth = new AuthorizationRole({
|
||||||
authorizationId: AuthorizationId.generate(),
|
authorizationId: AuthorizationId.generate(),
|
||||||
userId: params.userId,
|
userId: params.userId,
|
||||||
|
|
@ -234,7 +284,7 @@ export class AuthorizationRole extends AggregateRoot {
|
||||||
regionName: params.communityName,
|
regionName: params.communityName,
|
||||||
status: AuthorizationStatus.AUTHORIZED,
|
status: AuthorizationStatus.AUTHORIZED,
|
||||||
displayTitle: params.communityName,
|
displayTitle: params.communityName,
|
||||||
authorizedAt: new Date(),
|
authorizedAt: now,
|
||||||
authorizedBy: params.adminId,
|
authorizedBy: params.adminId,
|
||||||
revokedAt: null,
|
revokedAt: null,
|
||||||
revokedBy: null,
|
revokedBy: null,
|
||||||
|
|
@ -243,11 +293,14 @@ export class AuthorizationRole extends AggregateRoot {
|
||||||
requireLocalPercentage: 0,
|
requireLocalPercentage: 0,
|
||||||
exemptFromPercentageCheck: true,
|
exemptFromPercentageCheck: true,
|
||||||
benefitActive: skipAssessment,
|
benefitActive: skipAssessment,
|
||||||
benefitActivatedAt: skipAssessment ? new Date() : null,
|
benefitActivatedAt: skipAssessment ? now : null,
|
||||||
benefitDeactivatedAt: null,
|
benefitDeactivatedAt: null,
|
||||||
|
benefitValidUntil: skipAssessment ? AuthorizationRole.calculateBenefitValidUntil(now) : null,
|
||||||
|
lastAssessmentMonth: skipAssessment ? AuthorizationRole.getCurrentMonthString(now) : null,
|
||||||
|
monthlyTreesAdded: 0,
|
||||||
currentMonthIndex: skipAssessment ? 1 : 0,
|
currentMonthIndex: skipAssessment ? 1 : 0,
|
||||||
createdAt: new Date(),
|
createdAt: now,
|
||||||
updatedAt: new Date(),
|
updatedAt: now,
|
||||||
})
|
})
|
||||||
|
|
||||||
auth.addDomainEvent(
|
auth.addDomainEvent(
|
||||||
|
|
@ -268,6 +321,7 @@ export class AuthorizationRole extends AggregateRoot {
|
||||||
provinceCode: string
|
provinceCode: string
|
||||||
provinceName: string
|
provinceName: string
|
||||||
}): AuthorizationRole {
|
}): AuthorizationRole {
|
||||||
|
const now = new Date()
|
||||||
const auth = new AuthorizationRole({
|
const auth = new AuthorizationRole({
|
||||||
authorizationId: AuthorizationId.generate(),
|
authorizationId: AuthorizationId.generate(),
|
||||||
userId: params.userId,
|
userId: params.userId,
|
||||||
|
|
@ -287,9 +341,12 @@ export class AuthorizationRole extends AggregateRoot {
|
||||||
benefitActive: false,
|
benefitActive: false,
|
||||||
benefitActivatedAt: null,
|
benefitActivatedAt: null,
|
||||||
benefitDeactivatedAt: null,
|
benefitDeactivatedAt: null,
|
||||||
|
benefitValidUntil: null,
|
||||||
|
lastAssessmentMonth: null,
|
||||||
|
monthlyTreesAdded: 0,
|
||||||
currentMonthIndex: 0,
|
currentMonthIndex: 0,
|
||||||
createdAt: new Date(),
|
createdAt: now,
|
||||||
updatedAt: new Date(),
|
updatedAt: now,
|
||||||
})
|
})
|
||||||
|
|
||||||
auth.addDomainEvent(
|
auth.addDomainEvent(
|
||||||
|
|
@ -313,6 +370,7 @@ export class AuthorizationRole extends AggregateRoot {
|
||||||
skipAssessment?: boolean
|
skipAssessment?: boolean
|
||||||
}): AuthorizationRole {
|
}): AuthorizationRole {
|
||||||
const skipAssessment = params.skipAssessment ?? false
|
const skipAssessment = params.skipAssessment ?? false
|
||||||
|
const now = new Date()
|
||||||
const auth = new AuthorizationRole({
|
const auth = new AuthorizationRole({
|
||||||
authorizationId: AuthorizationId.generate(),
|
authorizationId: AuthorizationId.generate(),
|
||||||
userId: params.userId,
|
userId: params.userId,
|
||||||
|
|
@ -321,7 +379,7 @@ export class AuthorizationRole extends AggregateRoot {
|
||||||
regionName: params.provinceName,
|
regionName: params.provinceName,
|
||||||
status: AuthorizationStatus.AUTHORIZED,
|
status: AuthorizationStatus.AUTHORIZED,
|
||||||
displayTitle: params.provinceName,
|
displayTitle: params.provinceName,
|
||||||
authorizedAt: new Date(),
|
authorizedAt: now,
|
||||||
authorizedBy: params.adminId,
|
authorizedBy: params.adminId,
|
||||||
revokedAt: null,
|
revokedAt: null,
|
||||||
revokedBy: null,
|
revokedBy: null,
|
||||||
|
|
@ -330,11 +388,14 @@ export class AuthorizationRole extends AggregateRoot {
|
||||||
requireLocalPercentage: 0,
|
requireLocalPercentage: 0,
|
||||||
exemptFromPercentageCheck: true,
|
exemptFromPercentageCheck: true,
|
||||||
benefitActive: skipAssessment,
|
benefitActive: skipAssessment,
|
||||||
benefitActivatedAt: skipAssessment ? new Date() : null,
|
benefitActivatedAt: skipAssessment ? now : null,
|
||||||
benefitDeactivatedAt: null,
|
benefitDeactivatedAt: null,
|
||||||
|
benefitValidUntil: skipAssessment ? AuthorizationRole.calculateBenefitValidUntil(now) : null,
|
||||||
|
lastAssessmentMonth: skipAssessment ? AuthorizationRole.getCurrentMonthString(now) : null,
|
||||||
|
monthlyTreesAdded: 0,
|
||||||
currentMonthIndex: skipAssessment ? 1 : 0,
|
currentMonthIndex: skipAssessment ? 1 : 0,
|
||||||
createdAt: new Date(),
|
createdAt: now,
|
||||||
updatedAt: new Date(),
|
updatedAt: now,
|
||||||
})
|
})
|
||||||
|
|
||||||
auth.addDomainEvent(
|
auth.addDomainEvent(
|
||||||
|
|
@ -356,6 +417,7 @@ export class AuthorizationRole extends AggregateRoot {
|
||||||
cityCode: string
|
cityCode: string
|
||||||
cityName: string
|
cityName: string
|
||||||
}): AuthorizationRole {
|
}): AuthorizationRole {
|
||||||
|
const now = new Date()
|
||||||
const auth = new AuthorizationRole({
|
const auth = new AuthorizationRole({
|
||||||
authorizationId: AuthorizationId.generate(),
|
authorizationId: AuthorizationId.generate(),
|
||||||
userId: params.userId,
|
userId: params.userId,
|
||||||
|
|
@ -375,9 +437,12 @@ export class AuthorizationRole extends AggregateRoot {
|
||||||
benefitActive: false,
|
benefitActive: false,
|
||||||
benefitActivatedAt: null,
|
benefitActivatedAt: null,
|
||||||
benefitDeactivatedAt: null,
|
benefitDeactivatedAt: null,
|
||||||
|
benefitValidUntil: null,
|
||||||
|
lastAssessmentMonth: null,
|
||||||
|
monthlyTreesAdded: 0,
|
||||||
currentMonthIndex: 0,
|
currentMonthIndex: 0,
|
||||||
createdAt: new Date(),
|
createdAt: now,
|
||||||
updatedAt: new Date(),
|
updatedAt: now,
|
||||||
})
|
})
|
||||||
|
|
||||||
auth.addDomainEvent(
|
auth.addDomainEvent(
|
||||||
|
|
@ -401,6 +466,7 @@ export class AuthorizationRole extends AggregateRoot {
|
||||||
skipAssessment?: boolean
|
skipAssessment?: boolean
|
||||||
}): AuthorizationRole {
|
}): AuthorizationRole {
|
||||||
const skipAssessment = params.skipAssessment ?? false
|
const skipAssessment = params.skipAssessment ?? false
|
||||||
|
const now = new Date()
|
||||||
const auth = new AuthorizationRole({
|
const auth = new AuthorizationRole({
|
||||||
authorizationId: AuthorizationId.generate(),
|
authorizationId: AuthorizationId.generate(),
|
||||||
userId: params.userId,
|
userId: params.userId,
|
||||||
|
|
@ -409,7 +475,7 @@ export class AuthorizationRole extends AggregateRoot {
|
||||||
regionName: params.cityName,
|
regionName: params.cityName,
|
||||||
status: AuthorizationStatus.AUTHORIZED,
|
status: AuthorizationStatus.AUTHORIZED,
|
||||||
displayTitle: params.cityName,
|
displayTitle: params.cityName,
|
||||||
authorizedAt: new Date(),
|
authorizedAt: now,
|
||||||
authorizedBy: params.adminId,
|
authorizedBy: params.adminId,
|
||||||
revokedAt: null,
|
revokedAt: null,
|
||||||
revokedBy: null,
|
revokedBy: null,
|
||||||
|
|
@ -418,11 +484,14 @@ export class AuthorizationRole extends AggregateRoot {
|
||||||
requireLocalPercentage: 0,
|
requireLocalPercentage: 0,
|
||||||
exemptFromPercentageCheck: true,
|
exemptFromPercentageCheck: true,
|
||||||
benefitActive: skipAssessment,
|
benefitActive: skipAssessment,
|
||||||
benefitActivatedAt: skipAssessment ? new Date() : null,
|
benefitActivatedAt: skipAssessment ? now : null,
|
||||||
benefitDeactivatedAt: null,
|
benefitDeactivatedAt: null,
|
||||||
|
benefitValidUntil: skipAssessment ? AuthorizationRole.calculateBenefitValidUntil(now) : null,
|
||||||
|
lastAssessmentMonth: skipAssessment ? AuthorizationRole.getCurrentMonthString(now) : null,
|
||||||
|
monthlyTreesAdded: 0,
|
||||||
currentMonthIndex: skipAssessment ? 1 : 0,
|
currentMonthIndex: skipAssessment ? 1 : 0,
|
||||||
createdAt: new Date(),
|
createdAt: now,
|
||||||
updatedAt: new Date(),
|
updatedAt: now,
|
||||||
})
|
})
|
||||||
|
|
||||||
auth.addDomainEvent(
|
auth.addDomainEvent(
|
||||||
|
|
@ -447,6 +516,7 @@ export class AuthorizationRole extends AggregateRoot {
|
||||||
skipAssessment?: boolean
|
skipAssessment?: boolean
|
||||||
}): AuthorizationRole {
|
}): AuthorizationRole {
|
||||||
const skipAssessment = params.skipAssessment ?? false
|
const skipAssessment = params.skipAssessment ?? false
|
||||||
|
const now = new Date()
|
||||||
const auth = new AuthorizationRole({
|
const auth = new AuthorizationRole({
|
||||||
authorizationId: AuthorizationId.generate(),
|
authorizationId: AuthorizationId.generate(),
|
||||||
userId: params.userId,
|
userId: params.userId,
|
||||||
|
|
@ -455,7 +525,7 @@ export class AuthorizationRole extends AggregateRoot {
|
||||||
regionName: params.provinceName,
|
regionName: params.provinceName,
|
||||||
status: AuthorizationStatus.AUTHORIZED,
|
status: AuthorizationStatus.AUTHORIZED,
|
||||||
displayTitle: `授权${params.provinceName}`,
|
displayTitle: `授权${params.provinceName}`,
|
||||||
authorizedAt: new Date(),
|
authorizedAt: now,
|
||||||
authorizedBy: params.adminId,
|
authorizedBy: params.adminId,
|
||||||
revokedAt: null,
|
revokedAt: null,
|
||||||
revokedBy: null,
|
revokedBy: null,
|
||||||
|
|
@ -464,11 +534,14 @@ export class AuthorizationRole extends AggregateRoot {
|
||||||
requireLocalPercentage: 5.0,
|
requireLocalPercentage: 5.0,
|
||||||
exemptFromPercentageCheck: false,
|
exemptFromPercentageCheck: false,
|
||||||
benefitActive: skipAssessment,
|
benefitActive: skipAssessment,
|
||||||
benefitActivatedAt: skipAssessment ? new Date() : null,
|
benefitActivatedAt: skipAssessment ? now : null,
|
||||||
benefitDeactivatedAt: null,
|
benefitDeactivatedAt: null,
|
||||||
|
benefitValidUntil: skipAssessment ? AuthorizationRole.calculateBenefitValidUntil(now) : null,
|
||||||
|
lastAssessmentMonth: skipAssessment ? AuthorizationRole.getCurrentMonthString(now) : null,
|
||||||
|
monthlyTreesAdded: 0,
|
||||||
currentMonthIndex: skipAssessment ? 1 : 0,
|
currentMonthIndex: skipAssessment ? 1 : 0,
|
||||||
createdAt: new Date(),
|
createdAt: now,
|
||||||
updatedAt: new Date(),
|
updatedAt: now,
|
||||||
})
|
})
|
||||||
|
|
||||||
auth.addDomainEvent(
|
auth.addDomainEvent(
|
||||||
|
|
@ -493,6 +566,7 @@ export class AuthorizationRole extends AggregateRoot {
|
||||||
skipAssessment?: boolean
|
skipAssessment?: boolean
|
||||||
}): AuthorizationRole {
|
}): AuthorizationRole {
|
||||||
const skipAssessment = params.skipAssessment ?? false
|
const skipAssessment = params.skipAssessment ?? false
|
||||||
|
const now = new Date()
|
||||||
const auth = new AuthorizationRole({
|
const auth = new AuthorizationRole({
|
||||||
authorizationId: AuthorizationId.generate(),
|
authorizationId: AuthorizationId.generate(),
|
||||||
userId: params.userId,
|
userId: params.userId,
|
||||||
|
|
@ -501,7 +575,7 @@ export class AuthorizationRole extends AggregateRoot {
|
||||||
regionName: params.cityName,
|
regionName: params.cityName,
|
||||||
status: AuthorizationStatus.AUTHORIZED,
|
status: AuthorizationStatus.AUTHORIZED,
|
||||||
displayTitle: `授权${params.cityName}`,
|
displayTitle: `授权${params.cityName}`,
|
||||||
authorizedAt: new Date(),
|
authorizedAt: now,
|
||||||
authorizedBy: params.adminId,
|
authorizedBy: params.adminId,
|
||||||
revokedAt: null,
|
revokedAt: null,
|
||||||
revokedBy: null,
|
revokedBy: null,
|
||||||
|
|
@ -510,11 +584,14 @@ export class AuthorizationRole extends AggregateRoot {
|
||||||
requireLocalPercentage: 5.0,
|
requireLocalPercentage: 5.0,
|
||||||
exemptFromPercentageCheck: false,
|
exemptFromPercentageCheck: false,
|
||||||
benefitActive: skipAssessment,
|
benefitActive: skipAssessment,
|
||||||
benefitActivatedAt: skipAssessment ? new Date() : null,
|
benefitActivatedAt: skipAssessment ? now : null,
|
||||||
benefitDeactivatedAt: null,
|
benefitDeactivatedAt: null,
|
||||||
|
benefitValidUntil: skipAssessment ? AuthorizationRole.calculateBenefitValidUntil(now) : null,
|
||||||
|
lastAssessmentMonth: skipAssessment ? AuthorizationRole.getCurrentMonthString(now) : null,
|
||||||
|
monthlyTreesAdded: 0,
|
||||||
currentMonthIndex: skipAssessment ? 1 : 0,
|
currentMonthIndex: skipAssessment ? 1 : 0,
|
||||||
createdAt: new Date(),
|
createdAt: now,
|
||||||
updatedAt: new Date(),
|
updatedAt: now,
|
||||||
})
|
})
|
||||||
|
|
||||||
auth.addDomainEvent(
|
auth.addDomainEvent(
|
||||||
|
|
@ -534,17 +611,22 @@ export class AuthorizationRole extends AggregateRoot {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 激活权益(初始考核达标后)
|
* 激活权益(初始考核达标后)
|
||||||
|
* 设置有效期为当前月 + 下月末
|
||||||
*/
|
*/
|
||||||
activateBenefit(): void {
|
activateBenefit(): void {
|
||||||
if (this._benefitActive) {
|
if (this._benefitActive) {
|
||||||
throw new DomainError('权益已激活')
|
throw new DomainError('权益已激活')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const now = new Date()
|
||||||
this._status = AuthorizationStatus.AUTHORIZED
|
this._status = AuthorizationStatus.AUTHORIZED
|
||||||
this._benefitActive = true
|
this._benefitActive = true
|
||||||
this._benefitActivatedAt = new Date()
|
this._benefitActivatedAt = now
|
||||||
|
this._benefitValidUntil = AuthorizationRole.calculateBenefitValidUntil(now)
|
||||||
|
this._lastAssessmentMonth = AuthorizationRole.getCurrentMonthString(now)
|
||||||
|
this._monthlyTreesAdded = 0
|
||||||
this._currentMonthIndex = 1
|
this._currentMonthIndex = 1
|
||||||
this._updatedAt = new Date()
|
this._updatedAt = now
|
||||||
|
|
||||||
this.addDomainEvent(
|
this.addDomainEvent(
|
||||||
new BenefitActivatedEvent({
|
new BenefitActivatedEvent({
|
||||||
|
|
@ -558,16 +640,21 @@ export class AuthorizationRole extends AggregateRoot {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 失效权益(月度考核不达标)
|
* 失效权益(月度考核不达标)
|
||||||
|
* 重置所有考核相关字段
|
||||||
*/
|
*/
|
||||||
deactivateBenefit(reason: string): void {
|
deactivateBenefit(reason: string): void {
|
||||||
if (!this._benefitActive) {
|
if (!this._benefitActive) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const now = new Date()
|
||||||
this._benefitActive = false
|
this._benefitActive = false
|
||||||
this._benefitDeactivatedAt = new Date()
|
this._benefitDeactivatedAt = now
|
||||||
|
this._benefitValidUntil = null
|
||||||
|
this._lastAssessmentMonth = null
|
||||||
|
this._monthlyTreesAdded = 0
|
||||||
this._currentMonthIndex = 0 // 重置月份索引
|
this._currentMonthIndex = 0 // 重置月份索引
|
||||||
this._updatedAt = new Date()
|
this._updatedAt = now
|
||||||
|
|
||||||
this.addDomainEvent(
|
this.addDomainEvent(
|
||||||
new BenefitDeactivatedEvent({
|
new BenefitDeactivatedEvent({
|
||||||
|
|
@ -579,6 +666,48 @@ export class AuthorizationRole extends AggregateRoot {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 续期权益(月度考核达标后)
|
||||||
|
* 延长有效期到下下月末
|
||||||
|
*/
|
||||||
|
renewBenefit(treesAdded: number): void {
|
||||||
|
if (!this._benefitActive) {
|
||||||
|
throw new DomainError('权益未激活,无法续期')
|
||||||
|
}
|
||||||
|
|
||||||
|
const now = new Date()
|
||||||
|
this._benefitValidUntil = AuthorizationRole.calculateBenefitValidUntil(now)
|
||||||
|
this._lastAssessmentMonth = AuthorizationRole.getCurrentMonthString(now)
|
||||||
|
this._monthlyTreesAdded = treesAdded
|
||||||
|
this._updatedAt = now
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 增加月度新增树数
|
||||||
|
*/
|
||||||
|
addMonthlyTrees(treeCount: number): void {
|
||||||
|
this._monthlyTreesAdded += treeCount
|
||||||
|
this._updatedAt = new Date()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置月度新增树数(每月初调用)
|
||||||
|
*/
|
||||||
|
resetMonthlyTrees(): void {
|
||||||
|
this._monthlyTreesAdded = 0
|
||||||
|
this._updatedAt = new Date()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查权益是否已过期
|
||||||
|
*/
|
||||||
|
isBenefitExpired(checkDate: Date = new Date()): boolean {
|
||||||
|
if (!this._benefitActive || !this._benefitValidUntil) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return checkDate > this._benefitValidUntil
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 管理员授权
|
* 管理员授权
|
||||||
*/
|
*/
|
||||||
|
|
@ -721,6 +850,9 @@ export class AuthorizationRole extends AggregateRoot {
|
||||||
benefitActive: this._benefitActive,
|
benefitActive: this._benefitActive,
|
||||||
benefitActivatedAt: this._benefitActivatedAt,
|
benefitActivatedAt: this._benefitActivatedAt,
|
||||||
benefitDeactivatedAt: this._benefitDeactivatedAt,
|
benefitDeactivatedAt: this._benefitDeactivatedAt,
|
||||||
|
benefitValidUntil: this._benefitValidUntil,
|
||||||
|
lastAssessmentMonth: this._lastAssessmentMonth,
|
||||||
|
monthlyTreesAdded: this._monthlyTreesAdded,
|
||||||
currentMonthIndex: this._currentMonthIndex,
|
currentMonthIndex: this._currentMonthIndex,
|
||||||
createdAt: this._createdAt,
|
createdAt: this._createdAt,
|
||||||
updatedAt: this._updatedAt,
|
updatedAt: this._updatedAt,
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,9 @@ export class AuthorizationRoleRepositoryImpl implements IAuthorizationRoleReposi
|
||||||
benefitActive: data.benefitActive,
|
benefitActive: data.benefitActive,
|
||||||
benefitActivatedAt: data.benefitActivatedAt,
|
benefitActivatedAt: data.benefitActivatedAt,
|
||||||
benefitDeactivatedAt: data.benefitDeactivatedAt,
|
benefitDeactivatedAt: data.benefitDeactivatedAt,
|
||||||
|
benefitValidUntil: data.benefitValidUntil,
|
||||||
|
lastAssessmentMonth: data.lastAssessmentMonth,
|
||||||
|
monthlyTreesAdded: data.monthlyTreesAdded,
|
||||||
currentMonthIndex: data.currentMonthIndex,
|
currentMonthIndex: data.currentMonthIndex,
|
||||||
},
|
},
|
||||||
update: {
|
update: {
|
||||||
|
|
@ -58,6 +61,9 @@ export class AuthorizationRoleRepositoryImpl implements IAuthorizationRoleReposi
|
||||||
benefitActive: data.benefitActive,
|
benefitActive: data.benefitActive,
|
||||||
benefitActivatedAt: data.benefitActivatedAt,
|
benefitActivatedAt: data.benefitActivatedAt,
|
||||||
benefitDeactivatedAt: data.benefitDeactivatedAt,
|
benefitDeactivatedAt: data.benefitDeactivatedAt,
|
||||||
|
benefitValidUntil: data.benefitValidUntil,
|
||||||
|
lastAssessmentMonth: data.lastAssessmentMonth,
|
||||||
|
monthlyTreesAdded: data.monthlyTreesAdded,
|
||||||
currentMonthIndex: data.currentMonthIndex,
|
currentMonthIndex: data.currentMonthIndex,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
@ -384,6 +390,9 @@ export class AuthorizationRoleRepositoryImpl implements IAuthorizationRoleReposi
|
||||||
benefitActive: record.benefitActive,
|
benefitActive: record.benefitActive,
|
||||||
benefitActivatedAt: record.benefitActivatedAt,
|
benefitActivatedAt: record.benefitActivatedAt,
|
||||||
benefitDeactivatedAt: record.benefitDeactivatedAt,
|
benefitDeactivatedAt: record.benefitDeactivatedAt,
|
||||||
|
benefitValidUntil: record.benefitValidUntil,
|
||||||
|
lastAssessmentMonth: record.lastAssessmentMonth,
|
||||||
|
monthlyTreesAdded: record.monthlyTreesAdded ?? 0,
|
||||||
currentMonthIndex: record.currentMonthIndex,
|
currentMonthIndex: record.currentMonthIndex,
|
||||||
createdAt: record.createdAt,
|
createdAt: record.createdAt,
|
||||||
updatedAt: record.updatedAt,
|
updatedAt: record.updatedAt,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue