import { AggregateRoot } from './aggregate-root.base' import { AuthorizationId, UserId, AdminUserId, RegionCode, AssessmentConfig, } from '@/domain/value-objects' import { RoleType, AuthorizationStatus, MonthlyTargetType } from '@/domain/enums' import { DomainError } from '@/shared/exceptions' import { CommunityAuthorizedEvent, CommunityAuthRequestedEvent, AuthProvinceCompanyRequestedEvent, AuthCityCompanyRequestedEvent, AuthProvinceCompanyGrantedEvent, AuthCityCompanyGrantedEvent, ProvinceCompanyAuthorizedEvent, CityCompanyAuthorizedEvent, BenefitActivatedEvent, BenefitDeactivatedEvent, RoleAuthorizedEvent, RoleRevokedEvent, PercentageCheckExemptedEvent, } from '@/domain/events' export interface AuthorizationRoleProps { authorizationId: AuthorizationId userId: UserId roleType: RoleType regionCode: RegionCode regionName: string status: AuthorizationStatus displayTitle: string authorizedAt: Date | null authorizedBy: AdminUserId | null revokedAt: Date | null revokedBy: AdminUserId | null revokeReason: string | null assessmentConfig: AssessmentConfig requireLocalPercentage: number exemptFromPercentageCheck: boolean benefitActive: boolean benefitActivatedAt: Date | null benefitDeactivatedAt: Date | null currentMonthIndex: number createdAt: Date updatedAt: Date } export class AuthorizationRole extends AggregateRoot { private _authorizationId: AuthorizationId private _userId: UserId private _roleType: RoleType private _regionCode: RegionCode private _regionName: string private _status: AuthorizationStatus private _displayTitle: string // 授权信息 private _authorizedAt: Date | null private _authorizedBy: AdminUserId | null private _revokedAt: Date | null private _revokedBy: AdminUserId | null private _revokeReason: string | null // 考核配置 private _assessmentConfig: AssessmentConfig // 自有团队占比 private _requireLocalPercentage: number private _exemptFromPercentageCheck: boolean // 权益状态 private _benefitActive: boolean private _benefitActivatedAt: Date | null private _benefitDeactivatedAt: Date | null // 当前考核月份索引 private _currentMonthIndex: number private _createdAt: Date private _updatedAt: Date // Getters get authorizationId(): AuthorizationId { return this._authorizationId } get userId(): UserId { return this._userId } get roleType(): RoleType { return this._roleType } get regionCode(): RegionCode { return this._regionCode } get regionName(): string { return this._regionName } get status(): AuthorizationStatus { return this._status } get displayTitle(): string { return this._displayTitle } get authorizedAt(): Date | null { return this._authorizedAt } get authorizedBy(): AdminUserId | null { return this._authorizedBy } get revokedAt(): Date | null { return this._revokedAt } get revokedBy(): AdminUserId | null { return this._revokedBy } get revokeReason(): string | null { return this._revokeReason } get assessmentConfig(): AssessmentConfig { return this._assessmentConfig } get requireLocalPercentage(): number { return this._requireLocalPercentage } get exemptFromPercentageCheck(): boolean { return this._exemptFromPercentageCheck } get benefitActive(): boolean { return this._benefitActive } get benefitActivatedAt(): Date | null { return this._benefitActivatedAt } get benefitDeactivatedAt(): Date | null { return this._benefitDeactivatedAt } get currentMonthIndex(): number { return this._currentMonthIndex } get createdAt(): Date { return this._createdAt } get updatedAt(): Date { return this._updatedAt } get isActive(): boolean { return this._status === AuthorizationStatus.AUTHORIZED } // 私有构造函数 private constructor(props: AuthorizationRoleProps) { super() this._authorizationId = props.authorizationId this._userId = props.userId this._roleType = props.roleType this._regionCode = props.regionCode this._regionName = props.regionName this._status = props.status this._displayTitle = props.displayTitle this._authorizedAt = props.authorizedAt this._authorizedBy = props.authorizedBy this._revokedAt = props.revokedAt this._revokedBy = props.revokedBy this._revokeReason = props.revokeReason this._assessmentConfig = props.assessmentConfig this._requireLocalPercentage = props.requireLocalPercentage this._exemptFromPercentageCheck = props.exemptFromPercentageCheck this._benefitActive = props.benefitActive this._benefitActivatedAt = props.benefitActivatedAt this._benefitDeactivatedAt = props.benefitDeactivatedAt this._currentMonthIndex = props.currentMonthIndex this._createdAt = props.createdAt this._updatedAt = props.updatedAt } // 工厂方法 - 从数据库重建 static fromPersistence(props: AuthorizationRoleProps): AuthorizationRole { return new AuthorizationRole(props) } // 工厂方法 - 创建社区授权 static createCommunityAuth(params: { userId: UserId; communityName: string }): AuthorizationRole { const auth = new AuthorizationRole({ authorizationId: AuthorizationId.generate(), userId: params.userId, roleType: RoleType.COMMUNITY, regionCode: RegionCode.create(params.communityName), regionName: params.communityName, status: AuthorizationStatus.PENDING, displayTitle: params.communityName, authorizedAt: null, authorizedBy: null, revokedAt: null, revokedBy: null, revokeReason: null, assessmentConfig: AssessmentConfig.forCommunity(), requireLocalPercentage: 0, exemptFromPercentageCheck: true, benefitActive: false, benefitActivatedAt: null, benefitDeactivatedAt: null, currentMonthIndex: 0, createdAt: new Date(), updatedAt: new Date(), }) auth.addDomainEvent( new CommunityAuthRequestedEvent({ authorizationId: auth.authorizationId.value, userId: params.userId.value, communityName: params.communityName, }), ) return auth } // 工厂方法 - 管理员直接授权社区 static createCommunity(params: { userId: UserId communityName: string adminId: AdminUserId skipAssessment?: boolean }): AuthorizationRole { const skipAssessment = params.skipAssessment ?? false const auth = new AuthorizationRole({ authorizationId: AuthorizationId.generate(), userId: params.userId, roleType: RoleType.COMMUNITY, regionCode: RegionCode.create(params.communityName), regionName: params.communityName, status: AuthorizationStatus.AUTHORIZED, displayTitle: params.communityName, authorizedAt: new Date(), authorizedBy: params.adminId, revokedAt: null, revokedBy: null, revokeReason: null, assessmentConfig: AssessmentConfig.forCommunity(), requireLocalPercentage: 0, exemptFromPercentageCheck: true, benefitActive: skipAssessment, benefitActivatedAt: skipAssessment ? new Date() : null, benefitDeactivatedAt: null, currentMonthIndex: skipAssessment ? 1 : 0, createdAt: new Date(), updatedAt: new Date(), }) auth.addDomainEvent( new CommunityAuthorizedEvent({ authorizationId: auth.authorizationId.value, userId: params.userId.value, communityName: params.communityName, authorizedBy: params.adminId.value, }), ) return auth } // 工厂方法 - 创建授权省公司 static createAuthProvinceCompany(params: { userId: UserId provinceCode: string provinceName: string }): AuthorizationRole { const auth = new AuthorizationRole({ authorizationId: AuthorizationId.generate(), userId: params.userId, roleType: RoleType.AUTH_PROVINCE_COMPANY, regionCode: RegionCode.create(params.provinceCode), regionName: params.provinceName, status: AuthorizationStatus.PENDING, displayTitle: `授权${params.provinceName}`, authorizedAt: null, authorizedBy: null, revokedAt: null, revokedBy: null, revokeReason: null, assessmentConfig: AssessmentConfig.forAuthProvince(), requireLocalPercentage: 5.0, exemptFromPercentageCheck: false, benefitActive: false, benefitActivatedAt: null, benefitDeactivatedAt: null, currentMonthIndex: 0, createdAt: new Date(), updatedAt: new Date(), }) auth.addDomainEvent( new AuthProvinceCompanyRequestedEvent({ authorizationId: auth.authorizationId.value, userId: params.userId.value, provinceCode: params.provinceCode, provinceName: params.provinceName, }), ) return auth } // 工厂方法 - 创建正式省公司 static createProvinceCompany(params: { userId: UserId provinceCode: string provinceName: string adminId: AdminUserId skipAssessment?: boolean }): AuthorizationRole { const skipAssessment = params.skipAssessment ?? false const auth = new AuthorizationRole({ authorizationId: AuthorizationId.generate(), userId: params.userId, roleType: RoleType.PROVINCE_COMPANY, regionCode: RegionCode.create(params.provinceCode), regionName: params.provinceName, status: AuthorizationStatus.AUTHORIZED, displayTitle: params.provinceName, authorizedAt: new Date(), authorizedBy: params.adminId, revokedAt: null, revokedBy: null, revokeReason: null, assessmentConfig: AssessmentConfig.forProvince(), requireLocalPercentage: 0, exemptFromPercentageCheck: true, benefitActive: skipAssessment, benefitActivatedAt: skipAssessment ? new Date() : null, benefitDeactivatedAt: null, currentMonthIndex: skipAssessment ? 1 : 0, createdAt: new Date(), updatedAt: new Date(), }) auth.addDomainEvent( new ProvinceCompanyAuthorizedEvent({ authorizationId: auth.authorizationId.value, userId: params.userId.value, provinceCode: params.provinceCode, provinceName: params.provinceName, authorizedBy: params.adminId.value, }), ) return auth } // 工厂方法 - 创建授权市公司 static createAuthCityCompany(params: { userId: UserId cityCode: string cityName: string }): AuthorizationRole { const auth = new AuthorizationRole({ authorizationId: AuthorizationId.generate(), userId: params.userId, roleType: RoleType.AUTH_CITY_COMPANY, regionCode: RegionCode.create(params.cityCode), regionName: params.cityName, status: AuthorizationStatus.PENDING, displayTitle: `授权${params.cityName}`, authorizedAt: null, authorizedBy: null, revokedAt: null, revokedBy: null, revokeReason: null, assessmentConfig: AssessmentConfig.forAuthCity(), requireLocalPercentage: 5.0, exemptFromPercentageCheck: false, benefitActive: false, benefitActivatedAt: null, benefitDeactivatedAt: null, currentMonthIndex: 0, createdAt: new Date(), updatedAt: new Date(), }) auth.addDomainEvent( new AuthCityCompanyRequestedEvent({ authorizationId: auth.authorizationId.value, userId: params.userId.value, cityCode: params.cityCode, cityName: params.cityName, }), ) return auth } // 工厂方法 - 创建正式市公司 static createCityCompany(params: { userId: UserId cityCode: string cityName: string adminId: AdminUserId skipAssessment?: boolean }): AuthorizationRole { const skipAssessment = params.skipAssessment ?? false const auth = new AuthorizationRole({ authorizationId: AuthorizationId.generate(), userId: params.userId, roleType: RoleType.CITY_COMPANY, regionCode: RegionCode.create(params.cityCode), regionName: params.cityName, status: AuthorizationStatus.AUTHORIZED, displayTitle: params.cityName, authorizedAt: new Date(), authorizedBy: params.adminId, revokedAt: null, revokedBy: null, revokeReason: null, assessmentConfig: AssessmentConfig.forCity(), requireLocalPercentage: 0, exemptFromPercentageCheck: true, benefitActive: skipAssessment, benefitActivatedAt: skipAssessment ? new Date() : null, benefitDeactivatedAt: null, currentMonthIndex: skipAssessment ? 1 : 0, createdAt: new Date(), updatedAt: new Date(), }) auth.addDomainEvent( new CityCompanyAuthorizedEvent({ authorizationId: auth.authorizationId.value, userId: params.userId.value, cityCode: params.cityCode, cityName: params.cityName, authorizedBy: params.adminId.value, }), ) return auth } // 工厂方法 - Admin授权省团队 static createAuthProvinceCompanyByAdmin(params: { userId: UserId provinceCode: string provinceName: string adminId: AdminUserId skipAssessment?: boolean }): AuthorizationRole { const skipAssessment = params.skipAssessment ?? false const auth = new AuthorizationRole({ authorizationId: AuthorizationId.generate(), userId: params.userId, roleType: RoleType.AUTH_PROVINCE_COMPANY, regionCode: RegionCode.create(params.provinceCode), regionName: params.provinceName, status: AuthorizationStatus.AUTHORIZED, displayTitle: `授权${params.provinceName}`, authorizedAt: new Date(), authorizedBy: params.adminId, revokedAt: null, revokedBy: null, revokeReason: null, assessmentConfig: AssessmentConfig.forAuthProvince(), requireLocalPercentage: 5.0, exemptFromPercentageCheck: false, benefitActive: skipAssessment, benefitActivatedAt: skipAssessment ? new Date() : null, benefitDeactivatedAt: null, currentMonthIndex: skipAssessment ? 1 : 0, createdAt: new Date(), updatedAt: new Date(), }) auth.addDomainEvent( new AuthProvinceCompanyGrantedEvent({ authorizationId: auth.authorizationId.value, userId: params.userId.value, provinceCode: params.provinceCode, provinceName: params.provinceName, authorizedBy: params.adminId.value, }), ) return auth } // 工厂方法 - Admin授权市团队 static createAuthCityCompanyByAdmin(params: { userId: UserId cityCode: string cityName: string adminId: AdminUserId skipAssessment?: boolean }): AuthorizationRole { const skipAssessment = params.skipAssessment ?? false const auth = new AuthorizationRole({ authorizationId: AuthorizationId.generate(), userId: params.userId, roleType: RoleType.AUTH_CITY_COMPANY, regionCode: RegionCode.create(params.cityCode), regionName: params.cityName, status: AuthorizationStatus.AUTHORIZED, displayTitle: `授权${params.cityName}`, authorizedAt: new Date(), authorizedBy: params.adminId, revokedAt: null, revokedBy: null, revokeReason: null, assessmentConfig: AssessmentConfig.forAuthCity(), requireLocalPercentage: 5.0, exemptFromPercentageCheck: false, benefitActive: skipAssessment, benefitActivatedAt: skipAssessment ? new Date() : null, benefitDeactivatedAt: null, currentMonthIndex: skipAssessment ? 1 : 0, createdAt: new Date(), updatedAt: new Date(), }) auth.addDomainEvent( new AuthCityCompanyGrantedEvent({ authorizationId: auth.authorizationId.value, userId: params.userId.value, cityCode: params.cityCode, cityName: params.cityName, authorizedBy: params.adminId.value, }), ) return auth } // 核心领域行为 /** * 激活权益(初始考核达标后) */ activateBenefit(): void { if (this._benefitActive) { throw new DomainError('权益已激活') } this._status = AuthorizationStatus.AUTHORIZED this._benefitActive = true this._benefitActivatedAt = new Date() this._currentMonthIndex = 1 this._updatedAt = new Date() this.addDomainEvent( new BenefitActivatedEvent({ authorizationId: this._authorizationId.value, userId: this._userId.value, roleType: this._roleType, regionCode: this._regionCode.value, }), ) } /** * 失效权益(月度考核不达标) */ deactivateBenefit(reason: string): void { if (!this._benefitActive) { return } this._benefitActive = false this._benefitDeactivatedAt = new Date() this._currentMonthIndex = 0 // 重置月份索引 this._updatedAt = new Date() this.addDomainEvent( new BenefitDeactivatedEvent({ authorizationId: this._authorizationId.value, userId: this._userId.value, roleType: this._roleType, reason, }), ) } /** * 管理员授权 */ authorize(adminId: AdminUserId): void { if (this._status === AuthorizationStatus.AUTHORIZED) { throw new DomainError('已授权,无需重复授权') } this._status = AuthorizationStatus.AUTHORIZED this._authorizedAt = new Date() this._authorizedBy = adminId this._updatedAt = new Date() this.addDomainEvent( new RoleAuthorizedEvent({ authorizationId: this._authorizationId.value, userId: this._userId.value, roleType: this._roleType, regionCode: this._regionCode.value, authorizedBy: adminId.value, }), ) } /** * 撤销授权 */ revoke(adminId: AdminUserId, reason: string): void { if (this._status === AuthorizationStatus.REVOKED) { throw new DomainError('已撤销') } this._status = AuthorizationStatus.REVOKED this._revokedAt = new Date() this._revokedBy = adminId this._revokeReason = reason this._benefitActive = false this._benefitDeactivatedAt = new Date() this._updatedAt = new Date() this.addDomainEvent( new RoleRevokedEvent({ authorizationId: this._authorizationId.value, userId: this._userId.value, roleType: this._roleType, regionCode: this._regionCode.value, reason, revokedBy: adminId.value, }), ) } /** * 豁免占比考核 */ exemptLocalPercentageCheck(adminId: AdminUserId): void { this._exemptFromPercentageCheck = true this._updatedAt = new Date() this.addDomainEvent( new PercentageCheckExemptedEvent({ authorizationId: this._authorizationId.value, userId: this._userId.value, exemptedBy: adminId.value, }), ) } /** * 取消豁免占比考核 */ cancelExemptLocalPercentageCheck(): void { this._exemptFromPercentageCheck = false this._updatedAt = new Date() } /** * 递增考核月份 */ incrementMonthIndex(): void { this._currentMonthIndex += 1 this._updatedAt = new Date() } /** * 获取初始考核目标 */ getInitialTarget(): number { return this._assessmentConfig.initialTargetTreeCount } /** * 检查是否需要占比考核 */ needsLocalPercentageCheck(): boolean { return ( !this._exemptFromPercentageCheck && this._requireLocalPercentage > 0 && (this._roleType === RoleType.AUTH_PROVINCE_COMPANY || this._roleType === RoleType.AUTH_CITY_COMPANY) ) } /** * 检查是否需要阶梯考核 */ needsLadderAssessment(): boolean { return this._assessmentConfig.monthlyTargetType === MonthlyTargetType.LADDER } /** * 检查是否需要固定月度考核 */ needsFixedAssessment(): boolean { return this._assessmentConfig.monthlyTargetType === MonthlyTargetType.FIXED } /** * 转换为持久化数据 */ toPersistence(): Record { return { id: this._authorizationId.value, userId: this._userId.accountSequence, accountSequence: this._userId.accountSequence, roleType: this._roleType, regionCode: this._regionCode.value, regionName: this._regionName, status: this._status, displayTitle: this._displayTitle, authorizedAt: this._authorizedAt, authorizedBy: this._authorizedBy?.accountSequence || null, revokedAt: this._revokedAt, revokedBy: this._revokedBy?.accountSequence || null, revokeReason: this._revokeReason, initialTargetTreeCount: this._assessmentConfig.initialTargetTreeCount, monthlyTargetType: this._assessmentConfig.monthlyTargetType, requireLocalPercentage: this._requireLocalPercentage, exemptFromPercentageCheck: this._exemptFromPercentageCheck, benefitActive: this._benefitActive, benefitActivatedAt: this._benefitActivatedAt, benefitDeactivatedAt: this._benefitDeactivatedAt, currentMonthIndex: this._currentMonthIndex, createdAt: this._createdAt, updatedAt: this._updatedAt, } } }